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