1. added functions header for GraphicsConsoleDxe module.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Console / GraphicsConsoleDxe / GraphicsConsole.c
1 /** @file\r
2   This is the main routine for initializing the Graphics Console support routines.\r
3 Remaining Tasks\r
4   Add all standard Glyphs from UEFI 2.0 Specification\r
5   Implement optimal automatic Mode creation algorithm\r
6   Solve palette issues for mixed graphics and text\r
7   When does this protocol reset the palette?\r
8 \r
9 Copyright (c) 2006 - 2008 Intel Corporation. <BR>\r
10 All rights reserved. This program and the accompanying materials\r
11 are licensed and made available under the terms and conditions of the BSD License\r
12 which accompanies this distribution.  The full text of the license may be found at\r
13 http://opensource.org/licenses/bsd-license.php\r
14 \r
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17 \r
18 **/\r
19 \r
20 #include "GraphicsConsole.h"\r
21 \r
22 /**\r
23   Gets Graphics Console devcie's foreground color and background color.\r
24 \r
25   @param  This                  Protocol instance pointer.\r
26   @param  Foreground            Returned text foreground color.\r
27   @param  Background            Returned text background color.\r
28 \r
29   @retval EFI_SUCCESS           It returned always.\r
30 \r
31 **/\r
32 EFI_STATUS\r
33 GetTextColors (\r
34   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
35   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Foreground,\r
36   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Background\r
37   );\r
38 \r
39 /**\r
40   Draw Unicode string on the Graphice Console device's screen.\r
41 \r
42   @param  This                  Protocol instance pointer.\r
43   @param  UnicodeWeight         One Unicode string to be displayed.\r
44   @param  Count                 The count of Unicode string.\r
45 \r
46   @retval EFI_OUT_OF_RESOURCES  If no memory resource to use.\r
47   @retval EFI_UNSUPPORTED       If no Graphics Output protocol and UGA Draw\r
48                                 protocol exist.\r
49   @retval EFI_SUCCESS           Drawing Unicode string implemented successfully.\r
50 \r
51 **/\r
52 EFI_STATUS\r
53 DrawUnicodeWeightAtCursorN (\r
54   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
55   IN  CHAR16                           *UnicodeWeight,\r
56   IN  UINTN                            Count\r
57   );\r
58 \r
59 /**\r
60   Erase the cursor on the screen.\r
61 \r
62   @param  This                  Protocol instance pointer.\r
63 \r
64   @retval EFI_SUCCESS           The cursor is erased successfully.\r
65 \r
66 **/\r
67 EFI_STATUS\r
68 EraseCursor (\r
69   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This\r
70   );\r
71 \r
72 /**\r
73   Check if the current specific mode supported the user defined resolution\r
74   for the Graphice Console devcie based on Graphics Output Protocol.\r
75 \r
76   If yes, set the graphic devcice's current mode to this specific mode.\r
77   \r
78   @param  GraphicsOutput        Graphics Output Protocol instance pointer.\r
79   @param  HorizontalResolution  User defined horizontal resolution\r
80   @param  VerticalResolution    User defined vertical resolution.\r
81   @param  CurrentModeNumber     Current specific mode to be check.\r
82 \r
83   @retval EFI_SUCCESS       This driver is removed ControllerHandle.\r
84   @retval EFI_UNSUPPORTED   The specific mode is out of range of graphics \r
85                             devcie supported.\r
86   @retval other             The specific mode does not support user defined \r
87                             resolution or failed to set the current mode to the \r
88                             specific mode on graphics device.\r
89 \r
90 **/\r
91 EFI_STATUS\r
92 CheckModeSupported (\r
93   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput,\r
94   IN  UINT32  HorizontalResolution,\r
95   IN  UINT32  VerticalResolution,\r
96   OUT UINT32  *CurrentModeNumber\r
97   );\r
98 \r
99 //\r
100 // Globals\r
101 //\r
102 GRAPHICS_CONSOLE_DEV        mGraphicsConsoleDevTemplate = {\r
103   GRAPHICS_CONSOLE_DEV_SIGNATURE,\r
104   (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL,\r
105   (EFI_UGA_DRAW_PROTOCOL *) NULL,\r
106   {\r
107     GraphicsConsoleConOutReset,\r
108     GraphicsConsoleConOutOutputString,\r
109     GraphicsConsoleConOutTestString,\r
110     GraphicsConsoleConOutQueryMode,\r
111     GraphicsConsoleConOutSetMode,\r
112     GraphicsConsoleConOutSetAttribute,\r
113     GraphicsConsoleConOutClearScreen,\r
114     GraphicsConsoleConOutSetCursorPosition,\r
115     GraphicsConsoleConOutEnableCursor,\r
116     (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL\r
117   },\r
118   {\r
119     0,\r
120     0,\r
121     EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK),\r
122     0,\r
123     0,\r
124     TRUE\r
125   },\r
126   {\r
127     { 80, 25, 0, 0, 0, 0 },  // Mode 0\r
128     { 80, 50, 0, 0, 0, 0 },  // Mode 1\r
129     { 100,31, 0, 0, 0, 0 },  // Mode 2\r
130     {  0,  0, 0, 0, 0, 0 }   // Mode 3\r
131   },\r
132   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
133   (EFI_HII_HANDLE ) 0\r
134 };\r
135 \r
136 EFI_HII_DATABASE_PROTOCOL   *mHiiDatabase;\r
137 EFI_HII_FONT_PROTOCOL       *mHiiFont;\r
138 BOOLEAN                     mFirstAccessFlag = TRUE;\r
139 \r
140 STATIC EFI_GUID             mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, 0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad};\r
141 \r
142 STATIC CHAR16               mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };\r
143 \r
144 STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL        mEfiColors[16] = {\r
145   //\r
146   // B     G     R\r
147   //\r
148   {0x00, 0x00, 0x00, 0x00},  // BLACK\r
149   {0x98, 0x00, 0x00, 0x00},  // BLUE\r
150   {0x00, 0x98, 0x00, 0x00},  // GREEN\r
151   {0x98, 0x98, 0x00, 0x00},  // CYAN\r
152   {0x00, 0x00, 0x98, 0x00},  // RED\r
153   {0x98, 0x00, 0x98, 0x00},  // MAGENTA\r
154   {0x00, 0x98, 0x98, 0x00},  // BROWN\r
155   {0x98, 0x98, 0x98, 0x00},  // LIGHTGRAY\r
156   {0x30, 0x30, 0x30, 0x00},  // DARKGRAY - BRIGHT BLACK\r
157   {0xff, 0x00, 0x00, 0x00},  // LIGHTBLUE - ?\r
158   {0x00, 0xff, 0x00, 0x00},  // LIGHTGREEN - ?\r
159   {0xff, 0xff, 0x00, 0x00},  // LIGHTCYAN\r
160   {0x00, 0x00, 0xff, 0x00},  // LIGHTRED\r
161   {0xff, 0x00, 0xff, 0x00},  // LIGHTMAGENTA\r
162   {0x00, 0xff, 0xff, 0x00},  // LIGHTBROWN\r
163   {0xff, 0xff, 0xff, 0x00}  // WHITE\r
164 };\r
165 \r
166 STATIC EFI_NARROW_GLYPH     mCursorGlyph = {\r
167   0x0000,\r
168   0x00,\r
169   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }\r
170 };\r
171 \r
172 STATIC CHAR16       SpaceStr[] = { NARROW_CHAR, ' ', 0 };\r
173 \r
174 EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {\r
175   GraphicsConsoleControllerDriverSupported,\r
176   GraphicsConsoleControllerDriverStart,\r
177   GraphicsConsoleControllerDriverStop,\r
178   0xa,\r
179   NULL,\r
180   NULL\r
181 };\r
182 \r
183 \r
184 /**\r
185   Test to see if Graphics Console could be supported on the ControllerHandle.\r
186 \r
187   Graphics Console could be supported if Graphics Output Protocol or UGA Draw\r
188   Protocol exists on the ControllerHandle. (UGA Draw Protocol could be shipped\r
189   if PcdUgaConsumeSupport is set to FALSE.)\r
190 \r
191   @param  This                Protocol instance pointer.\r
192   @param  ControllerHandle    Handle of device to test.\r
193   @param  RemainingDevicePath Optional parameter use to pick a specific child\r
194                               device to start.\r
195 \r
196   @retval EFI_SUCCESS         This driver supports this device\r
197   @retval other               This driver does not support this device\r
198 \r
199 **/\r
200 EFI_STATUS\r
201 EFIAPI\r
202 GraphicsConsoleControllerDriverSupported (\r
203   IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
204   IN EFI_HANDLE                     Controller,\r
205   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
206   )\r
207 {\r
208   EFI_STATUS                   Status;\r
209   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
210   EFI_UGA_DRAW_PROTOCOL        *UgaDraw;\r
211   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;\r
212 \r
213   GraphicsOutput = NULL;\r
214   UgaDraw        = NULL;\r
215   //\r
216   // Open the IO Abstraction(s) needed to perform the supported test\r
217   //\r
218   Status = gBS->OpenProtocol (\r
219                   Controller,\r
220                   &gEfiGraphicsOutputProtocolGuid,\r
221                   (VOID **) &GraphicsOutput,\r
222                   This->DriverBindingHandle,\r
223                   Controller,\r
224                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
225                   );\r
226 \r
227   if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
228     //\r
229     // Open Graphics Output Protocol failed, try to open UGA Draw Protocol\r
230     //\r
231     Status = gBS->OpenProtocol (\r
232                     Controller,\r
233                     &gEfiUgaDrawProtocolGuid,\r
234                     (VOID **) &UgaDraw,\r
235                     This->DriverBindingHandle,\r
236                     Controller,\r
237                     EFI_OPEN_PROTOCOL_BY_DRIVER\r
238                     );\r
239   }\r
240   if (EFI_ERROR (Status)) {\r
241     return Status;\r
242   }\r
243 \r
244   //\r
245   // We need to ensure that we do not layer on top of a virtual handle.\r
246   // We need to ensure that the handles produced by the conspliter do not\r
247   // get used.\r
248   //\r
249   Status = gBS->OpenProtocol (\r
250                   Controller,\r
251                   &gEfiDevicePathProtocolGuid,\r
252                   (VOID **) &DevicePath,\r
253                   This->DriverBindingHandle,\r
254                   Controller,\r
255                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
256                   );\r
257   if (!EFI_ERROR (Status)) {\r
258     gBS->CloseProtocol (\r
259           Controller,\r
260           &gEfiDevicePathProtocolGuid,\r
261           This->DriverBindingHandle,\r
262           Controller\r
263           );\r
264   } else {\r
265     goto Error;\r
266   }\r
267 \r
268   //\r
269   // Does Hii Exist?  If not, we aren't ready to run\r
270   //\r
271   Status = EfiLocateHiiProtocol ();\r
272 \r
273   //\r
274   // Close the I/O Abstraction(s) used to perform the supported test\r
275   //\r
276 Error:\r
277   if (GraphicsOutput != NULL) {\r
278     gBS->CloseProtocol (\r
279           Controller,\r
280           &gEfiGraphicsOutputProtocolGuid,\r
281           This->DriverBindingHandle,\r
282           Controller\r
283           );\r
284   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
285     gBS->CloseProtocol (\r
286           Controller,\r
287           &gEfiUgaDrawProtocolGuid,\r
288           This->DriverBindingHandle,\r
289           Controller\r
290           );\r
291   }\r
292   return Status;\r
293 }\r
294 \r
295 \r
296 /**\r
297   Start this driver on ControllerHandle by opening Graphics Output protocol or \r
298   UGA Draw protocol, and installing Simple Text Out protocol on ControllerHandle.\r
299   (UGA Draw protocol could be shkipped if PcdUgaConsumeSupport is set to FALSE.)\r
300   \r
301   @param  This                 Protocol instance pointer.\r
302   @param  ControllerHandle     Handle of device to bind driver to\r
303   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
304                                device to start.\r
305 \r
306   @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
307   @retval other                This driver does not support this device\r
308 \r
309 **/\r
310 EFI_STATUS\r
311 EFIAPI\r
312 GraphicsConsoleControllerDriverStart (\r
313   IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
314   IN EFI_HANDLE                     Controller,\r
315   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
316   )\r
317 {\r
318   EFI_STATUS                           Status;\r
319   GRAPHICS_CONSOLE_DEV                 *Private;\r
320   UINTN                                NarrowFontSize;\r
321   UINT32                               HorizontalResolution;\r
322   UINT32                               VerticalResolution;\r
323   UINT32                               ColorDepth;\r
324   UINT32                               RefreshRate;\r
325   UINTN                                MaxMode;\r
326   UINTN                                Columns;\r
327   UINTN                                Rows;\r
328   UINT32                               ModeNumber;\r
329   EFI_HII_SIMPLE_FONT_PACKAGE_HDR      *SimplifiedFont;\r
330   UINTN                                PackageLength;\r
331   EFI_HII_PACKAGE_LIST_HEADER          *PackageList;\r
332   UINT8                                *Package;\r
333   UINT8                                *Location;\r
334 \r
335   ModeNumber = 0;\r
336 \r
337   //\r
338   // Initialize the Graphics Console device instance\r
339   //\r
340   Private = AllocateCopyPool (\r
341               sizeof (GRAPHICS_CONSOLE_DEV),\r
342               &mGraphicsConsoleDevTemplate\r
343               );\r
344   if (Private == NULL) {\r
345     return EFI_OUT_OF_RESOURCES;\r
346   }\r
347 \r
348   Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode);\r
349 \r
350   Status = gBS->OpenProtocol (\r
351                   Controller,\r
352                   &gEfiGraphicsOutputProtocolGuid,\r
353                   (VOID **) &Private->GraphicsOutput,\r
354                   This->DriverBindingHandle,\r
355                   Controller,\r
356                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
357                   );\r
358 \r
359   if (EFI_ERROR(Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
360     Status = gBS->OpenProtocol (\r
361                     Controller,\r
362                     &gEfiUgaDrawProtocolGuid,\r
363                     (VOID **) &Private->UgaDraw,\r
364                     This->DriverBindingHandle,\r
365                     Controller,\r
366                     EFI_OPEN_PROTOCOL_BY_DRIVER\r
367                     );\r
368   }\r
369 \r
370   if (EFI_ERROR (Status)) {\r
371     goto Error;\r
372   }\r
373 \r
374   NarrowFontSize  = ReturnNarrowFontSize ();\r
375 \r
376   if (mFirstAccessFlag) {\r
377     //\r
378     // Add 4 bytes to the header for entire length for HiiLibPreparePackageList use only.\r
379     // Looks ugly. Might be updated when font tool is ready.\r
380     //\r
381     PackageLength   = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + NarrowFontSize + 4;\r
382     Package = AllocateZeroPool (PackageLength);\r
383     if (Package == NULL) {\r
384       return EFI_OUT_OF_RESOURCES;\r
385     }\r
386     CopyMem (Package, &PackageLength, 4);\r
387     SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR*) (Package + 4);\r
388     SimplifiedFont->Header.Length        = (UINT32) (PackageLength - 4);\r
389     SimplifiedFont->Header.Type          = EFI_HII_PACKAGE_SIMPLE_FONTS;\r
390     SimplifiedFont->NumberOfNarrowGlyphs = (UINT16) (NarrowFontSize / sizeof (EFI_NARROW_GLYPH));\r
391 \r
392     Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1);\r
393     CopyMem (Location, UsStdNarrowGlyphData, NarrowFontSize);\r
394 \r
395     //\r
396     // Add this simplified font package to a package list then install it.\r
397     //\r
398     PackageList = HiiLibPreparePackageList (1, &mFontPackageListGuid, Package);\r
399     Status = mHiiDatabase->NewPackageList (mHiiDatabase, PackageList, NULL, &(Private->HiiHandle));\r
400     ASSERT_EFI_ERROR (Status);\r
401     SafeFreePool (PackageList);\r
402     SafeFreePool (Package);\r
403 \r
404     mFirstAccessFlag = FALSE;\r
405   }\r
406   //\r
407   // If the current mode information can not be retrieved, then attemp to set the default mode\r
408   // of 800x600, 32 bit colot, 60 Hz refresh.\r
409   //\r
410   HorizontalResolution  = 800;\r
411   VerticalResolution    = 600;\r
412 \r
413   if (Private->GraphicsOutput != NULL) {\r
414     //\r
415     // The console is build on top of Graphics Output Protocol, find the mode number\r
416     // for the user-defined mode; if there are multiple video devices,\r
417     // graphic console driver will set all the video devices to the same mode.\r
418     //\r
419     Status = CheckModeSupported (\r
420                  Private->GraphicsOutput,\r
421                  CURRENT_HORIZONTAL_RESOLUTION,\r
422                  CURRENT_VERTICAL_RESOLUTION,\r
423                  &ModeNumber\r
424                  );\r
425     if (!EFI_ERROR(Status)) {\r
426       //\r
427       // Update default mode to current mode\r
428       //\r
429       HorizontalResolution = CURRENT_HORIZONTAL_RESOLUTION;\r
430       VerticalResolution   = CURRENT_VERTICAL_RESOLUTION;\r
431     } else {\r
432       //\r
433       // if not supporting current mode, try 800x600 which is required by UEFI/EFI spec\r
434       //\r
435       Status = CheckModeSupported (\r
436                    Private->GraphicsOutput,\r
437                    800,\r
438                    600,\r
439                    &ModeNumber\r
440                    );\r
441     }\r
442 \r
443     if (EFI_ERROR (Status) || (ModeNumber == Private->GraphicsOutput->Mode->MaxMode)) {\r
444       //\r
445       // Set default mode failed or device don't support default mode, then get the current mode information\r
446       //\r
447       HorizontalResolution = Private->GraphicsOutput->Mode->Info->HorizontalResolution;\r
448       VerticalResolution = Private->GraphicsOutput->Mode->Info->VerticalResolution;\r
449       ModeNumber = Private->GraphicsOutput->Mode->Mode;\r
450     }\r
451   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
452     //\r
453     // At first try to set user-defined resolution\r
454     //\r
455     ColorDepth            = 32;\r
456     RefreshRate           = 60;\r
457     Status = Private->UgaDraw->SetMode (\r
458                                 Private->UgaDraw,\r
459                                 CURRENT_HORIZONTAL_RESOLUTION,\r
460                                 CURRENT_VERTICAL_RESOLUTION,\r
461                                 ColorDepth,\r
462                                 RefreshRate\r
463                                 );\r
464     if (!EFI_ERROR (Status)) {\r
465       HorizontalResolution = CURRENT_HORIZONTAL_RESOLUTION;\r
466       VerticalResolution   = CURRENT_VERTICAL_RESOLUTION;\r
467     } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
468       //\r
469       // Try to set 800*600 which is required by UEFI/EFI spec\r
470       //\r
471       Status = Private->UgaDraw->SetMode (\r
472                                   Private->UgaDraw,\r
473                                   HorizontalResolution,\r
474                                   VerticalResolution,\r
475                                   ColorDepth,\r
476                                   RefreshRate\r
477                                   );\r
478       if (EFI_ERROR (Status)) {\r
479         Status = Private->UgaDraw->GetMode (\r
480                                     Private->UgaDraw,\r
481                                     &HorizontalResolution,\r
482                                     &VerticalResolution,\r
483                                     &ColorDepth,\r
484                                     &RefreshRate\r
485                                     );\r
486         if (EFI_ERROR (Status)) {\r
487           goto Error;\r
488         }\r
489       }\r
490     } else {\r
491       Status = EFI_UNSUPPORTED;\r
492       goto Error;\r
493     }\r
494   }\r
495 \r
496   //\r
497   // Compute the maximum number of text Rows and Columns that this current graphics mode can support\r
498   //\r
499   Columns = HorizontalResolution / EFI_GLYPH_WIDTH;\r
500   Rows    = VerticalResolution / EFI_GLYPH_HEIGHT;\r
501 \r
502   //\r
503   // See if the mode is too small to support the required 80x25 text mode\r
504   //\r
505   if (Columns < 80 || Rows < 25) {\r
506     goto Error;\r
507   }\r
508   //\r
509   // Add Mode #0 that must be 80x25\r
510   //\r
511   MaxMode = 0;\r
512   Private->ModeData[MaxMode].GopWidth   = HorizontalResolution;\r
513   Private->ModeData[MaxMode].GopHeight  = VerticalResolution;\r
514   Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
515   Private->ModeData[MaxMode].DeltaX     = (HorizontalResolution - (80 * EFI_GLYPH_WIDTH)) >> 1;\r
516   Private->ModeData[MaxMode].DeltaY     = (VerticalResolution - (25 * EFI_GLYPH_HEIGHT)) >> 1;\r
517   MaxMode++;\r
518 \r
519   //\r
520   // If it is possible to support Mode #1 - 80x50, than add it as an active mode\r
521   //\r
522   if (Rows >= 50) {\r
523     Private->ModeData[MaxMode].GopWidth   = HorizontalResolution;\r
524     Private->ModeData[MaxMode].GopHeight  = VerticalResolution;\r
525     Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
526     Private->ModeData[MaxMode].DeltaX     = (HorizontalResolution - (80 * EFI_GLYPH_WIDTH)) >> 1;\r
527     Private->ModeData[MaxMode].DeltaY     = (VerticalResolution - (50 * EFI_GLYPH_HEIGHT)) >> 1;\r
528     MaxMode++;\r
529   }\r
530 \r
531   //\r
532   // If it is not to support Mode #1 - 80x50, then skip it\r
533   //\r
534   if (MaxMode < 2) {\r
535     Private->ModeData[MaxMode].Columns    = 0;\r
536     Private->ModeData[MaxMode].Rows       = 0;\r
537     Private->ModeData[MaxMode].GopWidth   = HorizontalResolution;\r
538     Private->ModeData[MaxMode].GopHeight  = VerticalResolution;\r
539     Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
540     Private->ModeData[MaxMode].DeltaX     = 0;\r
541     Private->ModeData[MaxMode].DeltaY     = 0;\r
542     MaxMode++;\r
543   }\r
544 \r
545   //\r
546   // Add Mode #2 that must be 100x31 (graphic mode >= 800x600)\r
547   //\r
548   if (Columns >= 100 && Rows >= 31) {\r
549     Private->ModeData[MaxMode].GopWidth   = HorizontalResolution;\r
550     Private->ModeData[MaxMode].GopHeight  = VerticalResolution;\r
551     Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
552     Private->ModeData[MaxMode].DeltaX     = (HorizontalResolution - (100 * EFI_GLYPH_WIDTH)) >> 1;\r
553     Private->ModeData[MaxMode].DeltaY     = (VerticalResolution - (31 * EFI_GLYPH_HEIGHT)) >> 1;\r
554     MaxMode++;\r
555   }\r
556 \r
557   //\r
558   // Add Mode #3 that uses the entire display for user-defined mode\r
559   //\r
560   if (HorizontalResolution > 800 && VerticalResolution > 600) {\r
561     Private->ModeData[MaxMode].Columns    = HorizontalResolution/EFI_GLYPH_WIDTH;\r
562     Private->ModeData[MaxMode].Rows       = VerticalResolution/EFI_GLYPH_HEIGHT;\r
563     Private->ModeData[MaxMode].GopWidth   = HorizontalResolution;\r
564     Private->ModeData[MaxMode].GopHeight  = VerticalResolution;\r
565     Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
566     Private->ModeData[MaxMode].DeltaX     = (HorizontalResolution % EFI_GLYPH_WIDTH) >> 1;\r
567     Private->ModeData[MaxMode].DeltaY     = (VerticalResolution % EFI_GLYPH_HEIGHT) >> 1;\r
568     MaxMode++;\r
569   }\r
570 \r
571   //\r
572   // Update the maximum number of modes\r
573   //\r
574   Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode;\r
575 \r
576   //\r
577   // Determine the number of text modes that this protocol can support\r
578   //\r
579   Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0);\r
580   if (EFI_ERROR (Status)) {\r
581     goto Error;\r
582   }\r
583 \r
584   DEBUG_CODE_BEGIN ();\r
585     GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r");\r
586   DEBUG_CODE_END ();\r
587 \r
588   //\r
589   // Install protocol interfaces for the Graphics Console device.\r
590   //\r
591   Status = gBS->InstallMultipleProtocolInterfaces (\r
592                   &Controller,\r
593                   &gEfiSimpleTextOutProtocolGuid,\r
594                   &Private->SimpleTextOutput,\r
595                   NULL\r
596                   );\r
597 \r
598 Error:\r
599   if (EFI_ERROR (Status)) {\r
600     //\r
601     // Close the GOP or UGA IO Protocol\r
602     //\r
603     if (Private->GraphicsOutput != NULL) {\r
604       gBS->CloseProtocol (\r
605             Controller,\r
606             &gEfiGraphicsOutputProtocolGuid,\r
607             This->DriverBindingHandle,\r
608             Controller\r
609             );\r
610     } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
611       gBS->CloseProtocol (\r
612             Controller,\r
613             &gEfiUgaDrawProtocolGuid,\r
614             This->DriverBindingHandle,\r
615             Controller\r
616             );\r
617     }\r
618 \r
619     //\r
620     // Free private data\r
621     //\r
622     if (Private != NULL) {\r
623       if (Private->LineBuffer != NULL) {\r
624         FreePool (Private->LineBuffer);\r
625       }\r
626       FreePool (Private);\r
627     }\r
628   }\r
629 \r
630   return Status;\r
631 }\r
632 \r
633 /**\r
634   Stop this driver on ControllerHandle by removing Simple Text Out protocol \r
635   and closing the Graphics Output Protocol or UGA Draw protocol on ControllerHandle.\r
636   (UGA Draw protocol could be shkipped if PcdUgaConsumeSupport is set to FALSE.)\r
637   \r
638 \r
639   @param  This              Protocol instance pointer.\r
640   @param  ControllerHandle  Handle of device to stop driver on\r
641   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
642                             children is zero stop the entire bus driver.\r
643   @param  ChildHandleBuffer List of Child Handles to Stop.\r
644 \r
645   @retval EFI_SUCCESS       This driver is removed ControllerHandle.\r
646   @retval EFI_NOT_STARTED   Simple Text Out protocol could not be found the \r
647                             ControllerHandle.\r
648   @retval other             This driver was not removed from this device.\r
649 \r
650 **/\r
651 EFI_STATUS\r
652 EFIAPI\r
653 GraphicsConsoleControllerDriverStop (\r
654   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
655   IN  EFI_HANDLE                    Controller,\r
656   IN  UINTN                         NumberOfChildren,\r
657   IN  EFI_HANDLE                    *ChildHandleBuffer\r
658   )\r
659 {\r
660   EFI_STATUS                       Status;\r
661   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *SimpleTextOutput;\r
662   GRAPHICS_CONSOLE_DEV             *Private;\r
663 \r
664   Status = gBS->OpenProtocol (\r
665                   Controller,\r
666                   &gEfiSimpleTextOutProtocolGuid,\r
667                   (VOID **) &SimpleTextOutput,\r
668                   This->DriverBindingHandle,\r
669                   Controller,\r
670                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
671                   );\r
672   if (EFI_ERROR (Status)) {\r
673     return EFI_NOT_STARTED;\r
674   }\r
675 \r
676   Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
677 \r
678   Status = gBS->UninstallProtocolInterface (\r
679                   Controller,\r
680                   &gEfiSimpleTextOutProtocolGuid,\r
681                   &Private->SimpleTextOutput\r
682                   );\r
683 \r
684   if (!EFI_ERROR (Status)) {\r
685     //\r
686     // Close the GOP or UGA IO Protocol\r
687     //\r
688     if (Private->GraphicsOutput != NULL) {\r
689       gBS->CloseProtocol (\r
690             Controller,\r
691             &gEfiGraphicsOutputProtocolGuid,\r
692             This->DriverBindingHandle,\r
693             Controller\r
694             );\r
695     } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
696       gBS->CloseProtocol (\r
697             Controller,\r
698             &gEfiUgaDrawProtocolGuid,\r
699             This->DriverBindingHandle,\r
700             Controller\r
701             );\r
702     }\r
703 \r
704     //\r
705     // Remove the font pack\r
706     //\r
707     if (Private->HiiHandle != NULL) {\r
708       HiiLibRemovePackages (Private->HiiHandle);\r
709       mFirstAccessFlag = TRUE;\r
710     }\r
711 \r
712     //\r
713     // Free our instance data\r
714     //\r
715     if (Private != NULL) {\r
716       FreePool (Private->LineBuffer);\r
717       FreePool (Private);\r
718     }\r
719   }\r
720 \r
721   return Status;\r
722 }\r
723 \r
724 /**\r
725   Check if the current specific mode supported the user defined resolution\r
726   for the Graphice Console devcie based on Graphics Output Protocol.\r
727 \r
728   If yes, set the graphic devcice's current mode to this specific mode.\r
729   \r
730   @param  GraphicsOutput        Graphics Output Protocol instance pointer.\r
731   @param  HorizontalResolution  User defined horizontal resolution\r
732   @param  VerticalResolution    User defined vertical resolution.\r
733   @param  CurrentModeNumber     Current specific mode to be check.\r
734 \r
735   @retval EFI_SUCCESS       This driver is removed ControllerHandle.\r
736   @retval EFI_UNSUPPORTED   The specific mode is out of range of graphics \r
737                             devcie supported.\r
738   @retval other             The specific mode does not support user defined \r
739                             resolution or failed to set the current mode to the \r
740                             specific mode on graphics device.\r
741 \r
742 **/\r
743 EFI_STATUS\r
744 CheckModeSupported (\r
745   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput,\r
746   IN  UINT32                    HorizontalResolution,\r
747   IN  UINT32                    VerticalResolution,\r
748   OUT UINT32                    *CurrentModeNumber\r
749   )\r
750 {\r
751   UINT32     ModeNumber;\r
752   EFI_STATUS Status;\r
753   UINTN      SizeOfInfo;\r
754   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
755 \r
756   Status = EFI_SUCCESS;\r
757 \r
758   for (ModeNumber = 0; ModeNumber < GraphicsOutput->Mode->MaxMode; ModeNumber++) {\r
759     Status = GraphicsOutput->QueryMode (\r
760                        GraphicsOutput,\r
761                        ModeNumber,\r
762                        &SizeOfInfo,\r
763                        &Info\r
764                        );\r
765     if (!EFI_ERROR (Status)) {\r
766       if ((Info->HorizontalResolution == HorizontalResolution) &&\r
767           (Info->VerticalResolution == VerticalResolution)) {\r
768         Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);\r
769         if (!EFI_ERROR (Status)) {\r
770           gBS->FreePool (Info);\r
771           break;\r
772         }\r
773       }\r
774       gBS->FreePool (Info);\r
775     }\r
776   }\r
777 \r
778   if (ModeNumber == GraphicsOutput->Mode->MaxMode) {\r
779     Status = EFI_UNSUPPORTED;\r
780   }\r
781 \r
782   *CurrentModeNumber = ModeNumber;\r
783   return Status;\r
784 }\r
785 \r
786 \r
787 /**\r
788   Locate HII Database protocol and HII Font protocol.\r
789 \r
790   @retval  EFI_SUCCESS     HII Database protocol and HII Font protocol \r
791                            are located successfully.\r
792   @return  other           Failed to locate HII Database protocol or \r
793                            HII Font protocol.\r
794 \r
795 **/\r
796 EFI_STATUS\r
797 EfiLocateHiiProtocol (\r
798   VOID\r
799   )\r
800 {\r
801   EFI_HANDLE  Handle;\r
802   UINTN       Size;\r
803   EFI_STATUS  Status;\r
804 \r
805   //\r
806   // There should only be one - so buffer size is this\r
807   //\r
808   Size = sizeof (EFI_HANDLE);\r
809 \r
810   Status = gBS->LocateHandle (\r
811                   ByProtocol,\r
812                   &gEfiHiiDatabaseProtocolGuid,\r
813                   NULL,\r
814                   &Size,\r
815                   (VOID **) &Handle\r
816                   );\r
817 \r
818   if (EFI_ERROR (Status)) {\r
819     return Status;\r
820   }\r
821 \r
822   Status = gBS->HandleProtocol (\r
823                   Handle,\r
824                   &gEfiHiiDatabaseProtocolGuid,\r
825                   (VOID **) &mHiiDatabase\r
826                   );\r
827 \r
828   if (EFI_ERROR (Status)) {\r
829     return Status;\r
830   }\r
831 \r
832   Status = gBS->HandleProtocol (\r
833                   Handle,\r
834                   &gEfiHiiFontProtocolGuid,\r
835                   (VOID **) &mHiiFont\r
836                   );\r
837   return Status;\r
838 }\r
839 \r
840 //\r
841 // Body of the STO functions\r
842 //\r
843 \r
844 /**\r
845   Reset the text output device hardware and optionaly run diagnostics.\r
846   \r
847   Implements SIMPLE_TEXT_OUTPUT.Reset().\r
848   If ExtendeVerification is TRUE, then perform dependent Graphics Console\r
849   device reset, and set display mode to mode 0.\r
850   If ExtendedVerification is FALSE, only set display mode to mode 0.\r
851 \r
852   @param  This                  Protocol instance pointer.\r
853   @param  ExtendedVerification  Indicates that the driver may perform a more\r
854                                 exhaustive verification operation of the device\r
855                                 during reset.\r
856 \r
857   @retval EFI_SUCCESS          The text output device was reset.\r
858   @retval EFI_DEVICE_ERROR     The text output device is not functioning correctly and\r
859                                could not be reset.\r
860 \r
861 **/\r
862 EFI_STATUS\r
863 EFIAPI\r
864 GraphicsConsoleConOutReset (\r
865   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
866   IN  BOOLEAN                          ExtendedVerification\r
867   )\r
868 {\r
869   This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));\r
870   return This->SetMode (This, 0);\r
871 }\r
872 \r
873 \r
874 /**\r
875   Write a Unicode string to the output device.\r
876 \r
877   Implements SIMPLE_TEXT_OUTPUT.OutputString(). \r
878   The Unicode string will be converted to Glyphs and will be\r
879   sent to the Graphics Console.\r
880 \r
881   @param  This                    Protocol instance pointer.\r
882   @param  WString                 The NULL-terminated Unicode string to be displayed\r
883                                   on the output device(s). All output devices must\r
884                                   also support the Unicode drawing defined in this file.\r
885 \r
886   @retval EFI_SUCCESS             The string was output to the device.\r
887   @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output\r
888                                   the text.\r
889   @retval EFI_UNSUPPORTED         The output device's mode is not currently in a\r
890                                   defined text mode.\r
891   @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the\r
892                                   characters in the Unicode string could not be\r
893                                   rendered and were skipped.\r
894 \r
895 **/\r
896 EFI_STATUS\r
897 EFIAPI\r
898 GraphicsConsoleConOutOutputString (\r
899   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
900   IN  CHAR16                           *WString\r
901   )\r
902 {\r
903   GRAPHICS_CONSOLE_DEV  *Private;\r
904   EFI_GRAPHICS_OUTPUT_PROTOCOL   *GraphicsOutput;\r
905   EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
906   INTN                  Mode;\r
907   UINTN                 MaxColumn;\r
908   UINTN                 MaxRow;\r
909   UINTN                 Width;\r
910   UINTN                 Height;\r
911   UINTN                 Delta;\r
912   EFI_STATUS            Status;\r
913   BOOLEAN               Warning;\r
914   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Foreground;\r
915   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Background;\r
916   UINTN                 DeltaX;\r
917   UINTN                 DeltaY;\r
918   UINTN                 Count;\r
919   UINTN                 Index;\r
920   INT32                 OriginAttribute;\r
921   EFI_TPL               OldTpl;\r
922 \r
923   Status = EFI_SUCCESS;\r
924 \r
925   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
926   //\r
927   // Current mode\r
928   //\r
929   Mode      = This->Mode->Mode;\r
930   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
931   GraphicsOutput = Private->GraphicsOutput;\r
932   UgaDraw   = Private->UgaDraw;\r
933 \r
934   MaxColumn = Private->ModeData[Mode].Columns;\r
935   MaxRow    = Private->ModeData[Mode].Rows;\r
936   DeltaX    = Private->ModeData[Mode].DeltaX;\r
937   DeltaY    = Private->ModeData[Mode].DeltaY;\r
938   Width     = MaxColumn * EFI_GLYPH_WIDTH;\r
939   Height    = (MaxRow - 1) * EFI_GLYPH_HEIGHT;\r
940   Delta     = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
941 \r
942   //\r
943   // The Attributes won't change when during the time OutputString is called\r
944   //\r
945   GetTextColors (This, &Foreground, &Background);\r
946 \r
947   EraseCursor (This);\r
948 \r
949   Warning = FALSE;\r
950 \r
951   //\r
952   // Backup attribute\r
953   //\r
954   OriginAttribute = This->Mode->Attribute;\r
955 \r
956   while (*WString != L'\0') {\r
957 \r
958     if (*WString == CHAR_BACKSPACE) {\r
959       //\r
960       // If the cursor is at the left edge of the display, then move the cursor\r
961       // one row up.\r
962       //\r
963       if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) {\r
964         This->Mode->CursorRow--;\r
965         This->Mode->CursorColumn = (INT32) (MaxColumn - 1);\r
966         This->OutputString (This, SpaceStr);\r
967         EraseCursor (This);\r
968         This->Mode->CursorRow--;\r
969         This->Mode->CursorColumn = (INT32) (MaxColumn - 1);\r
970       } else if (This->Mode->CursorColumn > 0) {\r
971         //\r
972         // If the cursor is not at the left edge of the display, then move the cursor\r
973         // left one column.\r
974         //\r
975         This->Mode->CursorColumn--;\r
976         This->OutputString (This, SpaceStr);\r
977         EraseCursor (This);\r
978         This->Mode->CursorColumn--;\r
979       }\r
980 \r
981       WString++;\r
982 \r
983     } else if (*WString == CHAR_LINEFEED) {\r
984       //\r
985       // If the cursor is at the bottom of the display, then scroll the display one\r
986       // row, and do not update the cursor position. Otherwise, move the cursor\r
987       // down one row.\r
988       //\r
989       if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) {\r
990         if (GraphicsOutput != NULL) {\r
991           //\r
992           // Scroll Screen Up One Row\r
993           //\r
994           GraphicsOutput->Blt (\r
995                     GraphicsOutput,\r
996                     NULL,\r
997                     EfiBltVideoToVideo,\r
998                     DeltaX,\r
999                     DeltaY + EFI_GLYPH_HEIGHT,\r
1000                     DeltaX,\r
1001                     DeltaY,\r
1002                     Width,\r
1003                     Height,\r
1004                     Delta\r
1005                     );\r
1006 \r
1007           //\r
1008           // Print Blank Line at last line\r
1009           //\r
1010           GraphicsOutput->Blt (\r
1011                     GraphicsOutput,\r
1012                     &Background,\r
1013                     EfiBltVideoFill,\r
1014                     0,\r
1015                     0,\r
1016                     DeltaX,\r
1017                     DeltaY + Height,\r
1018                     Width,\r
1019                     EFI_GLYPH_HEIGHT,\r
1020                     Delta\r
1021                     );\r
1022         } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1023           //\r
1024           // Scroll Screen Up One Row\r
1025           //\r
1026           UgaDraw->Blt (\r
1027                     UgaDraw,\r
1028                     NULL,\r
1029                     EfiUgaVideoToVideo,\r
1030                     DeltaX,\r
1031                     DeltaY + EFI_GLYPH_HEIGHT,\r
1032                     DeltaX,\r
1033                     DeltaY,\r
1034                     Width,\r
1035                     Height,\r
1036                     Delta\r
1037                     );\r
1038 \r
1039           //\r
1040           // Print Blank Line at last line\r
1041           //\r
1042           UgaDraw->Blt (\r
1043                     UgaDraw,\r
1044                     (EFI_UGA_PIXEL *) (UINTN) &Background,\r
1045                     EfiUgaVideoFill,\r
1046                     0,\r
1047                     0,\r
1048                     DeltaX,\r
1049                     DeltaY + Height,\r
1050                     Width,\r
1051                     EFI_GLYPH_HEIGHT,\r
1052                     Delta\r
1053                     );\r
1054         }\r
1055       } else {\r
1056         This->Mode->CursorRow++;\r
1057       }\r
1058 \r
1059       WString++;\r
1060 \r
1061     } else if (*WString == CHAR_CARRIAGE_RETURN) {\r
1062       //\r
1063       // Move the cursor to the beginning of the current row.\r
1064       //\r
1065       This->Mode->CursorColumn = 0;\r
1066       WString++;\r
1067 \r
1068     } else if (*WString == WIDE_CHAR) {\r
1069 \r
1070       This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;\r
1071       WString++;\r
1072 \r
1073     } else if (*WString == NARROW_CHAR) {\r
1074 \r
1075       This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);\r
1076       WString++;\r
1077 \r
1078     } else {\r
1079       //\r
1080       // Print the character at the current cursor position and move the cursor\r
1081       // right one column. If this moves the cursor past the right edge of the\r
1082       // display, then the line should wrap to the beginning of the next line. This\r
1083       // is equivalent to inserting a CR and an LF. Note that if the cursor is at the\r
1084       // bottom of the display, and the line wraps, then the display will be scrolled\r
1085       // one line.\r
1086       // If wide char is going to be displayed, need to display one character at a time\r
1087       // Or, need to know the display length of a certain string.\r
1088       //\r
1089       // Index is used to determine how many character width units (wide = 2, narrow = 1)\r
1090       // Count is used to determine how many characters are used regardless of their attributes\r
1091       //\r
1092       for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {\r
1093         if (WString[Count] == CHAR_NULL) {\r
1094           break;\r
1095         }\r
1096 \r
1097         if (WString[Count] == CHAR_BACKSPACE) {\r
1098           break;\r
1099         }\r
1100 \r
1101         if (WString[Count] == CHAR_LINEFEED) {\r
1102           break;\r
1103         }\r
1104 \r
1105         if (WString[Count] == CHAR_CARRIAGE_RETURN) {\r
1106           break;\r
1107         }\r
1108 \r
1109         if (WString[Count] == WIDE_CHAR) {\r
1110           break;\r
1111         }\r
1112 \r
1113         if (WString[Count] == NARROW_CHAR) {\r
1114           break;\r
1115         }\r
1116         //\r
1117         // Is the wide attribute on?\r
1118         //\r
1119         if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {\r
1120           //\r
1121           // If wide, add one more width unit than normal since we are going to increment at the end of the for loop\r
1122           //\r
1123           Index++;\r
1124           //\r
1125           // This is the end-case where if we are at column 79 and about to print a wide character\r
1126           // We should prevent this from happening because we will wrap inappropriately.  We should\r
1127           // not print this character until the next line.\r
1128           //\r
1129           if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {\r
1130             Index++;\r
1131             break;\r
1132           }\r
1133         }\r
1134       }\r
1135 \r
1136       Status = DrawUnicodeWeightAtCursorN (This, WString, Count);\r
1137       if (EFI_ERROR (Status)) {\r
1138         Warning = TRUE;\r
1139       }\r
1140       //\r
1141       // At the end of line, output carriage return and line feed\r
1142       //\r
1143       WString += Count;\r
1144       This->Mode->CursorColumn += (INT32) Index;\r
1145       if (This->Mode->CursorColumn > (INT32) MaxColumn) {\r
1146         This->Mode->CursorColumn -= 2;\r
1147         This->OutputString (This, SpaceStr);\r
1148       }\r
1149 \r
1150       if (This->Mode->CursorColumn >= (INT32) MaxColumn) {\r
1151         EraseCursor (This);\r
1152         This->OutputString (This, mCrLfString);\r
1153         EraseCursor (This);\r
1154       }\r
1155     }\r
1156   }\r
1157 \r
1158   This->Mode->Attribute = OriginAttribute;\r
1159 \r
1160   EraseCursor (This);\r
1161 \r
1162   if (Warning) {\r
1163     Status = EFI_WARN_UNKNOWN_GLYPH;\r
1164   }\r
1165 \r
1166   gBS->RestoreTPL (OldTpl);\r
1167   return Status;\r
1168 \r
1169 }\r
1170 \r
1171 /**\r
1172   Verifies that all characters in a Unicode string can be output to the \r
1173   target device.\r
1174 \r
1175   Implements SIMPLE_TEXT_OUTPUT.QueryMode().\r
1176   If one of the characters in the *Wstring is neither valid valid Unicode\r
1177   drawing characters, not ASCII code, then this function will return\r
1178   EFI_UNSUPPORTED\r
1179 \r
1180   @param  This    Protocol instance pointer.\r
1181   @param  WString The NULL-terminated Unicode string to be examined for the output\r
1182                   device(s).\r
1183 \r
1184   @retval EFI_SUCCESS      The device(s) are capable of rendering the output string.\r
1185   @retval EFI_UNSUPPORTED  Some of the characters in the Unicode string cannot be\r
1186                            rendered by one or more of the output devices mapped\r
1187                            by the EFI handle.\r
1188 \r
1189 **/\r
1190 EFI_STATUS\r
1191 EFIAPI\r
1192 GraphicsConsoleConOutTestString (\r
1193   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1194   IN  CHAR16                           *WString\r
1195   )\r
1196 {\r
1197   EFI_STATUS            Status;\r
1198   UINT16                Count;\r
1199 \r
1200   EFI_IMAGE_OUTPUT      *Blt;\r
1201 \r
1202   Blt   = NULL;\r
1203   Count = 0;\r
1204 \r
1205   while (WString[Count] != 0) {\r
1206     Status = mHiiFont->GetGlyph (\r
1207                          mHiiFont,\r
1208                          WString[Count],\r
1209                          NULL,\r
1210                          &Blt,\r
1211                          NULL\r
1212                          );\r
1213     SafeFreePool (Blt);\r
1214     Blt = NULL;\r
1215     Count++;\r
1216 \r
1217     if (EFI_ERROR (Status)) {\r
1218       return EFI_UNSUPPORTED;\r
1219     }\r
1220   }\r
1221 \r
1222   return EFI_SUCCESS;\r
1223 }\r
1224 \r
1225 \r
1226 /**\r
1227   Returns information for an available text mode that the output device(s)\r
1228   supports\r
1229 \r
1230   Implements SIMPLE_TEXT_OUTPUT.QueryMode().\r
1231   It returnes information for an available text mode that the Graphics Console supports.\r
1232   In this driver,we only support text mode 80x25, which is defined as mode 0.\r
1233 \r
1234   @param  This                  Protocol instance pointer.\r
1235   @param  ModeNumber            The mode number to return information on.\r
1236   @param  Columns               The returned columns of the requested mode.\r
1237   @param  Rows                  The returned rows of the requested mode.\r
1238 \r
1239   @retval EFI_SUCCESS           The requested mode information is returned.\r
1240   @retval EFI_UNSUPPORTED       The mode number is not valid.\r
1241 \r
1242 **/\r
1243 EFI_STATUS\r
1244 EFIAPI\r
1245 GraphicsConsoleConOutQueryMode (\r
1246   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1247   IN  UINTN                            ModeNumber,\r
1248   OUT UINTN                            *Columns,\r
1249   OUT UINTN                            *Rows\r
1250   )\r
1251 {\r
1252   GRAPHICS_CONSOLE_DEV  *Private;\r
1253   EFI_STATUS            Status;\r
1254   EFI_TPL               OldTpl;\r
1255 \r
1256   if (ModeNumber >= (UINTN) This->Mode->MaxMode) {\r
1257     return EFI_UNSUPPORTED;\r
1258   }\r
1259 \r
1260   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1261   Status = EFI_SUCCESS;\r
1262 \r
1263   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1264 \r
1265   *Columns  = Private->ModeData[ModeNumber].Columns;\r
1266   *Rows     = Private->ModeData[ModeNumber].Rows;\r
1267 \r
1268   if (*Columns <= 0 && *Rows <= 0) {\r
1269     Status = EFI_UNSUPPORTED;\r
1270     goto Done;\r
1271 \r
1272   }\r
1273 \r
1274 Done:\r
1275   gBS->RestoreTPL (OldTpl);\r
1276   return Status;\r
1277 }\r
1278 \r
1279 \r
1280 /**\r
1281   Sets the output device(s) to a specified mode.\r
1282   \r
1283   Implements SIMPLE_TEXT_OUTPUT.SetMode().\r
1284   Set the Graphics Console to a specified mode. In this driver, we only support mode 0.\r
1285 \r
1286   @param  This                  Protocol instance pointer.\r
1287   @param  ModeNumber            The text mode to set.\r
1288 \r
1289   @retval EFI_SUCCESS           The requested text mode is set.\r
1290   @retval EFI_DEVICE_ERROR      The requested text mode cannot be set because of \r
1291                                 Graphics Console device error.\r
1292   @retval EFI_UNSUPPORTED       The text mode number is not valid.\r
1293 \r
1294 **/\r
1295 EFI_STATUS\r
1296 EFIAPI\r
1297 GraphicsConsoleConOutSetMode (\r
1298   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1299   IN  UINTN                            ModeNumber\r
1300   )\r
1301 {\r
1302   EFI_STATUS                      Status;\r
1303   GRAPHICS_CONSOLE_DEV            *Private;\r
1304   GRAPHICS_CONSOLE_MODE_DATA      *ModeData;\r
1305   EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *NewLineBuffer;\r
1306   UINT32                          HorizontalResolution;\r
1307   UINT32                          VerticalResolution;\r
1308   EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;\r
1309   EFI_UGA_DRAW_PROTOCOL           *UgaDraw;\r
1310   UINT32                          ColorDepth;\r
1311   UINT32                          RefreshRate;\r
1312   EFI_TPL                         OldTpl;\r
1313 \r
1314   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1315 \r
1316   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1317   GraphicsOutput = Private->GraphicsOutput;\r
1318   UgaDraw   = Private->UgaDraw;\r
1319   ModeData  = &(Private->ModeData[ModeNumber]);\r
1320 \r
1321   if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {\r
1322     Status = EFI_UNSUPPORTED;\r
1323     goto Done;\r
1324   }\r
1325 \r
1326   //\r
1327   // Make sure the requested mode number is supported\r
1328   //\r
1329   if (ModeNumber >= (UINTN) This->Mode->MaxMode) {\r
1330     Status = EFI_UNSUPPORTED;\r
1331     goto Done;\r
1332   }\r
1333 \r
1334   if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {\r
1335     Status = EFI_UNSUPPORTED;\r
1336     goto Done;\r
1337   }\r
1338   //\r
1339   // Attempt to allocate a line buffer for the requested mode number\r
1340   //\r
1341   NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT);\r
1342 \r
1343   if (NewLineBuffer == NULL) {\r
1344     //\r
1345     // The new line buffer could not be allocated, so return an error.\r
1346     // No changes to the state of the current console have been made, so the current console is still valid\r
1347     //\r
1348     Status = EFI_OUT_OF_RESOURCES;\r
1349     goto Done;\r
1350   }\r
1351   //\r
1352   // If the mode has been set at least one other time, then LineBuffer will not be NULL\r
1353   //\r
1354   if (Private->LineBuffer != NULL) {\r
1355     //\r
1356     // Clear the current text window on the current graphics console\r
1357     //\r
1358     This->ClearScreen (This);\r
1359 \r
1360     //\r
1361     // If the new mode is the same as the old mode, then just return EFI_SUCCESS\r
1362     //\r
1363     if ((INT32) ModeNumber == This->Mode->Mode) {\r
1364       FreePool (NewLineBuffer);\r
1365       Status = EFI_SUCCESS;\r
1366       goto Done;\r
1367     }\r
1368     //\r
1369     // Otherwise, the size of the text console and/or the GOP/UGA mode will be changed,\r
1370     // so erase the cursor, and free the LineBuffer for the current mode\r
1371     //\r
1372     EraseCursor (This);\r
1373 \r
1374     FreePool (Private->LineBuffer);\r
1375   }\r
1376   //\r
1377   // Assign the current line buffer to the newly allocated line buffer\r
1378   //\r
1379   Private->LineBuffer = NewLineBuffer;\r
1380 \r
1381   if (GraphicsOutput != NULL) {\r
1382     if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {\r
1383       //\r
1384       // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode\r
1385       //\r
1386       Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);\r
1387       if (EFI_ERROR (Status)) {\r
1388         //\r
1389         // The mode set operation failed\r
1390         //\r
1391         goto Done;\r
1392       }\r
1393     } else {\r
1394       //\r
1395       // The current graphics mode is correct, so simply clear the entire display\r
1396       //\r
1397       Status = GraphicsOutput->Blt (\r
1398                           GraphicsOutput,\r
1399                           &mEfiColors[0],\r
1400                           EfiBltVideoFill,\r
1401                           0,\r
1402                           0,\r
1403                           0,\r
1404                           0,\r
1405                           ModeData->GopWidth,\r
1406                           ModeData->GopHeight,\r
1407                           0\r
1408                           );\r
1409     }\r
1410   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1411     //\r
1412     // Get the current UGA Draw mode information\r
1413     //\r
1414     Status = UgaDraw->GetMode (\r
1415                         UgaDraw,\r
1416                         &HorizontalResolution,\r
1417                         &VerticalResolution,\r
1418                         &ColorDepth,\r
1419                         &RefreshRate\r
1420                         );\r
1421     if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) {\r
1422       //\r
1423       // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode\r
1424       //\r
1425       Status = UgaDraw->SetMode (\r
1426                           UgaDraw,\r
1427                           ModeData->GopWidth,\r
1428                           ModeData->GopHeight,\r
1429                           32,\r
1430                           60\r
1431                           );\r
1432       if (EFI_ERROR (Status)) {\r
1433         //\r
1434         // The mode set operation failed\r
1435         //\r
1436         goto Done;\r
1437       }\r
1438     } else {\r
1439       //\r
1440       // The current graphics mode is correct, so simply clear the entire display\r
1441       //\r
1442       Status = UgaDraw->Blt (\r
1443                           UgaDraw,\r
1444                           (EFI_UGA_PIXEL *) (UINTN) &mEfiColors[0],\r
1445                           EfiUgaVideoFill,\r
1446                           0,\r
1447                           0,\r
1448                           0,\r
1449                           0,\r
1450                           ModeData->GopWidth,\r
1451                           ModeData->GopHeight,\r
1452                           0\r
1453                           );\r
1454     }\r
1455   }\r
1456 \r
1457   //\r
1458   // The new mode is valid, so commit the mode change\r
1459   //\r
1460   This->Mode->Mode = (INT32) ModeNumber;\r
1461 \r
1462   //\r
1463   // Move the text cursor to the upper left hand corner of the displat and enable it\r
1464   //\r
1465   This->SetCursorPosition (This, 0, 0);\r
1466 \r
1467   Status = EFI_SUCCESS;\r
1468 \r
1469 Done:\r
1470   gBS->RestoreTPL (OldTpl);\r
1471   return Status;\r
1472 }\r
1473 \r
1474 \r
1475 /**\r
1476   Sets the background and foreground colors for the OutputString () and\r
1477   ClearScreen () functions.\r
1478 \r
1479   Implements SIMPLE_TEXT_OUTPUT.SetAttribute().\r
1480 \r
1481   @param  This                  Protocol instance pointer.\r
1482   @param  Attribute             The attribute to set. Bits 0..3 are the foreground\r
1483                                 color, and bits 4..6 are the background color. \r
1484                                 All other bits are undefined and must be zero.\r
1485 \r
1486   @retval EFI_SUCCESS           The requested attribute is set.\r
1487   @retval EFI_DEVICE_ERROR      The requested attribute cannot be set due to Graphics Console port error.\r
1488   @retval EFI_UNSUPPORTED       The attribute requested is not defined.\r
1489 \r
1490 **/\r
1491 EFI_STATUS\r
1492 EFIAPI\r
1493 GraphicsConsoleConOutSetAttribute (\r
1494   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1495   IN  UINTN                            Attribute\r
1496   )\r
1497 {\r
1498   EFI_TPL               OldTpl;\r
1499 \r
1500   if ((Attribute | 0xFF) != 0xFF) {\r
1501     return EFI_UNSUPPORTED;\r
1502   }\r
1503 \r
1504   if ((INT32) Attribute == This->Mode->Attribute) {\r
1505     return EFI_SUCCESS;\r
1506   }\r
1507 \r
1508   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1509 \r
1510   EraseCursor (This);\r
1511 \r
1512   This->Mode->Attribute = (INT32) Attribute;\r
1513 \r
1514   EraseCursor (This);\r
1515 \r
1516   gBS->RestoreTPL (OldTpl);\r
1517 \r
1518   return EFI_SUCCESS;\r
1519 }\r
1520 \r
1521 \r
1522 /**\r
1523   Clears the output device(s) display to the currently selected background \r
1524   color.\r
1525 \r
1526   Implements SIMPLE_TEXT_OUTPUT.ClearScreen().\r
1527 \r
1528   @param  This                  Protocol instance pointer.\r
1529 \r
1530   @retval  EFI_SUCCESS      The operation completed successfully.\r
1531   @retval  EFI_DEVICE_ERROR The device had an error and could not complete the request.\r
1532   @retval  EFI_UNSUPPORTED  The output device is not in a valid text mode.\r
1533 \r
1534 **/\r
1535 EFI_STATUS\r
1536 EFIAPI\r
1537 GraphicsConsoleConOutClearScreen (\r
1538   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This\r
1539   )\r
1540 {\r
1541   EFI_STATUS                    Status;\r
1542   GRAPHICS_CONSOLE_DEV          *Private;\r
1543   GRAPHICS_CONSOLE_MODE_DATA    *ModeData;\r
1544   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;\r
1545   EFI_UGA_DRAW_PROTOCOL         *UgaDraw;\r
1546   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
1547   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
1548   EFI_TPL                       OldTpl;\r
1549 \r
1550   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1551 \r
1552   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1553   GraphicsOutput = Private->GraphicsOutput;\r
1554   UgaDraw   = Private->UgaDraw;\r
1555   ModeData  = &(Private->ModeData[This->Mode->Mode]);\r
1556 \r
1557   GetTextColors (This, &Foreground, &Background);\r
1558   if (GraphicsOutput != NULL) {\r
1559     Status = GraphicsOutput->Blt (\r
1560                         GraphicsOutput,\r
1561                         &Background,\r
1562                         EfiBltVideoFill,\r
1563                         0,\r
1564                         0,\r
1565                         0,\r
1566                         0,\r
1567                         ModeData->GopWidth,\r
1568                         ModeData->GopHeight,\r
1569                         0\r
1570                         );\r
1571   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1572     Status = UgaDraw->Blt (\r
1573                         UgaDraw,\r
1574                         (EFI_UGA_PIXEL *) (UINTN) &Background,\r
1575                         EfiUgaVideoFill,\r
1576                         0,\r
1577                         0,\r
1578                         0,\r
1579                         0,\r
1580                         ModeData->GopWidth,\r
1581                         ModeData->GopHeight,\r
1582                         0\r
1583                         );\r
1584   } else {\r
1585     Status = EFI_UNSUPPORTED;\r
1586   }\r
1587 \r
1588   This->Mode->CursorColumn  = 0;\r
1589   This->Mode->CursorRow     = 0;\r
1590 \r
1591   EraseCursor (This);\r
1592 \r
1593   gBS->RestoreTPL (OldTpl);\r
1594 \r
1595   return Status;\r
1596 }\r
1597 \r
1598 \r
1599 /**\r
1600   Sets the current coordinates of the cursor position.\r
1601 \r
1602   Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().\r
1603 \r
1604   @param  This        Protocol instance pointer.\r
1605   @param  Column      The position to set the cursor to. Must be greater than or\r
1606                       equal to zero and less than the number of columns and rows\r
1607                       by QueryMode ().\r
1608   @param  Row         The position to set the cursor to. Must be greater than or\r
1609                       equal to zero and less than the number of columns and rows\r
1610                       by QueryMode ().\r
1611 \r
1612   @retval EFI_SUCCESS      The operation completed successfully.\r
1613   @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.\r
1614   @retval EFI_UNSUPPORTED  The output device is not in a valid text mode, or the\r
1615                            cursor position is invalid for the current mode.\r
1616 \r
1617 **/\r
1618 EFI_STATUS\r
1619 EFIAPI\r
1620 GraphicsConsoleConOutSetCursorPosition (\r
1621   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1622   IN  UINTN                            Column,\r
1623   IN  UINTN                            Row\r
1624   )\r
1625 {\r
1626   GRAPHICS_CONSOLE_DEV        *Private;\r
1627   GRAPHICS_CONSOLE_MODE_DATA  *ModeData;\r
1628   EFI_STATUS                  Status;\r
1629   EFI_TPL                     OldTpl;\r
1630 \r
1631   Status = EFI_SUCCESS;\r
1632 \r
1633   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1634 \r
1635   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1636   ModeData  = &(Private->ModeData[This->Mode->Mode]);\r
1637 \r
1638   if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {\r
1639     Status = EFI_UNSUPPORTED;\r
1640     goto Done;\r
1641   }\r
1642 \r
1643   if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) {\r
1644     Status = EFI_SUCCESS;\r
1645     goto Done;\r
1646   }\r
1647 \r
1648   EraseCursor (This);\r
1649 \r
1650   This->Mode->CursorColumn  = (INT32) Column;\r
1651   This->Mode->CursorRow     = (INT32) Row;\r
1652 \r
1653   EraseCursor (This);\r
1654 \r
1655 Done:\r
1656   gBS->RestoreTPL (OldTpl);\r
1657 \r
1658   return Status;\r
1659 }\r
1660 \r
1661 \r
1662 /**\r
1663   Makes the cursor visible or invisible.\r
1664 \r
1665   Implements SIMPLE_TEXT_OUTPUT.EnableCursor().\r
1666 \r
1667   @param  This                  Protocol instance pointer.\r
1668   @param  Visible               If TRUE, the cursor is set to be visible, If FALSE,\r
1669                                 the cursor is set to be invisible.\r
1670 \r
1671   @retval EFI_SUCCESS           The operation completed successfully.\r
1672 \r
1673 **/\r
1674 EFI_STATUS\r
1675 EFIAPI\r
1676 GraphicsConsoleConOutEnableCursor (\r
1677   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1678   IN  BOOLEAN                          Visible\r
1679   )\r
1680 {\r
1681   EFI_TPL               OldTpl;\r
1682 \r
1683   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1684 \r
1685   EraseCursor (This);\r
1686 \r
1687   This->Mode->CursorVisible = Visible;\r
1688 \r
1689   EraseCursor (This);\r
1690 \r
1691   gBS->RestoreTPL (OldTpl);\r
1692   return EFI_SUCCESS;\r
1693 }\r
1694 \r
1695 /**\r
1696   Gets Graphics Console devcie's foreground color and background color.\r
1697 \r
1698   @param  This                  Protocol instance pointer.\r
1699   @param  Foreground            Returned text foreground color.\r
1700   @param  Background            Returned text background color.\r
1701 \r
1702   @retval EFI_SUCCESS           It returned always.\r
1703 \r
1704 **/\r
1705 EFI_STATUS\r
1706 GetTextColors (\r
1707   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1708   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Foreground,\r
1709   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Background\r
1710   )\r
1711 {\r
1712   INTN  Attribute;\r
1713 \r
1714   Attribute   = This->Mode->Attribute & 0x7F;\r
1715 \r
1716   *Foreground = mEfiColors[Attribute & 0x0f];\r
1717   *Background = mEfiColors[Attribute >> 4];\r
1718 \r
1719   return EFI_SUCCESS;\r
1720 }\r
1721 \r
1722 /**\r
1723   Draw Unicode string on the Graphice Console device's screen.\r
1724 \r
1725   @param  This                  Protocol instance pointer.\r
1726   @param  UnicodeWeight         One Unicode string to be displayed.\r
1727   @param  Count                 The count of Unicode string.\r
1728 \r
1729   @retval EFI_OUT_OF_RESOURCES  If no memory resource to use.\r
1730   @retval EFI_UNSUPPORTED       If no Graphics Output protocol and UGA Draw\r
1731                                 protocol exist.\r
1732   @retval EFI_SUCCESS           Drawing Unicode string implemented successfully.\r
1733 \r
1734 **/\r
1735 EFI_STATUS\r
1736 DrawUnicodeWeightAtCursorN (\r
1737   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
1738   IN  CHAR16                           *UnicodeWeight,\r
1739   IN  UINTN                            Count\r
1740   )\r
1741 {\r
1742   EFI_STATUS                        Status;\r
1743   GRAPHICS_CONSOLE_DEV              *Private;\r
1744   EFI_IMAGE_OUTPUT                  *Blt;\r
1745   EFI_STRING                        String;\r
1746   EFI_FONT_DISPLAY_INFO             *FontInfo;\r
1747   EFI_UGA_DRAW_PROTOCOL             *UgaDraw;\r
1748   EFI_HII_ROW_INFO                  *RowInfoArray;\r
1749   UINTN                             RowInfoArraySize;\r
1750 \r
1751   Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1752   Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
1753   if (Blt == NULL) {\r
1754     return EFI_OUT_OF_RESOURCES;\r
1755   }\r
1756 \r
1757   Blt->Width        = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);\r
1758   Blt->Height       = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);\r
1759 \r
1760   String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);\r
1761   if (String == NULL) {\r
1762     SafeFreePool (Blt);\r
1763     return EFI_OUT_OF_RESOURCES;\r
1764   }\r
1765   *(String + Count) = 0;\r
1766 \r
1767   FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));\r
1768   if (FontInfo == NULL) {\r
1769     SafeFreePool (Blt);\r
1770     SafeFreePool (String);\r
1771     return EFI_OUT_OF_RESOURCES;\r
1772   }\r
1773   GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);\r
1774 \r
1775   if (Private->GraphicsOutput != NULL) {\r
1776     Blt->Image.Screen = Private->GraphicsOutput;\r
1777 \r
1778     Status = mHiiFont->StringToImage (\r
1779                          mHiiFont,\r
1780                          EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,\r
1781                          String,\r
1782                          FontInfo,\r
1783                          &Blt,\r
1784                          This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,\r
1785                          This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,\r
1786                          NULL,\r
1787                          NULL,\r
1788                          NULL\r
1789                          );\r
1790 \r
1791   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1792     ASSERT (Private->UgaDraw!= NULL);\r
1793 \r
1794     UgaDraw = Private->UgaDraw;\r
1795 \r
1796     Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1797     if (Blt->Image.Bitmap == NULL) {\r
1798       SafeFreePool (Blt);\r
1799       SafeFreePool (String);\r
1800       return EFI_OUT_OF_RESOURCES;\r
1801     }\r
1802 \r
1803     RowInfoArray = NULL;\r
1804     //\r
1805     //  StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,\r
1806     //  we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.\r
1807     //\r
1808     Status = mHiiFont->StringToImage (\r
1809                           mHiiFont,\r
1810                           EFI_HII_IGNORE_IF_NO_GLYPH,\r
1811                           String,\r
1812                           FontInfo,\r
1813                           &Blt,\r
1814                           This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,\r
1815                           This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,\r
1816                           &RowInfoArray,\r
1817                           &RowInfoArraySize,\r
1818                           NULL\r
1819                           );\r
1820 \r
1821     if (!EFI_ERROR (Status)) {\r
1822       //\r
1823       // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will\r
1824       // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.\r
1825       //\r
1826       ASSERT (RowInfoArraySize <= 1);\r
1827 \r
1828       Status = UgaDraw->Blt (\r
1829                           UgaDraw,\r
1830                           (EFI_UGA_PIXEL *) Blt->Image.Bitmap,\r
1831                           EfiUgaBltBufferToVideo,\r
1832                           This->Mode->CursorColumn * EFI_GLYPH_WIDTH  + Private->ModeData[This->Mode->Mode].DeltaX,\r
1833                           (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,\r
1834                           This->Mode->CursorColumn * EFI_GLYPH_WIDTH  + Private->ModeData[This->Mode->Mode].DeltaX,\r
1835                           (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,\r
1836                           RowInfoArray[0].LineWidth,\r
1837                           RowInfoArray[0].LineHeight,\r
1838                           Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1839                           );\r
1840     }\r
1841 \r
1842     SafeFreePool (RowInfoArray);\r
1843     SafeFreePool (Blt->Image.Bitmap);\r
1844   } else {\r
1845     Status = EFI_UNSUPPORTED;\r
1846   }\r
1847 \r
1848   SafeFreePool (Blt);\r
1849   SafeFreePool (String);\r
1850   SafeFreePool (FontInfo);\r
1851   return Status;\r
1852 }\r
1853 \r
1854 /**\r
1855   Erase the cursor on the screen.\r
1856 \r
1857   @param  This                  Protocol instance pointer.\r
1858 \r
1859   @retval EFI_SUCCESS           The cursor is erased successfully.\r
1860 \r
1861 **/\r
1862 EFI_STATUS\r
1863 EraseCursor (\r
1864   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This\r
1865   )\r
1866 {\r
1867   GRAPHICS_CONSOLE_DEV        *Private;\r
1868   EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;\r
1869   INTN                        GlyphX;\r
1870   INTN                        GlyphY;\r
1871   EFI_GRAPHICS_OUTPUT_PROTOCOL        *GraphicsOutput;\r
1872   EFI_UGA_DRAW_PROTOCOL       *UgaDraw;\r
1873   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;\r
1874   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;\r
1875   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[EFI_GLYPH_HEIGHT][EFI_GLYPH_WIDTH];\r
1876   UINTN                       PosX;\r
1877   UINTN                       PosY;\r
1878 \r
1879   CurrentMode = This->Mode;\r
1880 \r
1881   if (!CurrentMode->CursorVisible) {\r
1882     return EFI_SUCCESS;\r
1883   }\r
1884 \r
1885   Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1886   GraphicsOutput = Private->GraphicsOutput;\r
1887   UgaDraw = Private->UgaDraw;\r
1888 \r
1889   //\r
1890   // In this driver, only narrow character was supported.\r
1891   //\r
1892   //\r
1893   // Blt a character to the screen\r
1894   //\r
1895   GlyphX  = (CurrentMode->CursorColumn * EFI_GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;\r
1896   GlyphY  = (CurrentMode->CursorRow * EFI_GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;\r
1897   if (GraphicsOutput != NULL) {\r
1898     GraphicsOutput->Blt (\r
1899               GraphicsOutput,\r
1900               (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,\r
1901               EfiBltVideoToBltBuffer,\r
1902               GlyphX,\r
1903               GlyphY,\r
1904               0,\r
1905               0,\r
1906               EFI_GLYPH_WIDTH,\r
1907               EFI_GLYPH_HEIGHT,\r
1908               EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1909               );\r
1910   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1911     UgaDraw->Blt (\r
1912               UgaDraw,\r
1913               (EFI_UGA_PIXEL *) (UINTN) BltChar,\r
1914               EfiUgaVideoToBltBuffer,\r
1915               GlyphX,\r
1916               GlyphY,\r
1917               0,\r
1918               0,\r
1919               EFI_GLYPH_WIDTH,\r
1920               EFI_GLYPH_HEIGHT,\r
1921               EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)\r
1922               );\r
1923   }\r
1924 \r
1925   GetTextColors (This, &Foreground.Pixel, &Background.Pixel);\r
1926 \r
1927   //\r
1928   // Convert Monochrome bitmap of the Glyph to BltBuffer structure\r
1929   //\r
1930   for (PosY = 0; PosY < EFI_GLYPH_HEIGHT; PosY++) {\r
1931     for (PosX = 0; PosX < EFI_GLYPH_WIDTH; PosX++) {\r
1932       if ((mCursorGlyph.GlyphCol1[PosY] & (1 << PosX)) != 0) {\r
1933         BltChar[PosY][EFI_GLYPH_WIDTH - PosX - 1].Raw ^= Foreground.Raw;\r
1934       }\r
1935     }\r
1936   }\r
1937 \r
1938   if (GraphicsOutput != NULL) {\r
1939     GraphicsOutput->Blt (\r
1940               GraphicsOutput,\r
1941               (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,\r
1942               EfiBltBufferToVideo,\r
1943               0,\r
1944               0,\r
1945               GlyphX,\r
1946               GlyphY,\r
1947               EFI_GLYPH_WIDTH,\r
1948               EFI_GLYPH_HEIGHT,\r
1949               EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1950               );\r
1951   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1952     UgaDraw->Blt (\r
1953               UgaDraw,\r
1954               (EFI_UGA_PIXEL *) (UINTN) BltChar,\r
1955               EfiUgaBltBufferToVideo,\r
1956               0,\r
1957               0,\r
1958               GlyphX,\r
1959               GlyphY,\r
1960               EFI_GLYPH_WIDTH,\r
1961               EFI_GLYPH_HEIGHT,\r
1962               EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)\r
1963               );\r
1964   }\r
1965 \r
1966   return EFI_SUCCESS;\r
1967 }\r
1968 \r
1969 /**\r
1970   The user Entry Point for module GraphicsConsole. The user code starts with this function.\r
1971 \r
1972   @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
1973   @param[in] SystemTable    A pointer to the EFI System Table.\r
1974 \r
1975   @retval EFI_SUCCESS       The entry point is executed successfully.\r
1976   @retval other             Some error occurs when executing this entry point.\r
1977 \r
1978 **/\r
1979 EFI_STATUS\r
1980 EFIAPI\r
1981 InitializeGraphicsConsole (\r
1982   IN EFI_HANDLE           ImageHandle,\r
1983   IN EFI_SYSTEM_TABLE     *SystemTable\r
1984   )\r
1985 {\r
1986   EFI_STATUS              Status;\r
1987 \r
1988   //\r
1989   // Install driver model protocol(s).\r
1990   //\r
1991   Status = EfiLibInstallDriverBindingComponentName2 (\r
1992              ImageHandle,\r
1993              SystemTable,\r
1994              &gGraphicsConsoleDriverBinding,\r
1995              ImageHandle,\r
1996              &gGraphicsConsoleComponentName,\r
1997              &gGraphicsConsoleComponentName2\r
1998              );\r
1999   ASSERT_EFI_ERROR (Status);\r
2000 \r
2001 \r
2002   return Status;\r
2003 }\r
2004 \r
2005 \r