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