align some line to conform with code style
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
1 /**@file\r
2   Console Splitter Driver. Any Handle that attatched\r
3   EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.\r
4 \r
5   So far it works like any other driver by opening a SimpleTextIn and/or\r
6   SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big\r
7   difference is this driver does not layer a protocol on the passed in\r
8   handle, or construct a child handle like a standard device or bus driver.\r
9   This driver produces three virtual handles as children, one for console input\r
10   splitter, one for console output splitter and one for error output splitter.\r
11   EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to\r
12   identify the splitter type.\r
13 \r
14   Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL\r
15   and Console I/O protocol, will be produced in the driver entry point.\r
16   The virtual handle are added on driver entry and never removed.\r
17   Such design ensures sytem function well during none console device situation.\r
18 \r
19 Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
20 All rights reserved. This program and the accompanying materials\r
21 are licensed and made available under the terms and conditions of the BSD License\r
22 which accompanies this distribution.  The full text of the license may be found at\r
23 http://opensource.org/licenses/bsd-license.php\r
24 \r
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
27 \r
28 **/\r
29 \r
30 #include "ConSplitter.h"\r
31 \r
32 //\r
33 // Global Variables\r
34 //\r
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {\r
36   TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
37   (EFI_HANDLE) NULL,\r
38   {\r
39     ConSplitterTextInReset,\r
40     ConSplitterTextInReadKeyStroke,\r
41     (EFI_EVENT) NULL\r
42   },\r
43   0,\r
44   (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
45   0,\r
46   {\r
47     ConSplitterTextInResetEx,\r
48     ConSplitterTextInReadKeyStrokeEx,\r
49     (EFI_EVENT) NULL,\r
50     ConSplitterTextInSetState,\r
51     ConSplitterTextInRegisterKeyNotify,\r
52     ConSplitterTextInUnregisterKeyNotify\r
53   },\r
54   0,\r
55   (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,\r
56   0,\r
57   {\r
58     (struct _LIST_ENTRY     *) NULL,\r
59     (struct _LIST_ENTRY     *) NULL\r
60   },\r
61 \r
62   {\r
63     ConSplitterSimplePointerReset,\r
64     ConSplitterSimplePointerGetState,\r
65     (EFI_EVENT) NULL,\r
66     (EFI_SIMPLE_POINTER_MODE *) NULL\r
67   },\r
68   {\r
69     0x10000,\r
70     0x10000,\r
71     0x10000,\r
72     TRUE,\r
73     TRUE\r
74   },\r
75   0,\r
76   (EFI_SIMPLE_POINTER_PROTOCOL **) NULL,\r
77   0,\r
78 \r
79   {\r
80     ConSplitterAbsolutePointerReset,\r
81     ConSplitterAbsolutePointerGetState,\r
82     (EFI_EVENT) NULL,\r
83     (EFI_ABSOLUTE_POINTER_MODE *) NULL\r
84   },\r
85 \r
86   {\r
87     0,       //AbsoluteMinX\r
88     0,       //AbsoluteMinY\r
89     0,       //AbsoluteMinZ\r
90     0x10000, //AbsoluteMaxX\r
91     0x10000, //AbsoluteMaxY\r
92     0x10000, //AbsoluteMaxZ\r
93     0        //Attributes    \r
94   },\r
95   0,\r
96   (EFI_ABSOLUTE_POINTER_PROTOCOL **) NULL,\r
97   0,\r
98   FALSE,\r
99 \r
100   FALSE,\r
101   {\r
102     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
103     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
104     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
105     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
106   },\r
107   0,\r
108   {\r
109     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
110     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
111     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
112     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
113   },\r
114   (EFI_EVENT) NULL,\r
115 \r
116   FALSE,\r
117   FALSE\r
118 };\r
119 \r
120 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {\r
121   TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
122   (EFI_HANDLE) NULL,\r
123   {\r
124     ConSplitterTextOutReset,\r
125     ConSplitterTextOutOutputString,\r
126     ConSplitterTextOutTestString,\r
127     ConSplitterTextOutQueryMode,\r
128     ConSplitterTextOutSetMode,\r
129     ConSplitterTextOutSetAttribute,\r
130     ConSplitterTextOutClearScreen,\r
131     ConSplitterTextOutSetCursorPosition,\r
132     ConSplitterTextOutEnableCursor,\r
133     (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL\r
134   },\r
135   {\r
136     1,\r
137     0,\r
138     0,\r
139     0,\r
140     0,\r
141     FALSE,\r
142   },\r
143   {\r
144     ConSpliterUgaDrawGetMode,\r
145     ConSpliterUgaDrawSetMode,\r
146     ConSpliterUgaDrawBlt\r
147   },\r
148   0,\r
149   0,\r
150   0,\r
151   0,\r
152   (EFI_UGA_PIXEL *) NULL,\r
153   {\r
154     ConSpliterGraphicsOutputQueryMode,\r
155     ConSpliterGraphicsOutputSetMode,\r
156     ConSpliterGraphicsOutputBlt,\r
157     NULL\r
158   },\r
159   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
160   (TEXT_OUT_GOP_MODE *) NULL,\r
161   0,\r
162   TRUE,\r
163   {\r
164     ConSpliterConsoleControlGetMode,\r
165     ConSpliterConsoleControlSetMode,\r
166     ConSpliterConsoleControlLockStdIn\r
167   },\r
168 \r
169   0,\r
170   (TEXT_OUT_AND_GOP_DATA *) NULL,\r
171   0,\r
172   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
173   0,\r
174   (INT32 *) NULL,\r
175 \r
176   EfiConsoleControlScreenText,\r
177   0,\r
178   0,\r
179   (CHAR16 *) NULL,\r
180   (INT32 *) NULL\r
181 };\r
182 \r
183 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {\r
184   TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
185   (EFI_HANDLE) NULL,\r
186   {\r
187     ConSplitterTextOutReset,\r
188     ConSplitterTextOutOutputString,\r
189     ConSplitterTextOutTestString,\r
190     ConSplitterTextOutQueryMode,\r
191     ConSplitterTextOutSetMode,\r
192     ConSplitterTextOutSetAttribute,\r
193     ConSplitterTextOutClearScreen,\r
194     ConSplitterTextOutSetCursorPosition,\r
195     ConSplitterTextOutEnableCursor,\r
196     (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL\r
197   },\r
198   {\r
199     1,\r
200     0,\r
201     0,\r
202     0,\r
203     0,\r
204     FALSE,\r
205   },\r
206   {\r
207     ConSpliterUgaDrawGetMode,\r
208     ConSpliterUgaDrawSetMode,\r
209     ConSpliterUgaDrawBlt\r
210   },\r
211   0,\r
212   0,\r
213   0,\r
214   0,\r
215   (EFI_UGA_PIXEL *) NULL,\r
216   {\r
217     ConSpliterGraphicsOutputQueryMode,\r
218     ConSpliterGraphicsOutputSetMode,\r
219     ConSpliterGraphicsOutputBlt,\r
220     NULL\r
221   },\r
222   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
223   (TEXT_OUT_GOP_MODE *) NULL,\r
224   0,\r
225   TRUE,\r
226   {\r
227     ConSpliterConsoleControlGetMode,\r
228     ConSpliterConsoleControlSetMode,\r
229     ConSpliterConsoleControlLockStdIn\r
230   },\r
231 \r
232   0,\r
233   (TEXT_OUT_AND_GOP_DATA *) NULL,\r
234   0,\r
235   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
236   0,\r
237   (INT32 *) NULL,\r
238 \r
239   EfiConsoleControlScreenText,\r
240   0,\r
241   0,\r
242   (CHAR16 *) NULL,\r
243   (INT32 *) NULL\r
244 };\r
245 \r
246 EFI_DRIVER_BINDING_PROTOCOL           gConSplitterConInDriverBinding = {\r
247   ConSplitterConInDriverBindingSupported,\r
248   ConSplitterConInDriverBindingStart,\r
249   ConSplitterConInDriverBindingStop,\r
250   0xa,\r
251   NULL,\r
252   NULL\r
253 };\r
254 \r
255 EFI_DRIVER_BINDING_PROTOCOL           gConSplitterSimplePointerDriverBinding = {\r
256   ConSplitterSimplePointerDriverBindingSupported,\r
257   ConSplitterSimplePointerDriverBindingStart,\r
258   ConSplitterSimplePointerDriverBindingStop,\r
259   0xa,\r
260   NULL,\r
261   NULL\r
262 };\r
263 \r
264 //\r
265 // Driver binding instance for Absolute Pointer protocol\r
266 //\r
267 EFI_DRIVER_BINDING_PROTOCOL           gConSplitterAbsolutePointerDriverBinding = {\r
268   ConSplitterAbsolutePointerDriverBindingSupported,\r
269   ConSplitterAbsolutePointerDriverBindingStart,\r
270   ConSplitterAbsolutePointerDriverBindingStop,\r
271   0xa,\r
272   NULL,\r
273   NULL\r
274 };\r
275 \r
276 EFI_DRIVER_BINDING_PROTOCOL           gConSplitterConOutDriverBinding = {\r
277   ConSplitterConOutDriverBindingSupported,\r
278   ConSplitterConOutDriverBindingStart,\r
279   ConSplitterConOutDriverBindingStop,\r
280   0xa,\r
281   NULL,\r
282   NULL\r
283 };\r
284 \r
285 EFI_DRIVER_BINDING_PROTOCOL           gConSplitterStdErrDriverBinding = {\r
286   ConSplitterStdErrDriverBindingSupported,\r
287   ConSplitterStdErrDriverBindingStart,\r
288   ConSplitterStdErrDriverBindingStop,\r
289   0xa,\r
290   NULL,\r
291   NULL\r
292 };\r
293 \r
294 /**\r
295   The user Entry Point for module ConSplitter. The user code starts with this function.\r
296 \r
297   @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
298   @param[in] SystemTable    A pointer to the EFI System Table.\r
299 \r
300   @retval EFI_SUCCESS       The entry point is executed successfully.\r
301   @retval other             Some error occurs when executing this entry point.\r
302 \r
303 **/\r
304 EFI_STATUS\r
305 EFIAPI\r
306 InitializeConSplitter(\r
307   IN EFI_HANDLE           ImageHandle,\r
308   IN EFI_SYSTEM_TABLE     *SystemTable\r
309   )\r
310 {\r
311   EFI_STATUS              Status;\r
312 \r
313   //\r
314   // Install driver model protocol(s).\r
315   //\r
316   Status = EfiLibInstallDriverBindingComponentName2 (\r
317              ImageHandle,\r
318              SystemTable,\r
319              &gConSplitterConInDriverBinding,\r
320              ImageHandle,\r
321              &gConSplitterConInComponentName,\r
322              &gConSplitterConInComponentName2\r
323              );\r
324   ASSERT_EFI_ERROR (Status);\r
325 \r
326   Status = EfiLibInstallDriverBindingComponentName2 (\r
327              ImageHandle,\r
328              SystemTable,\r
329              &gConSplitterSimplePointerDriverBinding,\r
330              NULL,\r
331              &gConSplitterSimplePointerComponentName,\r
332              &gConSplitterSimplePointerComponentName2\r
333              );\r
334   ASSERT_EFI_ERROR (Status);\r
335 \r
336   Status = EfiLibInstallDriverBindingComponentName2 (\r
337              ImageHandle,\r
338              SystemTable,\r
339              &gConSplitterAbsolutePointerDriverBinding,\r
340              NULL,\r
341              &gConSplitterAbsolutePointerComponentName,\r
342              &gConSplitterAbsolutePointerComponentName2\r
343              );\r
344   ASSERT_EFI_ERROR (Status);\r
345 \r
346   Status = EfiLibInstallDriverBindingComponentName2 (\r
347              ImageHandle,\r
348              SystemTable,\r
349              &gConSplitterConOutDriverBinding,\r
350              NULL,\r
351              &gConSplitterConOutComponentName,\r
352              &gConSplitterConOutComponentName2\r
353              );\r
354   ASSERT_EFI_ERROR (Status);\r
355 \r
356   Status = EfiLibInstallDriverBindingComponentName2 (\r
357              ImageHandle,\r
358              SystemTable,\r
359              &gConSplitterStdErrDriverBinding,\r
360              NULL,\r
361              &gConSplitterStdErrComponentName,\r
362              &gConSplitterStdErrComponentName2\r
363              );\r
364   ASSERT_EFI_ERROR (Status);\r
365 \r
366 \r
367   //\r
368   // Call the original Entry Point\r
369   //\r
370   Status = ConSplitterDriverEntry (ImageHandle, SystemTable);\r
371 \r
372   return Status;\r
373 }\r
374 \r
375 \r
376 EFI_STATUS\r
377 EFIAPI\r
378 ConSplitterDriverEntry (\r
379   IN EFI_HANDLE                       ImageHandle,\r
380   IN EFI_SYSTEM_TABLE                 *SystemTable\r
381   )\r
382 /*++\r
383 \r
384 Routine Description:\r
385   Intialize a virtual console device to act as an agrigator of physical console\r
386   devices.\r
387 \r
388 Arguments:\r
389   ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
390   SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
391 Returns:\r
392   EFI_SUCCESS\r
393 \r
394 --*/\r
395 {\r
396   EFI_STATUS  Status;\r
397 \r
398   ASSERT (FeaturePcdGet (PcdConOutGopSupport) ||\r
399           FeaturePcdGet (PcdConOutUgaSupport));\r
400   //\r
401   // The driver creates virtual handles for ConIn, ConOut, and StdErr.\r
402   // The virtual handles will always exist even if no console exist in the\r
403   // system. This is need to support hotplug devices like USB.\r
404   //\r
405   //\r
406   // Create virtual device handle for StdErr Splitter\r
407   //\r
408   Status = ConSplitterTextOutConstructor (&mStdErr);\r
409   if (!EFI_ERROR (Status)) {\r
410     Status = gBS->InstallMultipleProtocolInterfaces (\r
411                     &mStdErr.VirtualHandle,\r
412                     &gEfiSimpleTextOutProtocolGuid,\r
413                     &mStdErr.TextOut,\r
414                     &gEfiPrimaryStandardErrorDeviceGuid,\r
415                     NULL,\r
416                     NULL\r
417                     );\r
418   }\r
419   //\r
420   // Create virtual device handle for ConIn Splitter\r
421   //\r
422   Status = ConSplitterTextInConstructor (&mConIn);\r
423   if (!EFI_ERROR (Status)) {\r
424     Status = gBS->InstallMultipleProtocolInterfaces (\r
425                     &mConIn.VirtualHandle,\r
426                     &gEfiSimpleTextInProtocolGuid,\r
427                     &mConIn.TextIn,\r
428                     &gEfiSimpleTextInputExProtocolGuid,\r
429                     &mConIn.TextInEx,\r
430                     &gEfiSimplePointerProtocolGuid,\r
431                     &mConIn.SimplePointer,\r
432                     &gEfiAbsolutePointerProtocolGuid,\r
433                     &mConIn.AbsolutePointer,\r
434                     &gEfiPrimaryConsoleInDeviceGuid,\r
435                     NULL,\r
436                     NULL\r
437                     );\r
438     if (!EFI_ERROR (Status)) {\r
439       //\r
440       // Update the EFI System Table with new virtual console\r
441       //\r
442       gST->ConsoleInHandle  = mConIn.VirtualHandle;\r
443       gST->ConIn            = &mConIn.TextIn;\r
444     }\r
445   }\r
446   //\r
447   // Create virtual device handle for ConOut Splitter\r
448   //\r
449   Status = ConSplitterTextOutConstructor (&mConOut);\r
450   if (!EFI_ERROR (Status)) {\r
451     if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
452       //\r
453       // In EFI mode, UGA Draw protocol is installed\r
454       //\r
455       Status = gBS->InstallMultipleProtocolInterfaces (\r
456                       &mConOut.VirtualHandle,\r
457                       &gEfiSimpleTextOutProtocolGuid,\r
458                       &mConOut.TextOut,\r
459                       &gEfiUgaDrawProtocolGuid,\r
460                       &mConOut.UgaDraw,\r
461                       &gEfiConsoleControlProtocolGuid,\r
462                       &mConOut.ConsoleControl,\r
463                       &gEfiPrimaryConsoleOutDeviceGuid,\r
464                       NULL,\r
465                       NULL\r
466                       );\r
467     } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
468       //\r
469       // In UEFI mode, Graphics Output Protocol is installed on virtual handle.\r
470       //\r
471       Status = gBS->InstallMultipleProtocolInterfaces (\r
472                       &mConOut.VirtualHandle,\r
473                       &gEfiSimpleTextOutProtocolGuid,\r
474                       &mConOut.TextOut,\r
475                       &gEfiGraphicsOutputProtocolGuid,\r
476                       &mConOut.GraphicsOutput,\r
477                       &gEfiConsoleControlProtocolGuid,\r
478                       &mConOut.ConsoleControl,\r
479                       &gEfiPrimaryConsoleOutDeviceGuid,\r
480                       NULL,\r
481                       NULL\r
482                       );\r
483     } else {\r
484       //\r
485       // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are\r
486       // installed on virtual handle.\r
487       //\r
488       Status = gBS->InstallMultipleProtocolInterfaces (\r
489                       &mConOut.VirtualHandle,\r
490                       &gEfiSimpleTextOutProtocolGuid,\r
491                       &mConOut.TextOut,\r
492                       &gEfiGraphicsOutputProtocolGuid,\r
493                       &mConOut.GraphicsOutput,\r
494                       &gEfiUgaDrawProtocolGuid,\r
495                       &mConOut.UgaDraw,\r
496                       &gEfiConsoleControlProtocolGuid,\r
497                       &mConOut.ConsoleControl,\r
498                       &gEfiPrimaryConsoleOutDeviceGuid,\r
499                       NULL,\r
500                       NULL\r
501                       );\r
502     }\r
503 \r
504     if (!EFI_ERROR (Status)) {\r
505       //\r
506       // Update the EFI System Table with new virtual console\r
507       //\r
508       gST->ConsoleOutHandle = mConOut.VirtualHandle;\r
509       gST->ConOut           = &mConOut.TextOut;\r
510     }\r
511 \r
512   }\r
513   //\r
514   // Update the CRC32 in the EFI System Table header\r
515   //\r
516   gST->Hdr.CRC32 = 0;\r
517   gBS->CalculateCrc32 (\r
518         (UINT8 *) &gST->Hdr,\r
519         gST->Hdr.HeaderSize,\r
520         &gST->Hdr.CRC32\r
521         );\r
522 \r
523   return EFI_SUCCESS;\r
524 }\r
525 \r
526 EFI_STATUS\r
527 ConSplitterTextInConstructor (\r
528   TEXT_IN_SPLITTER_PRIVATE_DATA       *ConInPrivate\r
529   )\r
530 /*++\r
531 \r
532 Routine Description:\r
533 \r
534   Construct the ConSplitter.\r
535 \r
536 Arguments:\r
537 \r
538   ConInPrivate    - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.\r
539 \r
540 Returns:\r
541   EFI_OUT_OF_RESOURCES - Out of resources.\r
542 \r
543 --*/\r
544 {\r
545   EFI_STATUS  Status;\r
546 \r
547   //\r
548   // Initilize console input splitter's private data.\r
549   //\r
550   Status = ConSplitterGrowBuffer (\r
551             sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),\r
552             &ConInPrivate->TextInListCount,\r
553             (VOID **) &ConInPrivate->TextInList\r
554             );\r
555   if (EFI_ERROR (Status)) {\r
556     return EFI_OUT_OF_RESOURCES;\r
557   }\r
558   //\r
559   // Create Event to support locking StdIn Device\r
560   //\r
561   Status = gBS->CreateEvent (\r
562                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
563                   TPL_CALLBACK,\r
564                   ConSpliterConsoleControlLockStdInEvent,\r
565                   NULL,\r
566                   &ConInPrivate->LockEvent\r
567                   );\r
568   ASSERT_EFI_ERROR (Status);\r
569 \r
570   Status = gBS->CreateEvent (\r
571                   EVT_NOTIFY_WAIT,\r
572                   TPL_NOTIFY,\r
573                   ConSplitterTextInWaitForKey,\r
574                   ConInPrivate,\r
575                   &ConInPrivate->TextIn.WaitForKey\r
576                   );\r
577   ASSERT_EFI_ERROR (Status);\r
578 \r
579   //\r
580   // Buffer for Simple Text Input Ex Protocol\r
581   //  \r
582   Status = ConSplitterGrowBuffer (\r
583              sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
584              &ConInPrivate->TextInExListCount,\r
585              (VOID **) &ConInPrivate->TextInExList\r
586              );\r
587   if (EFI_ERROR (Status)) {\r
588     return EFI_OUT_OF_RESOURCES;\r
589   }\r
590 \r
591   Status = gBS->CreateEvent (\r
592                   EVT_NOTIFY_WAIT,\r
593                   TPL_NOTIFY,\r
594                   ConSplitterTextInWaitForKey,\r
595                   ConInPrivate,\r
596                   &ConInPrivate->TextInEx.WaitForKeyEx\r
597                   );\r
598   ASSERT_EFI_ERROR (Status);\r
599 \r
600   InitializeListHead (&ConInPrivate->NotifyList); \r
601 \r
602   //\r
603   // Allocate Buffer and Create Event for Absolute Pointer and Simple Pointer Protocols\r
604   //\r
605   ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;\r
606 \r
607   Status = ConSplitterGrowBuffer (\r
608             sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
609             &ConInPrivate->AbsolutePointerListCount,\r
610             (VOID **) &ConInPrivate->AbsolutePointerList\r
611             );\r
612   if (EFI_ERROR (Status)) {\r
613     return EFI_OUT_OF_RESOURCES;\r
614   }\r
615 \r
616   Status = gBS->CreateEvent (\r
617             EVT_NOTIFY_WAIT,\r
618             TPL_NOTIFY,\r
619             ConSplitterAbsolutePointerWaitForInput,\r
620             ConInPrivate,\r
621             &ConInPrivate->AbsolutePointer.WaitForInput\r
622         );\r
623   ASSERT_EFI_ERROR (Status);\r
624 \r
625   ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
626 \r
627   Status = ConSplitterGrowBuffer (\r
628             sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),\r
629             &ConInPrivate->PointerListCount,\r
630             (VOID **) &ConInPrivate->PointerList\r
631             );\r
632   if (EFI_ERROR (Status)) {\r
633     return EFI_OUT_OF_RESOURCES;\r
634   }\r
635 \r
636   Status = gBS->CreateEvent (\r
637                   EVT_NOTIFY_WAIT,\r
638                   TPL_NOTIFY,\r
639                   ConSplitterSimplePointerWaitForInput,\r
640                   ConInPrivate,\r
641                   &ConInPrivate->SimplePointer.WaitForInput\r
642                   );\r
643 \r
644   return Status;\r
645 }\r
646 \r
647 EFI_STATUS\r
648 ConSplitterTextOutConstructor (\r
649   TEXT_OUT_SPLITTER_PRIVATE_DATA      *ConOutPrivate\r
650   )\r
651 {\r
652   EFI_STATUS  Status;\r
653 \r
654   //\r
655   // Initilize console output splitter's private data.\r
656   //\r
657   ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;\r
658 \r
659   Status = ConSplitterGrowBuffer (\r
660             sizeof (TEXT_OUT_AND_GOP_DATA),\r
661             &ConOutPrivate->TextOutListCount,\r
662             (VOID **) &ConOutPrivate->TextOutList\r
663             );\r
664   if (EFI_ERROR (Status)) {\r
665     return EFI_OUT_OF_RESOURCES;\r
666   }\r
667 \r
668   Status = ConSplitterGrowBuffer (\r
669             sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),\r
670             &ConOutPrivate->TextOutQueryDataCount,\r
671             (VOID **) &ConOutPrivate->TextOutQueryData\r
672             );\r
673   if (EFI_ERROR (Status)) {\r
674     return EFI_OUT_OF_RESOURCES;\r
675   }\r
676   //\r
677   // Setup the DevNullTextOut console to 80 x 25\r
678   //\r
679   ConOutPrivate->TextOutQueryData[0].Columns  = 80;\r
680   ConOutPrivate->TextOutQueryData[0].Rows     = 25;\r
681   DevNullTextOutSetMode (ConOutPrivate, 0);\r
682 \r
683   if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
684     //\r
685     // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel\r
686     //\r
687     ConSpliterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60);\r
688   }\r
689   if (FeaturePcdGet (PcdConOutGopSupport)) {\r
690     //\r
691     // Setup resource for mode information in Graphics Output Protocol interface\r
692     //\r
693     if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {\r
694       return EFI_OUT_OF_RESOURCES;\r
695     }\r
696     if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
697       return EFI_OUT_OF_RESOURCES;\r
698     }\r
699     //\r
700     // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel\r
701     //\r
702     if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {\r
703       return EFI_OUT_OF_RESOURCES;\r
704     }\r
705     ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;\r
706     ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;\r
707 \r
708     //\r
709     // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()\r
710     //  GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat\r
711     //  GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
712     //\r
713     ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
714     ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
715     ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
716     ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
717     ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;\r
718 \r
719     ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
720     //\r
721     // Initial current mode to unknow state, and then set to mode 0\r
722     //\r
723     ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;\r
724     ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);\r
725   }\r
726 \r
727   return Status;\r
728 }\r
729 \r
730 STATIC\r
731 EFI_STATUS\r
732 ConSplitterSupported (\r
733   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
734   IN  EFI_HANDLE                      ControllerHandle,\r
735   IN  EFI_GUID                        *Guid\r
736   )\r
737 /*++\r
738 \r
739 Routine Description:\r
740   Generic Supported Check\r
741 \r
742 Arguments:\r
743   This              - Pointer to protocol.\r
744   ControllerHandle  - Controller Handle.\r
745   Guid              - Guid.\r
746 \r
747 Returns:\r
748 \r
749   EFI_UNSUPPORTED - unsupported.\r
750   EFI_SUCCESS     - operation is OK.\r
751 \r
752 --*/\r
753 {\r
754   EFI_STATUS  Status;\r
755   VOID        *Instance;\r
756 \r
757   //\r
758   // Make sure the Console Splitter does not attempt to attach to itself\r
759   //\r
760   if (ControllerHandle == mConIn.VirtualHandle) {\r
761     return EFI_UNSUPPORTED;\r
762   }\r
763 \r
764   if (ControllerHandle == mConOut.VirtualHandle) {\r
765     return EFI_UNSUPPORTED;\r
766   }\r
767 \r
768   if (ControllerHandle == mStdErr.VirtualHandle) {\r
769     return EFI_UNSUPPORTED;\r
770   }\r
771   //\r
772   // Check to see whether the handle has the ConsoleInDevice GUID on it\r
773   //\r
774   Status = gBS->OpenProtocol (\r
775                   ControllerHandle,\r
776                   Guid,\r
777                   &Instance,\r
778                   This->DriverBindingHandle,\r
779                   ControllerHandle,\r
780                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
781                   );\r
782 \r
783   if (EFI_ERROR (Status)) {\r
784     return Status;\r
785   }\r
786 \r
787   gBS->CloseProtocol (\r
788         ControllerHandle,\r
789         Guid,\r
790         This->DriverBindingHandle,\r
791         ControllerHandle\r
792         );\r
793 \r
794   return EFI_SUCCESS;\r
795 }\r
796 \r
797 EFI_STATUS\r
798 EFIAPI\r
799 ConSplitterConInDriverBindingSupported (\r
800   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
801   IN  EFI_HANDLE                      ControllerHandle,\r
802   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
803   )\r
804 /*++\r
805 \r
806 Routine Description:\r
807   Console In Supported Check\r
808 \r
809 Arguments:\r
810   This              - Pointer to protocol.\r
811   ControllerHandle  - Controller handle.\r
812   RemainingDevicePath  - Remaining device path.\r
813 \r
814 Returns:\r
815 \r
816   EFI_STATUS\r
817 \r
818 --*/\r
819 {\r
820   return ConSplitterSupported (\r
821           This,\r
822           ControllerHandle,\r
823           &gEfiConsoleInDeviceGuid\r
824           );\r
825 }\r
826 \r
827 EFI_STATUS\r
828 EFIAPI\r
829 ConSplitterSimplePointerDriverBindingSupported (\r
830   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
831   IN  EFI_HANDLE                      ControllerHandle,\r
832   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
833   )\r
834 /*++\r
835 \r
836 Routine Description:\r
837   Standard Error Supported Check\r
838 \r
839 Arguments:\r
840   This              - Pointer to protocol.\r
841   ControllerHandle  - Controller handle.\r
842   RemainingDevicePath  - Remaining device path.\r
843 \r
844 Returns:\r
845 \r
846   EFI_STATUS\r
847 \r
848 --*/\r
849 {\r
850   return ConSplitterSupported (\r
851           This,\r
852           ControllerHandle,\r
853           &gEfiSimplePointerProtocolGuid\r
854           );\r
855 }\r
856 \r
857 EFI_STATUS\r
858 EFIAPI\r
859 ConSplitterAbsolutePointerDriverBindingSupported (\r
860   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
861   IN  EFI_HANDLE                      ControllerHandle,\r
862   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
863   )\r
864 /*++\r
865 \r
866 Routine Description:\r
867   Absolute Pointer Supported Check\r
868 \r
869 Arguments:\r
870   This              - Pointer to protocol.\r
871   ControllerHandle  - Controller handle.\r
872   RemainingDevicePath  - Remaining device path.\r
873 \r
874 Returns:\r
875 \r
876   EFI_STATUS\r
877 \r
878 --*/\r
879 {\r
880   return ConSplitterSupported (\r
881           This,\r
882           ControllerHandle,\r
883           &gEfiAbsolutePointerProtocolGuid\r
884           );\r
885 }\r
886 \r
887 EFI_STATUS\r
888 EFIAPI\r
889 ConSplitterConOutDriverBindingSupported (\r
890   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
891   IN  EFI_HANDLE                      ControllerHandle,\r
892   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
893   )\r
894 /*++\r
895 \r
896 Routine Description:\r
897   Console Out Supported Check\r
898 \r
899 Arguments:\r
900   This              - Pointer to protocol.\r
901   ControllerHandle  - Controller handle.\r
902   RemainingDevicePath  - Remaining device path.\r
903 \r
904 Returns:\r
905 \r
906   EFI_STATUS\r
907 \r
908 --*/\r
909 {\r
910   return ConSplitterSupported (\r
911           This,\r
912           ControllerHandle,\r
913           &gEfiConsoleOutDeviceGuid\r
914           );\r
915 }\r
916 \r
917 EFI_STATUS\r
918 EFIAPI\r
919 ConSplitterStdErrDriverBindingSupported (\r
920   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
921   IN  EFI_HANDLE                      ControllerHandle,\r
922   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
923   )\r
924 /*++\r
925 \r
926 Routine Description:\r
927   Standard Error Supported Check\r
928 \r
929 Arguments:\r
930   This              - Pointer to protocol.\r
931   ControllerHandle  - Controller handle.\r
932   RemainingDevicePath  - Remaining device path.\r
933 \r
934 Returns:\r
935 \r
936   EFI_STATUS\r
937 \r
938 --*/\r
939 {\r
940   return ConSplitterSupported (\r
941           This,\r
942           ControllerHandle,\r
943           &gEfiStandardErrorDeviceGuid\r
944           );\r
945 }\r
946 \r
947 STATIC\r
948 EFI_STATUS\r
949 EFIAPI\r
950 ConSplitterStart (\r
951   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
952   IN  EFI_HANDLE                      ControllerHandle,\r
953   IN  EFI_HANDLE                      ConSplitterVirtualHandle,\r
954   IN  EFI_GUID                        *DeviceGuid,\r
955   IN  EFI_GUID                        *InterfaceGuid,\r
956   IN  VOID                            **Interface\r
957   )\r
958 /*++\r
959 \r
960 Routine Description:\r
961   Start ConSplitter on ControllerHandle, and create the virtual\r
962   agrogated console device on first call Start for a SimpleTextIn handle.\r
963 \r
964 Arguments:\r
965   (Standard DriverBinding Protocol Start() function)\r
966 \r
967 Returns:\r
968   EFI_ERROR if a SimpleTextIn protocol is not started.\r
969 \r
970 --*/\r
971 {\r
972   EFI_STATUS  Status;\r
973   VOID        *Instance;\r
974 \r
975   //\r
976   // Check to see whether the handle has the ConsoleInDevice GUID on it\r
977   //\r
978   Status = gBS->OpenProtocol (\r
979                   ControllerHandle,\r
980                   DeviceGuid,\r
981                   &Instance,\r
982                   This->DriverBindingHandle,\r
983                   ControllerHandle,\r
984                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
985                   );\r
986   if (EFI_ERROR (Status)) {\r
987     return Status;\r
988   }\r
989 \r
990   Status = gBS->OpenProtocol (\r
991                   ControllerHandle,\r
992                   DeviceGuid,\r
993                   &Instance,\r
994                   This->DriverBindingHandle,\r
995                   ConSplitterVirtualHandle,\r
996                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
997                   );\r
998   if (EFI_ERROR (Status)) {\r
999     return Status;\r
1000   }\r
1001 \r
1002   return gBS->OpenProtocol (\r
1003                 ControllerHandle,\r
1004                 InterfaceGuid,\r
1005                 Interface,\r
1006                 This->DriverBindingHandle,\r
1007                 ConSplitterVirtualHandle,\r
1008                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1009                 );\r
1010 }\r
1011 \r
1012 EFI_STATUS\r
1013 EFIAPI\r
1014 ConSplitterConInDriverBindingStart (\r
1015   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1016   IN  EFI_HANDLE                      ControllerHandle,\r
1017   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
1018   )\r
1019 /*++\r
1020 \r
1021 Routine Description:\r
1022   Start ConSplitter on ControllerHandle, and create the virtual\r
1023   agrogated console device on first call Start for a SimpleTextIn handle.\r
1024 \r
1025 Arguments:\r
1026   This              - Pointer to protocol.\r
1027   ControllerHandle  - Controller handle.\r
1028   RemainingDevicePath  - Remaining device path.\r
1029 \r
1030 Returns:\r
1031 \r
1032   EFI_STATUS\r
1033   EFI_ERROR if a SimpleTextIn protocol is not started.\r
1034 \r
1035 --*/\r
1036 {\r
1037   EFI_STATUS                     Status;\r
1038   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
1039   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
1040 \r
1041   //\r
1042   // Start ConSplitter on ControllerHandle, and create the virtual\r
1043   // agrogated console device on first call Start for a SimpleTextIn handle.\r
1044   //\r
1045   Status = ConSplitterStart (\r
1046             This,\r
1047             ControllerHandle,\r
1048             mConIn.VirtualHandle,\r
1049             &gEfiConsoleInDeviceGuid,\r
1050             &gEfiSimpleTextInProtocolGuid,\r
1051             (VOID **) &TextIn\r
1052             );\r
1053   if (EFI_ERROR (Status)) {\r
1054     return Status;\r
1055   }\r
1056 \r
1057   Status = ConSplitterTextInAddDevice (&mConIn, TextIn);\r
1058   if (EFI_ERROR (Status)) {\r
1059     return Status;\r
1060   }\r
1061 \r
1062   Status = gBS->OpenProtocol (\r
1063                   ControllerHandle,\r
1064                   &gEfiSimpleTextInputExProtocolGuid,\r
1065                   (VOID **) &TextInEx,\r
1066                   This->DriverBindingHandle,\r
1067                   mConIn.VirtualHandle,\r
1068                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1069                   );\r
1070   if (EFI_ERROR (Status)) {\r
1071     return Status;\r
1072   }\r
1073 \r
1074   Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
1075    \r
1076   return Status;\r
1077 }\r
1078 \r
1079 EFI_STATUS\r
1080 EFIAPI\r
1081 ConSplitterSimplePointerDriverBindingStart (\r
1082   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1083   IN  EFI_HANDLE                      ControllerHandle,\r
1084   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
1085   )\r
1086 /*++\r
1087 \r
1088 Routine Description:\r
1089   Start ConSplitter on ControllerHandle, and create the virtual\r
1090   agrogated console device on first call Start for a SimpleTextIn handle.\r
1091 \r
1092 Arguments:\r
1093   This              - Pointer to protocol.\r
1094   ControllerHandle  - Controller handle.\r
1095   RemainingDevicePath  - Remaining device path.\r
1096 \r
1097 Returns:\r
1098 \r
1099   EFI_ERROR if a SimpleTextIn protocol is not started.\r
1100 \r
1101 --*/\r
1102 {\r
1103   EFI_STATUS                  Status;\r
1104   EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;\r
1105 \r
1106   Status = ConSplitterStart (\r
1107             This,\r
1108             ControllerHandle,\r
1109             mConIn.VirtualHandle,\r
1110             &gEfiSimplePointerProtocolGuid,\r
1111             &gEfiSimplePointerProtocolGuid,\r
1112             (VOID **) &SimplePointer\r
1113             );\r
1114   if (EFI_ERROR (Status)) {\r
1115     return Status;\r
1116   }\r
1117 \r
1118   return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);\r
1119 }\r
1120 \r
1121 EFI_STATUS\r
1122 EFIAPI\r
1123 ConSplitterAbsolutePointerDriverBindingStart (\r
1124   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1125   IN  EFI_HANDLE                      ControllerHandle,\r
1126   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
1127   )\r
1128 /*++\r
1129 \r
1130 Routine Description:\r
1131   Start ConSplitter on ControllerHandle, and create the virtual\r
1132   agrogated console device on first call Start for a ConIn handle.\r
1133 \r
1134 Arguments:\r
1135   This                 - Pointer to protocol.\r
1136   ControllerHandle     - Controller handle.\r
1137   RemainingDevicePath  - Remaining device path.\r
1138 \r
1139 Returns:\r
1140 \r
1141   EFI_ERROR if a AbsolutePointer protocol is not started.\r
1142 \r
1143 --*/\r
1144 {\r
1145   EFI_STATUS                        Status;\r
1146   EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer;\r
1147 \r
1148   Status = ConSplitterStart (\r
1149              This,\r
1150              ControllerHandle,\r
1151              mConIn.VirtualHandle,\r
1152              &gEfiAbsolutePointerProtocolGuid,\r
1153              &gEfiAbsolutePointerProtocolGuid,\r
1154              (VOID **) &AbsolutePointer\r
1155              );\r
1156   \r
1157   if (EFI_ERROR (Status)) {\r
1158     return Status;\r
1159   }\r
1160 \r
1161   return ConSplitterAbsolutePointerAddDevice (&mConIn, AbsolutePointer);\r
1162 }\r
1163 \r
1164 EFI_STATUS\r
1165 EFIAPI\r
1166 ConSplitterConOutDriverBindingStart (\r
1167   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1168   IN  EFI_HANDLE                      ControllerHandle,\r
1169   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
1170   )\r
1171 /*++\r
1172 \r
1173 Routine Description:\r
1174   Start ConSplitter on ControllerHandle, and create the virtual\r
1175   agrogated console device on first call Start for a SimpleTextIn handle.\r
1176 \r
1177 Arguments:\r
1178   This              - Pointer to protocol.\r
1179   ControllerHandle  - Controller handle.\r
1180   RemainingDevicePath  - Remaining device path.\r
1181 \r
1182 Returns:\r
1183   EFI_ERROR if a SimpleTextIn protocol is not started.\r
1184 \r
1185 --*/\r
1186 {\r
1187   EFI_STATUS                       Status;\r
1188   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
1189   EFI_GRAPHICS_OUTPUT_PROTOCOL     *GraphicsOutput;\r
1190   EFI_UGA_DRAW_PROTOCOL            *UgaDraw;\r
1191 \r
1192   Status = ConSplitterStart (\r
1193             This,\r
1194             ControllerHandle,\r
1195             mConOut.VirtualHandle,\r
1196             &gEfiConsoleOutDeviceGuid,\r
1197             &gEfiSimpleTextOutProtocolGuid,\r
1198             (VOID **) &TextOut\r
1199             );\r
1200   if (EFI_ERROR (Status)) {\r
1201     return Status;\r
1202   }\r
1203   //\r
1204   // Try to Open Graphics Output protocol\r
1205   //\r
1206   Status = gBS->OpenProtocol (\r
1207                   ControllerHandle,\r
1208                   &gEfiGraphicsOutputProtocolGuid,\r
1209                   (VOID **) &GraphicsOutput,\r
1210                   This->DriverBindingHandle,\r
1211                   mConOut.VirtualHandle,\r
1212                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1213                   );\r
1214   if (EFI_ERROR (Status)) {\r
1215     GraphicsOutput = NULL;\r
1216   }\r
1217   //\r
1218   // Open UGA_DRAW protocol\r
1219   //\r
1220   Status = gBS->OpenProtocol (\r
1221                   ControllerHandle,\r
1222                   &gEfiUgaDrawProtocolGuid,\r
1223                   (VOID **) &UgaDraw,\r
1224                   This->DriverBindingHandle,\r
1225                   mConOut.VirtualHandle,\r
1226                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1227                   );\r
1228   if (EFI_ERROR (Status)) {\r
1229     UgaDraw = NULL;\r
1230   }\r
1231   //\r
1232   // If both ConOut and StdErr incorporate the same Text Out device,\r
1233   // their MaxMode and QueryData should be the intersection of both.\r
1234   //\r
1235   Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);\r
1236   ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
1237 \r
1238   if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
1239     //\r
1240     // Match the UGA mode data of ConOut with the current mode\r
1241     //\r
1242     if (UgaDraw != NULL) {\r
1243       UgaDraw->GetMode (\r
1244                  UgaDraw,\r
1245                  &mConOut.UgaHorizontalResolution,\r
1246                  &mConOut.UgaVerticalResolution,\r
1247                  &mConOut.UgaColorDepth,\r
1248                  &mConOut.UgaRefreshRate\r
1249                  );\r
1250     }\r
1251   }\r
1252   return Status;\r
1253 }\r
1254 \r
1255 EFI_STATUS\r
1256 EFIAPI\r
1257 ConSplitterStdErrDriverBindingStart (\r
1258   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1259   IN  EFI_HANDLE                      ControllerHandle,\r
1260   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
1261   )\r
1262 /*++\r
1263 \r
1264 Routine Description:\r
1265   Start ConSplitter on ControllerHandle, and create the virtual\r
1266   agrogated console device on first call Start for a SimpleTextIn handle.\r
1267 \r
1268 Arguments:\r
1269   This              - Pointer to protocol.\r
1270   ControllerHandle  - Controller handle.\r
1271   RemainingDevicePath  - Remaining device path.\r
1272 \r
1273 Returns:\r
1274   EFI_ERROR if a SimpleTextIn protocol is not started.\r
1275 \r
1276 --*/\r
1277 {\r
1278   EFI_STATUS                       Status;\r
1279   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
1280 \r
1281   Status = ConSplitterStart (\r
1282             This,\r
1283             ControllerHandle,\r
1284             mStdErr.VirtualHandle,\r
1285             &gEfiStandardErrorDeviceGuid,\r
1286             &gEfiSimpleTextOutProtocolGuid,\r
1287             (VOID **) &TextOut\r
1288             );\r
1289   if (EFI_ERROR (Status)) {\r
1290     return Status;\r
1291   }\r
1292   //\r
1293   // If both ConOut and StdErr incorporate the same Text Out device,\r
1294   // their MaxMode and QueryData should be the intersection of both.\r
1295   //\r
1296   Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);\r
1297   ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));\r
1298   if (EFI_ERROR (Status)) {\r
1299     return Status;\r
1300   }\r
1301 \r
1302   if (mStdErr.CurrentNumberOfConsoles == 1) {\r
1303     gST->StandardErrorHandle  = mStdErr.VirtualHandle;\r
1304     gST->StdErr               = &mStdErr.TextOut;\r
1305     //\r
1306     // Update the CRC32 in the EFI System Table header\r
1307     //\r
1308     gST->Hdr.CRC32 = 0;\r
1309     gBS->CalculateCrc32 (\r
1310           (UINT8 *) &gST->Hdr,\r
1311           gST->Hdr.HeaderSize,\r
1312           &gST->Hdr.CRC32\r
1313           );\r
1314   }\r
1315 \r
1316   return Status;\r
1317 }\r
1318 \r
1319 STATIC\r
1320 EFI_STATUS\r
1321 EFIAPI\r
1322 ConSplitterStop (\r
1323   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1324   IN  EFI_HANDLE                      ControllerHandle,\r
1325   IN  EFI_HANDLE                      ConSplitterVirtualHandle,\r
1326   IN  EFI_GUID                        *DeviceGuid,\r
1327   IN  EFI_GUID                        *InterfaceGuid,\r
1328   IN  VOID                            **Interface\r
1329   )\r
1330 /*++\r
1331 \r
1332 Routine Description:\r
1333 \r
1334 Arguments:\r
1335   (Standard DriverBinding Protocol Stop() function)\r
1336 \r
1337 Returns:\r
1338 \r
1339   None\r
1340 \r
1341 --*/\r
1342 {\r
1343   EFI_STATUS  Status;\r
1344 \r
1345   Status = gBS->OpenProtocol (\r
1346                   ControllerHandle,\r
1347                   InterfaceGuid,\r
1348                   Interface,\r
1349                   This->DriverBindingHandle,\r
1350                   ControllerHandle,\r
1351                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1352                   );\r
1353   if (EFI_ERROR (Status)) {\r
1354     return Status;\r
1355   }\r
1356   //\r
1357   // close the protocol refered.\r
1358   //\r
1359   gBS->CloseProtocol (\r
1360         ControllerHandle,\r
1361         DeviceGuid,\r
1362         This->DriverBindingHandle,\r
1363         ConSplitterVirtualHandle\r
1364         );\r
1365   gBS->CloseProtocol (\r
1366         ControllerHandle,\r
1367         DeviceGuid,\r
1368         This->DriverBindingHandle,\r
1369         ControllerHandle\r
1370         );\r
1371 \r
1372   return EFI_SUCCESS;\r
1373 }\r
1374 \r
1375 EFI_STATUS\r
1376 EFIAPI\r
1377 ConSplitterConInDriverBindingStop (\r
1378   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1379   IN  EFI_HANDLE                      ControllerHandle,\r
1380   IN  UINTN                           NumberOfChildren,\r
1381   IN  EFI_HANDLE                      *ChildHandleBuffer\r
1382   )\r
1383 /*++\r
1384 \r
1385 Routine Description:\r
1386 \r
1387 Arguments:\r
1388   (Standard DriverBinding Protocol Stop() function)\r
1389 \r
1390 Returns:\r
1391 \r
1392   None\r
1393 \r
1394 --*/\r
1395 {\r
1396   EFI_STATUS                     Status;\r
1397   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
1398 \r
1399   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
1400   if (NumberOfChildren == 0) {\r
1401     return EFI_SUCCESS;\r
1402   }\r
1403 \r
1404   Status = gBS->OpenProtocol (\r
1405                   ControllerHandle,\r
1406                   &gEfiSimpleTextInputExProtocolGuid,\r
1407                   (VOID **) &TextInEx,\r
1408                   This->DriverBindingHandle,\r
1409                   ControllerHandle,\r
1410                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1411                   );\r
1412   if (EFI_ERROR (Status)) {\r
1413     return Status;\r
1414   }\r
1415 \r
1416   Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
1417   if (EFI_ERROR (Status)) {\r
1418     return Status;\r
1419   }\r
1420   \r
1421   \r
1422   Status = ConSplitterStop (\r
1423             This,\r
1424             ControllerHandle,\r
1425             mConIn.VirtualHandle,\r
1426             &gEfiConsoleInDeviceGuid,\r
1427             &gEfiSimpleTextInProtocolGuid,\r
1428             (VOID **) &TextIn\r
1429             );\r
1430   if (EFI_ERROR (Status)) {\r
1431     return Status;\r
1432   }\r
1433   //\r
1434   // Delete this console input device's data structures.\r
1435   //\r
1436   return ConSplitterTextInDeleteDevice (&mConIn, TextIn);\r
1437 }\r
1438 \r
1439 EFI_STATUS\r
1440 EFIAPI\r
1441 ConSplitterSimplePointerDriverBindingStop (\r
1442   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1443   IN  EFI_HANDLE                      ControllerHandle,\r
1444   IN  UINTN                           NumberOfChildren,\r
1445   IN  EFI_HANDLE                      *ChildHandleBuffer\r
1446   )\r
1447 /*++\r
1448 \r
1449 Routine Description:\r
1450 \r
1451 Arguments:\r
1452   (Standard DriverBinding Protocol Stop() function)\r
1453 \r
1454 Returns:\r
1455 \r
1456   None\r
1457 \r
1458 --*/\r
1459 {\r
1460   EFI_STATUS                  Status;\r
1461   EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;\r
1462 \r
1463   if (NumberOfChildren == 0) {\r
1464     return EFI_SUCCESS;\r
1465   }\r
1466 \r
1467   Status = ConSplitterStop (\r
1468             This,\r
1469             ControllerHandle,\r
1470             mConIn.VirtualHandle,\r
1471             &gEfiSimplePointerProtocolGuid,\r
1472             &gEfiSimplePointerProtocolGuid,\r
1473             (VOID **) &SimplePointer\r
1474             );\r
1475   if (EFI_ERROR (Status)) {\r
1476     return Status;\r
1477   }\r
1478   //\r
1479   // Delete this console input device's data structures.\r
1480   //\r
1481   return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);\r
1482 }\r
1483 \r
1484 EFI_STATUS\r
1485 EFIAPI\r
1486 ConSplitterAbsolutePointerDriverBindingStop (\r
1487   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1488   IN  EFI_HANDLE                      ControllerHandle,\r
1489   IN  UINTN                           NumberOfChildren,\r
1490   IN  EFI_HANDLE                      *ChildHandleBuffer\r
1491   )\r
1492 /*++\r
1493 \r
1494 Routine Description:\r
1495 \r
1496 Arguments:\r
1497   (Standard DriverBinding Protocol Stop() function)\r
1498 \r
1499 Returns:\r
1500 \r
1501   None\r
1502 \r
1503 --*/\r
1504 {\r
1505   EFI_STATUS                        Status;\r
1506   EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer;\r
1507 \r
1508   if (NumberOfChildren == 0) {\r
1509     return EFI_SUCCESS;\r
1510   }\r
1511 \r
1512   Status = ConSplitterStop (\r
1513              This,\r
1514              ControllerHandle,\r
1515              mConIn.VirtualHandle,\r
1516              &gEfiAbsolutePointerProtocolGuid,\r
1517              &gEfiAbsolutePointerProtocolGuid,\r
1518              (VOID **) &AbsolutePointer\r
1519              );\r
1520   if (EFI_ERROR (Status)) {\r
1521     return Status;\r
1522   }\r
1523   //\r
1524   // Delete this console input device's data structures.\r
1525   //\r
1526   return ConSplitterAbsolutePointerDeleteDevice (&mConIn, AbsolutePointer);\r
1527 }\r
1528 \r
1529 EFI_STATUS\r
1530 EFIAPI\r
1531 ConSplitterConOutDriverBindingStop (\r
1532   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1533   IN  EFI_HANDLE                      ControllerHandle,\r
1534   IN  UINTN                           NumberOfChildren,\r
1535   IN  EFI_HANDLE                      *ChildHandleBuffer\r
1536   )\r
1537 /*++\r
1538 \r
1539 Routine Description:\r
1540 \r
1541 Arguments:\r
1542   (Standard DriverBinding Protocol Stop() function)\r
1543 \r
1544 Returns:\r
1545 \r
1546   None\r
1547 \r
1548 --*/\r
1549 {\r
1550   EFI_STATUS                       Status;\r
1551   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
1552 \r
1553   if (NumberOfChildren == 0) {\r
1554     return EFI_SUCCESS;\r
1555   }\r
1556 \r
1557   Status = ConSplitterStop (\r
1558             This,\r
1559             ControllerHandle,\r
1560             mConOut.VirtualHandle,\r
1561             &gEfiConsoleOutDeviceGuid,\r
1562             &gEfiSimpleTextOutProtocolGuid,\r
1563             (VOID **) &TextOut\r
1564             );\r
1565   if (EFI_ERROR (Status)) {\r
1566     return Status;\r
1567   }\r
1568 \r
1569   //\r
1570   // Delete this console output device's data structures.\r
1571   //\r
1572   return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);\r
1573 }\r
1574 \r
1575 EFI_STATUS\r
1576 EFIAPI\r
1577 ConSplitterStdErrDriverBindingStop (\r
1578   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1579   IN  EFI_HANDLE                      ControllerHandle,\r
1580   IN  UINTN                           NumberOfChildren,\r
1581   IN  EFI_HANDLE                      *ChildHandleBuffer\r
1582   )\r
1583 /*++\r
1584 \r
1585 Routine Description:\r
1586 \r
1587 Arguments:\r
1588   (Standard DriverBinding Protocol Stop() function)\r
1589 \r
1590 Returns:\r
1591 \r
1592   EFI_SUCCESS - Complete successfully.\r
1593 \r
1594 --*/\r
1595 {\r
1596   EFI_STATUS                       Status;\r
1597   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
1598 \r
1599   if (NumberOfChildren == 0) {\r
1600     return EFI_SUCCESS;\r
1601   }\r
1602 \r
1603   Status = ConSplitterStop (\r
1604             This,\r
1605             ControllerHandle,\r
1606             mStdErr.VirtualHandle,\r
1607             &gEfiStandardErrorDeviceGuid,\r
1608             &gEfiSimpleTextOutProtocolGuid,\r
1609             (VOID **) &TextOut\r
1610             );\r
1611   if (EFI_ERROR (Status)) {\r
1612     return Status;\r
1613   }\r
1614   //\r
1615   // Delete this console error out device's data structures.\r
1616   //\r
1617   Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
1618   if (EFI_ERROR (Status)) {\r
1619     return Status;\r
1620   }\r
1621 \r
1622   if (mStdErr.CurrentNumberOfConsoles == 0) {\r
1623     gST->StandardErrorHandle  = NULL;\r
1624     gST->StdErr               = NULL;\r
1625     //\r
1626     // Update the CRC32 in the EFI System Table header\r
1627     //\r
1628     gST->Hdr.CRC32 = 0;\r
1629     gBS->CalculateCrc32 (\r
1630           (UINT8 *) &gST->Hdr,\r
1631           gST->Hdr.HeaderSize,\r
1632           &gST->Hdr.CRC32\r
1633           );\r
1634   }\r
1635 \r
1636   return Status;\r
1637 }\r
1638 \r
1639 EFI_STATUS\r
1640 ConSplitterGrowBuffer (\r
1641   IN  UINTN                           SizeOfCount,\r
1642   IN  UINTN                           *Count,\r
1643   IN OUT  VOID                        **Buffer\r
1644   )\r
1645 /*++\r
1646 \r
1647 Routine Description:\r
1648   Take the passed in Buffer of size SizeOfCount and grow the buffer\r
1649   by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount\r
1650   bytes. Copy the current data in Buffer to the new version of Buffer\r
1651   and free the old version of buffer.\r
1652 \r
1653 \r
1654 Arguments:\r
1655   SizeOfCount - Size of element in array\r
1656   Count       - Current number of elements in array\r
1657   Buffer      - Bigger version of passed in Buffer with all the data\r
1658 \r
1659 Returns:\r
1660   EFI_SUCCESS - Buffer size has grown\r
1661   EFI_OUT_OF_RESOURCES - Could not grow the buffer size\r
1662 \r
1663   None\r
1664 \r
1665 --*/\r
1666 {\r
1667   UINTN NewSize;\r
1668   UINTN OldSize;\r
1669   VOID  *Ptr;\r
1670 \r
1671   //\r
1672   // grow the buffer to new buffer size,\r
1673   // copy the old buffer's content to the new-size buffer,\r
1674   // then free the old buffer.\r
1675   //\r
1676   OldSize = *Count * SizeOfCount;\r
1677   *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;\r
1678   NewSize = *Count * SizeOfCount;\r
1679 \r
1680   Ptr     = AllocateZeroPool (NewSize);\r
1681   if (Ptr == NULL) {\r
1682     return EFI_OUT_OF_RESOURCES;\r
1683   }\r
1684 \r
1685   CopyMem (Ptr, *Buffer, OldSize);\r
1686 \r
1687   if (*Buffer != NULL) {\r
1688     FreePool (*Buffer);\r
1689   }\r
1690 \r
1691   *Buffer = Ptr;\r
1692 \r
1693   return EFI_SUCCESS;\r
1694 }\r
1695 \r
1696 EFI_STATUS\r
1697 ConSplitterTextInAddDevice (\r
1698   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
1699   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *TextIn\r
1700   )\r
1701 /*++\r
1702 \r
1703 Routine Description:\r
1704 \r
1705 Arguments:\r
1706 \r
1707 Returns:\r
1708 \r
1709   EFI_SUCCESS\r
1710   EFI_OUT_OF_RESOURCES\r
1711 \r
1712 --*/\r
1713 {\r
1714   EFI_STATUS  Status;\r
1715 \r
1716   //\r
1717   // If the Text In List is full, enlarge it by calling growbuffer().\r
1718   //\r
1719   if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {\r
1720     Status = ConSplitterGrowBuffer (\r
1721               sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),\r
1722               &Private->TextInListCount,\r
1723               (VOID **) &Private->TextInList\r
1724               );\r
1725     if (EFI_ERROR (Status)) {\r
1726       return EFI_OUT_OF_RESOURCES;\r
1727     }\r
1728   }\r
1729   //\r
1730   // Add the new text-in device data structure into the Text In List.\r
1731   //\r
1732   Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;\r
1733   Private->CurrentNumberOfConsoles++;\r
1734 \r
1735   //\r
1736   // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1737   //\r
1738   gBS->CheckEvent (TextIn->WaitForKey);\r
1739 \r
1740   return EFI_SUCCESS;\r
1741 }\r
1742 \r
1743 EFI_STATUS\r
1744 ConSplitterTextInDeleteDevice (\r
1745   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
1746   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *TextIn\r
1747   )\r
1748 /*++\r
1749 \r
1750 Routine Description:\r
1751 \r
1752 Arguments:\r
1753 \r
1754 Returns:\r
1755 \r
1756   EFI_SUCCESS\r
1757   EFI_NOT_FOUND\r
1758 \r
1759 --*/\r
1760 {\r
1761   UINTN Index;\r
1762   //\r
1763   // Remove the specified text-in device data structure from the Text In List,\r
1764   // and rearrange the remaining data structures in the Text In List.\r
1765   //\r
1766   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
1767     if (Private->TextInList[Index] == TextIn) {\r
1768       for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
1769         Private->TextInList[Index] = Private->TextInList[Index + 1];\r
1770       }\r
1771 \r
1772       Private->CurrentNumberOfConsoles--;\r
1773       return EFI_SUCCESS;\r
1774     }\r
1775   }\r
1776 \r
1777   return EFI_NOT_FOUND;\r
1778 }\r
1779 \r
1780 EFI_STATUS\r
1781 ConSplitterTextInExAddDevice (\r
1782   IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
1783   IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
1784   )\r
1785 {\r
1786   EFI_STATUS  Status;\r
1787 \r
1788   //\r
1789   // If the TextInEx List is full, enlarge it by calling growbuffer().\r
1790   //\r
1791   if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
1792     Status = ConSplitterGrowBuffer (\r
1793               sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
1794               &Private->TextInExListCount,\r
1795               (VOID **) &Private->TextInExList\r
1796               );\r
1797     if (EFI_ERROR (Status)) {\r
1798       return EFI_OUT_OF_RESOURCES;\r
1799     }\r
1800   }\r
1801   //\r
1802   // Add the new text-in device data structure into the Text In List.\r
1803   //\r
1804   Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
1805   Private->CurrentNumberOfExConsoles++;\r
1806 \r
1807   //\r
1808   // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1809   //\r
1810   gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
1811 \r
1812   return EFI_SUCCESS;\r
1813 }\r
1814 \r
1815 EFI_STATUS\r
1816 ConSplitterTextInExDeleteDevice (\r
1817   IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
1818   IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
1819   )\r
1820 {\r
1821   UINTN Index;\r
1822   //\r
1823   // Remove the specified text-in device data structure from the Text In List,\r
1824   // and rearrange the remaining data structures in the Text In List.\r
1825   //\r
1826   for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
1827     if (Private->TextInExList[Index] == TextInEx) {\r
1828       for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
1829         Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
1830       }\r
1831 \r
1832       Private->CurrentNumberOfExConsoles--;\r
1833       return EFI_SUCCESS;\r
1834     }\r
1835   }\r
1836 \r
1837   return EFI_NOT_FOUND;\r
1838 }\r
1839 \r
1840 EFI_STATUS\r
1841 ConSplitterSimplePointerAddDevice (\r
1842   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
1843   IN  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointer\r
1844   )\r
1845 /*++\r
1846 \r
1847 Routine Description:\r
1848 \r
1849 Arguments:\r
1850 \r
1851 Returns:\r
1852 \r
1853   EFI_OUT_OF_RESOURCES\r
1854   EFI_SUCCESS\r
1855 \r
1856 --*/\r
1857 {\r
1858   EFI_STATUS  Status;\r
1859 \r
1860   //\r
1861   // If the Text In List is full, enlarge it by calling growbuffer().\r
1862   //\r
1863   if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {\r
1864     Status = ConSplitterGrowBuffer (\r
1865               sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),\r
1866               &Private->PointerListCount,\r
1867               (VOID **) &Private->PointerList\r
1868               );\r
1869     if (EFI_ERROR (Status)) {\r
1870       return EFI_OUT_OF_RESOURCES;\r
1871     }\r
1872   }\r
1873   //\r
1874   // Add the new text-in device data structure into the Text In List.\r
1875   //\r
1876   Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;\r
1877   Private->CurrentNumberOfPointers++;\r
1878   return EFI_SUCCESS;\r
1879 }\r
1880 \r
1881 EFI_STATUS\r
1882 ConSplitterSimplePointerDeleteDevice (\r
1883   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
1884   IN  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointer\r
1885   )\r
1886 /*++\r
1887 \r
1888 Routine Description:\r
1889 \r
1890 Arguments:\r
1891 \r
1892 Returns:\r
1893 \r
1894   None\r
1895 \r
1896 --*/\r
1897 {\r
1898   UINTN Index;\r
1899   //\r
1900   // Remove the specified text-in device data structure from the Text In List,\r
1901   // and rearrange the remaining data structures in the Text In List.\r
1902   //\r
1903   for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
1904     if (Private->PointerList[Index] == SimplePointer) {\r
1905       for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
1906         Private->PointerList[Index] = Private->PointerList[Index + 1];\r
1907       }\r
1908 \r
1909       Private->CurrentNumberOfPointers--;\r
1910       return EFI_SUCCESS;\r
1911     }\r
1912   }\r
1913 \r
1914   return EFI_NOT_FOUND;\r
1915 }\r
1916 \r
1917 EFI_STATUS\r
1918 ConSplitterAbsolutePointerAddDevice (\r
1919   IN  TEXT_IN_SPLITTER_PRIVATE_DATA     *Private,\r
1920   IN  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer\r
1921   )\r
1922 /*++\r
1923 \r
1924 Routine Description:\r
1925 \r
1926 Arguments:\r
1927 \r
1928 Returns:\r
1929 \r
1930   EFI_OUT_OF_RESOURCES\r
1931   EFI_SUCCESS\r
1932 \r
1933 --*/\r
1934 {\r
1935   EFI_STATUS  Status;\r
1936 \r
1937   //\r
1938   // If the Absolute Pointer List is full, enlarge it by calling growbuffer().\r
1939   //\r
1940   if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) {\r
1941     Status = ConSplitterGrowBuffer (\r
1942               sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
1943               &Private->AbsolutePointerListCount,\r
1944               (VOID **) &Private->AbsolutePointerList\r
1945               );\r
1946     if (EFI_ERROR (Status)) {\r
1947       return EFI_OUT_OF_RESOURCES;\r
1948     }\r
1949   }\r
1950   //\r
1951   // Add the new text-in device data structure into the Text In List.\r
1952   //\r
1953   Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer;\r
1954   Private->CurrentNumberOfAbsolutePointers++;\r
1955   return EFI_SUCCESS;\r
1956 }\r
1957 \r
1958 EFI_STATUS\r
1959 ConSplitterAbsolutePointerDeleteDevice (\r
1960   IN  TEXT_IN_SPLITTER_PRIVATE_DATA     *Private,\r
1961   IN  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer\r
1962   )\r
1963 /*++\r
1964 \r
1965 Routine Description:\r
1966 \r
1967 Arguments:\r
1968 \r
1969 Returns:\r
1970 \r
1971   None\r
1972 \r
1973 --*/\r
1974 {\r
1975   UINTN Index;\r
1976   //\r
1977   // Remove the specified text-in device data structure from the Text In List,\r
1978   // and rearrange the remaining data structures in the Text In List.\r
1979   //\r
1980   for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
1981     if (Private->AbsolutePointerList[Index] == AbsolutePointer) {\r
1982       for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
1983         Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];\r
1984       }\r
1985 \r
1986       Private->CurrentNumberOfAbsolutePointers--;\r
1987       return EFI_SUCCESS;\r
1988     }\r
1989   }\r
1990 \r
1991   return EFI_NOT_FOUND;\r
1992 }\r
1993 \r
1994 STATIC\r
1995 EFI_STATUS\r
1996 ConSplitterGrowMapTable (\r
1997   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private\r
1998   )\r
1999 /*++\r
2000 \r
2001 Routine Description:\r
2002 \r
2003 Arguments:\r
2004 \r
2005 Returns:\r
2006 \r
2007   None\r
2008 \r
2009 --*/\r
2010 {\r
2011   UINTN Size;\r
2012   UINTN NewSize;\r
2013   UINTN TotalSize;\r
2014   INT32 *TextOutModeMap;\r
2015   INT32 *OldTextOutModeMap;\r
2016   INT32 *SrcAddress;\r
2017   INT32 Index;\r
2018 \r
2019   NewSize           = Private->TextOutListCount * sizeof (INT32);\r
2020   OldTextOutModeMap = Private->TextOutModeMap;\r
2021   TotalSize         = NewSize * Private->TextOutQueryDataCount;\r
2022 \r
2023   TextOutModeMap    = AllocateZeroPool (TotalSize);\r
2024   if (TextOutModeMap == NULL) {\r
2025     return EFI_OUT_OF_RESOURCES;\r
2026   }\r
2027 \r
2028   SetMem (TextOutModeMap, TotalSize, 0xFF);\r
2029   Private->TextOutModeMap = TextOutModeMap;\r
2030 \r
2031   //\r
2032   // If TextOutList has been enlarged, need to realloc the mode map table\r
2033   // The mode map table is regarded as a two dimension array.\r
2034   //\r
2035   //                         Old                    New\r
2036   //  0   ---------> TextOutListCount ----> TextOutListCount\r
2037   //  |   -------------------------------------------\r
2038   //  |  |                    |                      |\r
2039   //  |  |                    |                      |\r
2040   //  |  |                    |                      |\r
2041   //  |  |                    |                      |\r
2042   //  |  |                    |                      |\r
2043   // \/  |                    |                      |\r
2044   //      -------------------------------------------\r
2045   // QueryDataCount\r
2046   //\r
2047   if (OldTextOutModeMap != NULL) {\r
2048 \r
2049     Size        = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
2050     Index       = 0;\r
2051     SrcAddress  = OldTextOutModeMap;\r
2052 \r
2053     //\r
2054     // Copy the old data to the new one\r
2055     //\r
2056     while (Index < Private->TextOutMode.MaxMode) {\r
2057       CopyMem (TextOutModeMap, SrcAddress, Size);\r
2058       TextOutModeMap += NewSize;\r
2059       SrcAddress += Size;\r
2060       Index++;\r
2061     }\r
2062     //\r
2063     // Free the old buffer\r
2064     //\r
2065     FreePool (OldTextOutModeMap);\r
2066   }\r
2067 \r
2068   return EFI_SUCCESS;\r
2069 }\r
2070 \r
2071 STATIC\r
2072 EFI_STATUS\r
2073 ConSplitterAddOutputMode (\r
2074   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA     *Private,\r
2075   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *TextOut\r
2076   )\r
2077 /*++\r
2078 \r
2079 Routine Description:\r
2080 \r
2081 Arguments:\r
2082 \r
2083 Returns:\r
2084 \r
2085   None\r
2086 \r
2087 --*/\r
2088 {\r
2089   EFI_STATUS  Status;\r
2090   INT32       MaxMode;\r
2091   INT32       Mode;\r
2092   UINTN       Index;\r
2093 \r
2094   MaxMode                       = TextOut->Mode->MaxMode;\r
2095   Private->TextOutMode.MaxMode  = MaxMode;\r
2096 \r
2097   //\r
2098   // Grow the buffer if query data buffer is not large enough to\r
2099   // hold all the mode supported by the first console.\r
2100   //\r
2101   while (MaxMode > (INT32) Private->TextOutQueryDataCount) {\r
2102     Status = ConSplitterGrowBuffer (\r
2103               sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),\r
2104               &Private->TextOutQueryDataCount,\r
2105               (VOID **) &Private->TextOutQueryData\r
2106               );\r
2107     if (EFI_ERROR (Status)) {\r
2108       return EFI_OUT_OF_RESOURCES;\r
2109     }\r
2110   }\r
2111   //\r
2112   // Allocate buffer for the output mode map\r
2113   //\r
2114   Status = ConSplitterGrowMapTable (Private);\r
2115   if (EFI_ERROR (Status)) {\r
2116     return EFI_OUT_OF_RESOURCES;\r
2117   }\r
2118   //\r
2119   // As the first textout device, directly add the mode in to QueryData\r
2120   // and at the same time record the mapping between QueryData and TextOut.\r
2121   //\r
2122   Mode  = 0;\r
2123   Index = 0;\r
2124   while (Mode < MaxMode) {\r
2125     TextOut->QueryMode (\r
2126               TextOut,\r
2127               Mode,\r
2128               &Private->TextOutQueryData[Mode].Columns,\r
2129               &Private->TextOutQueryData[Mode].Rows\r
2130               );\r
2131     Private->TextOutModeMap[Index] = Mode;\r
2132     Mode++;\r
2133     Index += Private->TextOutListCount;\r
2134   }\r
2135 \r
2136   return EFI_SUCCESS;\r
2137 }\r
2138 \r
2139 STATIC\r
2140 VOID\r
2141 ConSplitterGetIntersection (\r
2142   IN  INT32                           *TextOutModeMap,\r
2143   IN  INT32                           *NewlyAddedMap,\r
2144   IN  UINTN                           MapStepSize,\r
2145   IN  UINTN                           NewMapStepSize,\r
2146   OUT INT32                           *MaxMode,\r
2147   OUT INT32                           *CurrentMode\r
2148   )\r
2149 {\r
2150   INT32 Index;\r
2151   INT32 *CurrentMapEntry;\r
2152   INT32 *NextMapEntry;\r
2153   INT32 CurrentMaxMode;\r
2154   INT32 Mode;\r
2155 \r
2156   Index           = 0;\r
2157   CurrentMapEntry = TextOutModeMap;\r
2158   NextMapEntry    = TextOutModeMap;\r
2159   CurrentMaxMode  = *MaxMode;\r
2160   Mode            = *CurrentMode;\r
2161 \r
2162   while (Index < CurrentMaxMode) {\r
2163     if (*NewlyAddedMap == -1) {\r
2164       //\r
2165       // This mode is not supported any more. Remove it. Special care\r
2166       // must be taken as this remove will also affect current mode;\r
2167       //\r
2168       if (Index == *CurrentMode) {\r
2169         Mode = -1;\r
2170       } else if (Index < *CurrentMode) {\r
2171         Mode--;\r
2172       }\r
2173       (*MaxMode)--;\r
2174     } else {\r
2175       if (CurrentMapEntry != NextMapEntry) {\r
2176         CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));\r
2177       }\r
2178 \r
2179       NextMapEntry += MapStepSize;\r
2180     }\r
2181 \r
2182     CurrentMapEntry += MapStepSize;\r
2183     NewlyAddedMap += NewMapStepSize;\r
2184     Index++;\r
2185   }\r
2186 \r
2187   *CurrentMode = Mode;\r
2188 \r
2189   return ;\r
2190 }\r
2191 \r
2192 STATIC\r
2193 VOID\r
2194 ConSplitterSyncOutputMode (\r
2195   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA     *Private,\r
2196   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *TextOut\r
2197   )\r
2198 /*++\r
2199 \r
2200 Routine Description:\r
2201 \r
2202 Arguments:\r
2203   Private - Private data structure.\r
2204   TextOut - Text Out Protocol.\r
2205 Returns:\r
2206 \r
2207   None\r
2208 \r
2209 --*/\r
2210 {\r
2211   INT32                         CurrentMaxMode;\r
2212   INT32                         Mode;\r
2213   INT32                         Index;\r
2214   INT32                         *TextOutModeMap;\r
2215   INT32                         *MapTable;\r
2216   TEXT_OUT_SPLITTER_QUERY_DATA  *TextOutQueryData;\r
2217   UINTN                         Rows;\r
2218   UINTN                         Columns;\r
2219   UINTN                         StepSize;\r
2220 \r
2221   //\r
2222   // Must make sure that current mode won't change even if mode number changes\r
2223   //\r
2224   CurrentMaxMode    = Private->TextOutMode.MaxMode;\r
2225   TextOutModeMap    = Private->TextOutModeMap;\r
2226   StepSize          = Private->TextOutListCount;\r
2227   TextOutQueryData  = Private->TextOutQueryData;\r
2228 \r
2229   //\r
2230   // Query all the mode that the newly added TextOut supports\r
2231   //\r
2232   Mode      = 0;\r
2233   MapTable  = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
2234   while (Mode < TextOut->Mode->MaxMode) {\r
2235     TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
2236 \r
2237     //\r
2238     // Search the QueryData database to see if they intersects\r
2239     //\r
2240     Index = 0;\r
2241     while (Index < CurrentMaxMode) {\r
2242       if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {\r
2243         MapTable[Index * StepSize] = Mode;\r
2244         break;\r
2245       }\r
2246 \r
2247       Index++;\r
2248     }\r
2249 \r
2250     Mode++;\r
2251   }\r
2252   //\r
2253   // Now search the TextOutModeMap table to find the intersection of supported\r
2254   // mode between ConSplitter and the newly added device.\r
2255   //\r
2256   ConSplitterGetIntersection (\r
2257     TextOutModeMap,\r
2258     MapTable,\r
2259     StepSize,\r
2260     StepSize,\r
2261     &Private->TextOutMode.MaxMode,\r
2262     &Private->TextOutMode.Mode\r
2263     );\r
2264 \r
2265   return ;\r
2266 }\r
2267 \r
2268 STATIC\r
2269 EFI_STATUS\r
2270 ConSplitterGetIntersectionBetweenConOutAndStrErr (\r
2271   VOID\r
2272   )\r
2273 /*++\r
2274 \r
2275 Routine Description:\r
2276 \r
2277 Arguments:\r
2278 \r
2279 Returns:\r
2280 \r
2281   None\r
2282   EFI_OUT_OF_RESOURCES\r
2283 \r
2284 --*/\r
2285 {\r
2286   UINTN                         ConOutNumOfConsoles;\r
2287   UINTN                         StdErrNumOfConsoles;\r
2288   TEXT_OUT_AND_GOP_DATA         *ConOutTextOutList;\r
2289   TEXT_OUT_AND_GOP_DATA         *StdErrTextOutList;\r
2290   UINTN                         Indexi;\r
2291   UINTN                         Indexj;\r
2292   UINTN                         Rows;\r
2293   UINTN                         Columns;\r
2294   INT32                         ConOutMaxMode;\r
2295   INT32                         StdErrMaxMode;\r
2296   INT32                         Mode;\r
2297   INT32                         Index;\r
2298   INT32                         *ConOutModeMap;\r
2299   INT32                         *StdErrModeMap;\r
2300   INT32                         *ConOutMapTable;\r
2301   INT32                         *StdErrMapTable;\r
2302   TEXT_OUT_SPLITTER_QUERY_DATA  *ConOutQueryData;\r
2303   TEXT_OUT_SPLITTER_QUERY_DATA  *StdErrQueryData;\r
2304   BOOLEAN                       FoundTheSameTextOut;\r
2305   UINTN                         ConOutMapTableSize;\r
2306   UINTN                         StdErrMapTableSize;\r
2307 \r
2308   ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;\r
2309   StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;\r
2310   ConOutTextOutList   = mConOut.TextOutList;\r
2311   StdErrTextOutList   = mStdErr.TextOutList;\r
2312 \r
2313   Indexi              = 0;\r
2314   FoundTheSameTextOut = FALSE;\r
2315   while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {\r
2316     Indexj = 0;\r
2317     while (Indexj < StdErrNumOfConsoles) {\r
2318       if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {\r
2319         FoundTheSameTextOut = TRUE;\r
2320         break;\r
2321       }\r
2322 \r
2323       Indexj++;\r
2324       StdErrTextOutList++;\r
2325     }\r
2326 \r
2327     Indexi++;\r
2328     ConOutTextOutList++;\r
2329   }\r
2330 \r
2331   if (!FoundTheSameTextOut) {\r
2332     return EFI_SUCCESS;\r
2333   }\r
2334   //\r
2335   // Must make sure that current mode won't change even if mode number changes\r
2336   //\r
2337   ConOutMaxMode     = mConOut.TextOutMode.MaxMode;\r
2338   ConOutModeMap     = mConOut.TextOutModeMap;\r
2339   ConOutQueryData   = mConOut.TextOutQueryData;\r
2340 \r
2341   StdErrMaxMode     = mStdErr.TextOutMode.MaxMode;\r
2342   StdErrModeMap     = mStdErr.TextOutModeMap;\r
2343   StdErrQueryData   = mStdErr.TextOutQueryData;\r
2344 \r
2345   //\r
2346   // Allocate the map table and set the map table's index to -1.\r
2347   //\r
2348   ConOutMapTableSize  = ConOutMaxMode * sizeof (INT32);\r
2349   ConOutMapTable      = AllocateZeroPool (ConOutMapTableSize);\r
2350   if (ConOutMapTable == NULL) {\r
2351     return EFI_OUT_OF_RESOURCES;\r
2352   }\r
2353 \r
2354   SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);\r
2355 \r
2356   StdErrMapTableSize  = StdErrMaxMode * sizeof (INT32);\r
2357   StdErrMapTable      = AllocateZeroPool (StdErrMapTableSize);\r
2358   if (StdErrMapTable == NULL) {\r
2359     return EFI_OUT_OF_RESOURCES;\r
2360   }\r
2361 \r
2362   SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);\r
2363 \r
2364   //\r
2365   // Find the intersection of the two set of modes. If they actually intersect, the\r
2366   // correponding entry in the map table is set to 1.\r
2367   //\r
2368   Mode = 0;\r
2369   while (Mode < ConOutMaxMode) {\r
2370     //\r
2371     // Search the other's QueryData database to see if they intersect\r
2372     //\r
2373     Index   = 0;\r
2374     Rows    = ConOutQueryData[Mode].Rows;\r
2375     Columns = ConOutQueryData[Mode].Columns;\r
2376     while (Index < StdErrMaxMode) {\r
2377       if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {\r
2378         ConOutMapTable[Mode]  = 1;\r
2379         StdErrMapTable[Index] = 1;\r
2380         break;\r
2381       }\r
2382 \r
2383       Index++;\r
2384     }\r
2385 \r
2386     Mode++;\r
2387   }\r
2388   //\r
2389   // Now search the TextOutModeMap table to find the intersection of supported\r
2390   // mode between ConSplitter and the newly added device.\r
2391   //\r
2392   ConSplitterGetIntersection (\r
2393     ConOutModeMap,\r
2394     ConOutMapTable,\r
2395     mConOut.TextOutListCount,\r
2396     1,\r
2397     &(mConOut.TextOutMode.MaxMode),\r
2398     &(mConOut.TextOutMode.Mode)\r
2399     );\r
2400   if (mConOut.TextOutMode.Mode < 0) {\r
2401     mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);\r
2402   }\r
2403 \r
2404   ConSplitterGetIntersection (\r
2405     StdErrModeMap,\r
2406     StdErrMapTable,\r
2407     mStdErr.TextOutListCount,\r
2408     1,\r
2409     &(mStdErr.TextOutMode.MaxMode),\r
2410     &(mStdErr.TextOutMode.Mode)\r
2411     );\r
2412   if (mStdErr.TextOutMode.Mode < 0) {\r
2413     mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);\r
2414   }\r
2415 \r
2416   FreePool (ConOutMapTable);\r
2417   FreePool (StdErrMapTable);\r
2418 \r
2419   return EFI_SUCCESS;\r
2420 }\r
2421 \r
2422 STATIC\r
2423 EFI_STATUS\r
2424 ConSplitterAddGraphicsOutputMode (\r
2425   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,\r
2426   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput,\r
2427   IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw\r
2428   )\r
2429 /*++\r
2430 \r
2431 Routine Description:\r
2432 \r
2433 Arguments:\r
2434 \r
2435 Returns:\r
2436 \r
2437   None\r
2438 \r
2439 --*/\r
2440 {\r
2441   EFI_STATUS                           Status;\r
2442   UINTN                                Index;\r
2443   TEXT_OUT_GOP_MODE                    *Mode;\r
2444   UINTN                                SizeOfInfo;\r
2445   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
2446   EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE    *CurrentGraphicsOutputMode;\r
2447   TEXT_OUT_GOP_MODE                    *ModeBuffer;\r
2448   TEXT_OUT_GOP_MODE                    *MatchedMode;\r
2449   UINTN                                NumberIndex;\r
2450   BOOLEAN                              Match;\r
2451 \r
2452   if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2453     return EFI_UNSUPPORTED;\r
2454   }\r
2455 \r
2456   CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
2457 \r
2458   if (GraphicsOutput != NULL) {\r
2459     if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
2460         //\r
2461         // This is the first Graphics Output device added\r
2462         //\r
2463         CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;\r
2464         CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;\r
2465         CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);\r
2466         CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;\r
2467         CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;\r
2468         CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;\r
2469 \r
2470         //\r
2471         // Allocate resource for the private mode buffer\r
2472         //\r
2473         ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);\r
2474         if (ModeBuffer == NULL) {\r
2475           return EFI_OUT_OF_RESOURCES;\r
2476         }\r
2477         FreePool (Private->GraphicsOutputModeBuffer);\r
2478         Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2479 \r
2480         //\r
2481         // Store all supported display modes to the private mode buffer\r
2482         //\r
2483         Mode = ModeBuffer;\r
2484         for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {\r
2485           Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);\r
2486           if (EFI_ERROR (Status)) {\r
2487             return Status;\r
2488           }\r
2489           Mode->HorizontalResolution = Info->HorizontalResolution;\r
2490           Mode->VerticalResolution = Info->VerticalResolution;\r
2491           Mode++;\r
2492           FreePool (Info);\r
2493         }\r
2494     } else {\r
2495       //\r
2496       // Check intersection of display mode\r
2497       //\r
2498       ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);\r
2499       if (ModeBuffer == NULL) {\r
2500         return EFI_OUT_OF_RESOURCES;\r
2501       }\r
2502 \r
2503       MatchedMode = ModeBuffer;\r
2504       Mode = &Private->GraphicsOutputModeBuffer[0];\r
2505       for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2506         Match = FALSE;\r
2507 \r
2508         for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {\r
2509           Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
2510           if (EFI_ERROR (Status)) {\r
2511             return Status;\r
2512           }\r
2513           if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
2514               (Info->VerticalResolution == Mode->VerticalResolution)){\r
2515             Match = TRUE;\r
2516             FreePool (Info);\r
2517             break;\r
2518           }\r
2519           FreePool (Info);\r
2520         }\r
2521 \r
2522         if (Match) {\r
2523           CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));\r
2524           MatchedMode++;\r
2525         }\r
2526 \r
2527         Mode++;\r
2528       }\r
2529 \r
2530       //\r
2531       // Drop the old mode buffer, assign it to a new one\r
2532       //\r
2533       FreePool (Private->GraphicsOutputModeBuffer);\r
2534       Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2535 \r
2536       //\r
2537       // Physical frame buffer is no longer available when there are more than one physical GOP devices\r
2538       //\r
2539       CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));\r
2540       CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2541       ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2542       CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2543       CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2544       CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2545     }\r
2546 \r
2547     //\r
2548     // Select a prefered Display mode 800x600\r
2549     //\r
2550     for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2551       Mode = &Private->GraphicsOutputModeBuffer[Index];\r
2552       if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
2553         break;\r
2554       }\r
2555     }\r
2556     //\r
2557     // Prefered mode is not found, set to mode 0\r
2558     //\r
2559     if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
2560       Index = 0;\r
2561     }\r
2562 \r
2563     //\r
2564     // Current mode number may need update now, so set it to an invalide mode number\r
2565     //\r
2566     CurrentGraphicsOutputMode->Mode = 0xffff;\r
2567   } else {\r
2568     //\r
2569     // For UGA device, it's inconvenient to retrieve all the supported display modes.\r
2570     // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec\r
2571     //\r
2572     CurrentGraphicsOutputMode->MaxMode = 1;\r
2573     CurrentGraphicsOutputMode->Info->Version = 0;\r
2574     CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;\r
2575     CurrentGraphicsOutputMode->Info->VerticalResolution = 600;\r
2576     CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2577     CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;\r
2578     CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2579     CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2580     CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2581 \r
2582     //\r
2583     // Update the private mode buffer\r
2584     //\r
2585     ModeBuffer = &Private->GraphicsOutputModeBuffer[0];\r
2586     ModeBuffer->HorizontalResolution = 800;\r
2587     ModeBuffer->VerticalResolution   = 600;\r
2588 \r
2589     //\r
2590     // Current mode is unknow now, set it to an invalid mode number 0xffff\r
2591     //\r
2592     CurrentGraphicsOutputMode->Mode = 0xffff;\r
2593     Index = 0;\r
2594   }\r
2595 \r
2596   //\r
2597   // Force GraphicsOutput mode to be set,\r
2598   // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
2599   //\r
2600   Private->HardwareNeedsStarting = TRUE;\r
2601   Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);\r
2602 \r
2603   Private->CurrentNumberOfGraphicsOutput++;\r
2604 \r
2605   return Status;\r
2606 }\r
2607 \r
2608 EFI_STATUS\r
2609 ConSplitterTextOutAddDevice (\r
2610   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA     *Private,\r
2611   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *TextOut,\r
2612   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput,\r
2613   IN  EFI_UGA_DRAW_PROTOCOL              *UgaDraw\r
2614   )\r
2615 /*++\r
2616 \r
2617 Routine Description:\r
2618 \r
2619 Arguments:\r
2620 \r
2621 Returns:\r
2622 \r
2623   None\r
2624 \r
2625 --*/\r
2626 {\r
2627   EFI_STATUS            Status;\r
2628   UINTN                 CurrentNumOfConsoles;\r
2629   INT32                 CurrentMode;\r
2630   INT32                 MaxMode;\r
2631   TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
2632 \r
2633   Status                = EFI_SUCCESS;\r
2634   CurrentNumOfConsoles  = Private->CurrentNumberOfConsoles;\r
2635 \r
2636   //\r
2637   // If the Text Out List is full, enlarge it by calling growbuffer().\r
2638   //\r
2639   while (CurrentNumOfConsoles >= Private->TextOutListCount) {\r
2640     Status = ConSplitterGrowBuffer (\r
2641               sizeof (TEXT_OUT_AND_GOP_DATA),\r
2642               &Private->TextOutListCount,\r
2643               (VOID **) &Private->TextOutList\r
2644               );\r
2645     if (EFI_ERROR (Status)) {\r
2646       return EFI_OUT_OF_RESOURCES;\r
2647     }\r
2648     //\r
2649     // Also need to reallocate the TextOutModeMap table\r
2650     //\r
2651     Status = ConSplitterGrowMapTable (Private);\r
2652     if (EFI_ERROR (Status)) {\r
2653       return EFI_OUT_OF_RESOURCES;\r
2654     }\r
2655   }\r
2656 \r
2657   TextAndGop          = &Private->TextOutList[CurrentNumOfConsoles];\r
2658 \r
2659   TextAndGop->TextOut = TextOut;\r
2660   TextAndGop->GraphicsOutput = GraphicsOutput;\r
2661   TextAndGop->UgaDraw = UgaDraw;\r
2662 \r
2663   if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2664     //\r
2665     // If No UGA device then use the ConOut device\r
2666     //\r
2667     TextAndGop->TextOutEnabled = TRUE;\r
2668   } else {\r
2669     //\r
2670     // If UGA device use ConOut device only used if UGA screen is in Text mode\r
2671     //\r
2672     TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
2673   }\r
2674 \r
2675   if (CurrentNumOfConsoles == 0) {\r
2676     //\r
2677     // Add the first device's output mode to console splitter's mode list\r
2678     //\r
2679     Status = ConSplitterAddOutputMode (Private, TextOut);\r
2680   } else {\r
2681     ConSplitterSyncOutputMode (Private, TextOut);\r
2682   }\r
2683 \r
2684   Private->CurrentNumberOfConsoles++;\r
2685 \r
2686   //\r
2687   // Scan both TextOutList, for the intersection TextOut device\r
2688   // maybe both ConOut and StdErr incorporate the same Text Out\r
2689   // device in them, thus the output of both should be synced.\r
2690   //\r
2691   ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2692 \r
2693   CurrentMode = Private->TextOutMode.Mode;\r
2694   MaxMode     = Private->TextOutMode.MaxMode;\r
2695   ASSERT (MaxMode >= 1);\r
2696 \r
2697   if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2698     if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
2699       ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
2700     }\r
2701   }\r
2702 \r
2703   if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
2704     //\r
2705     // We just added a new UGA device in graphics mode\r
2706     //\r
2707     if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2708       DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
2709     } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
2710       DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
2711     }\r
2712   } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
2713     //\r
2714     // The new console supports the same mode of the current console so sync up\r
2715     //\r
2716     DevNullSyncGopStdOut (Private);\r
2717   } else {\r
2718     //\r
2719     // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
2720     //\r
2721     Private->TextOut.SetMode (&Private->TextOut, 0);\r
2722   }\r
2723 \r
2724   return Status;\r
2725 }\r
2726 \r
2727 EFI_STATUS\r
2728 ConSplitterTextOutDeleteDevice (\r
2729   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA     *Private,\r
2730   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *TextOut\r
2731   )\r
2732 /*++\r
2733 \r
2734 Routine Description:\r
2735 \r
2736 Arguments:\r
2737 \r
2738 Returns:\r
2739 \r
2740   None\r
2741 \r
2742 --*/\r
2743 {\r
2744   INT32                 Index;\r
2745   UINTN                 CurrentNumOfConsoles;\r
2746   TEXT_OUT_AND_GOP_DATA *TextOutList;\r
2747   EFI_STATUS            Status;\r
2748 \r
2749   //\r
2750   // Remove the specified text-out device data structure from the Text out List,\r
2751   // and rearrange the remaining data structures in the Text out List.\r
2752   //\r
2753   CurrentNumOfConsoles  = Private->CurrentNumberOfConsoles;\r
2754   Index                 = (INT32) CurrentNumOfConsoles - 1;\r
2755   TextOutList           = Private->TextOutList;\r
2756   while (Index >= 0) {\r
2757     if (TextOutList->TextOut == TextOut) {\r
2758       CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
2759       CurrentNumOfConsoles--;\r
2760       break;\r
2761     }\r
2762 \r
2763     Index--;\r
2764     TextOutList++;\r
2765   }\r
2766   //\r
2767   // The specified TextOut is not managed by the ConSplitter driver\r
2768   //\r
2769   if (Index < 0) {\r
2770     return EFI_NOT_FOUND;\r
2771   }\r
2772 \r
2773   if (CurrentNumOfConsoles == 0) {\r
2774     //\r
2775     // If the number of consoles is zero clear the Dev NULL device\r
2776     //\r
2777     Private->CurrentNumberOfConsoles      = 0;\r
2778     Private->TextOutMode.MaxMode          = 1;\r
2779     Private->TextOutQueryData[0].Columns  = 80;\r
2780     Private->TextOutQueryData[0].Rows     = 25;\r
2781     DevNullTextOutSetMode (Private, 0);\r
2782 \r
2783     return EFI_SUCCESS;\r
2784   }\r
2785   //\r
2786   // Max Mode is realy an intersection of the QueryMode command to all\r
2787   // devices. So we must copy the QueryMode of the first device to\r
2788   // QueryData.\r
2789   //\r
2790   ZeroMem (\r
2791     Private->TextOutQueryData,\r
2792     Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)\r
2793     );\r
2794 \r
2795   FreePool (Private->TextOutModeMap);\r
2796   Private->TextOutModeMap = NULL;\r
2797   TextOutList             = Private->TextOutList;\r
2798 \r
2799   //\r
2800   // Add the first TextOut to the QueryData array and ModeMap table\r
2801   //\r
2802   Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);\r
2803 \r
2804   //\r
2805   // Now add one by one\r
2806   //\r
2807   Index = 1;\r
2808   Private->CurrentNumberOfConsoles = 1;\r
2809   TextOutList++;\r
2810   while ((UINTN) Index < CurrentNumOfConsoles) {\r
2811     ConSplitterSyncOutputMode (Private, TextOutList->TextOut);\r
2812     Index++;\r
2813     Private->CurrentNumberOfConsoles++;\r
2814     TextOutList++;\r
2815   }\r
2816 \r
2817   ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2818 \r
2819   return Status;\r
2820 }\r
2821 //\r
2822 // ConSplitter TextIn member functions\r
2823 //\r
2824 EFI_STATUS\r
2825 EFIAPI\r
2826 ConSplitterTextInReset (\r
2827   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
2828   IN  BOOLEAN                         ExtendedVerification\r
2829   )\r
2830 /*++\r
2831 \r
2832   Routine Description:\r
2833     Reset the input device and optionaly run diagnostics\r
2834 \r
2835   Arguments:\r
2836     This                 - Protocol instance pointer.\r
2837     ExtendedVerification - Driver may perform diagnostics on reset.\r
2838 \r
2839   Returns:\r
2840     EFI_SUCCESS           - The device was reset.\r
2841     EFI_DEVICE_ERROR      - The device is not functioning properly and could\r
2842                             not be reset.\r
2843 \r
2844 --*/\r
2845 {\r
2846   EFI_STATUS                    Status;\r
2847   EFI_STATUS                    ReturnStatus;\r
2848   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2849   UINTN                         Index;\r
2850 \r
2851   Private                       = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2852 \r
2853   Private->KeyEventSignalState  = FALSE;\r
2854 \r
2855   //\r
2856   // return the worst status met\r
2857   //\r
2858   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2859     Status = Private->TextInList[Index]->Reset (\r
2860                                           Private->TextInList[Index],\r
2861                                           ExtendedVerification\r
2862                                           );\r
2863     if (EFI_ERROR (Status)) {\r
2864       ReturnStatus = Status;\r
2865     }\r
2866   }\r
2867 \r
2868   return ReturnStatus;\r
2869 }\r
2870 \r
2871 EFI_STATUS\r
2872 EFIAPI\r
2873 ConSplitterTextInPrivateReadKeyStroke (\r
2874   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
2875   OUT EFI_INPUT_KEY                   *Key\r
2876   )\r
2877 /*++\r
2878 \r
2879   Routine Description:\r
2880     Reads the next keystroke from the input device. The WaitForKey Event can\r
2881     be used to test for existance of a keystroke via WaitForEvent () call.\r
2882 \r
2883   Arguments:\r
2884     This   - Protocol instance pointer.\r
2885     Key    - Driver may perform diagnostics on reset.\r
2886 \r
2887   Returns:\r
2888     EFI_SUCCESS       - The keystroke information was returned.\r
2889     EFI_NOT_READY     - There was no keystroke data availiable.\r
2890     EFI_DEVICE_ERROR  - The keydtroke information was not returned due to\r
2891                         hardware errors.\r
2892 \r
2893 --*/\r
2894 {\r
2895   EFI_STATUS    Status;\r
2896   UINTN         Index;\r
2897   EFI_INPUT_KEY CurrentKey;\r
2898 \r
2899   Key->UnicodeChar  = 0;\r
2900   Key->ScanCode     = SCAN_NULL;\r
2901 \r
2902   //\r
2903   // if no physical console input device exists, return EFI_NOT_READY;\r
2904   // if any physical console input device has key input,\r
2905   // return the key and EFI_SUCCESS.\r
2906   //\r
2907   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2908     Status = Private->TextInList[Index]->ReadKeyStroke (\r
2909                                           Private->TextInList[Index],\r
2910                                           &CurrentKey\r
2911                                           );\r
2912     if (!EFI_ERROR (Status)) {\r
2913       *Key = CurrentKey;\r
2914       return Status;\r
2915     }\r
2916   }\r
2917 \r
2918   return EFI_NOT_READY;\r
2919 }\r
2920 \r
2921 BOOLEAN\r
2922 ConSpliterConssoleControlStdInLocked (\r
2923   VOID\r
2924   )\r
2925 /*++\r
2926 \r
2927 Routine Description:\r
2928   Return TRUE if StdIn is locked. The ConIn device on the virtual handle is\r
2929   the only device locked.\r
2930 \r
2931 Arguments:\r
2932   NONE\r
2933 \r
2934 Returns:\r
2935   TRUE  - StdIn locked\r
2936   FALSE - StdIn working normally\r
2937 \r
2938 --*/\r
2939 {\r
2940   return mConIn.PasswordEnabled;\r
2941 }\r
2942 \r
2943 VOID\r
2944 EFIAPI\r
2945 ConSpliterConsoleControlLockStdInEvent (\r
2946   IN  EFI_EVENT                       Event,\r
2947   IN  VOID                            *Context\r
2948   )\r
2949 /*++\r
2950 \r
2951 Routine Description:\r
2952   This timer event will fire when StdIn is locked. It will check the key\r
2953   sequence on StdIn to see if it matches the password. Any error in the\r
2954   password will cause the check to reset. As long a mConIn.PasswordEnabled is\r
2955   TRUE the StdIn splitter will not report any input.\r
2956 \r
2957 Arguments:\r
2958   (Standard EFI_EVENT_NOTIFY)\r
2959 \r
2960 Returns:\r
2961   None\r
2962 \r
2963 --*/\r
2964 {\r
2965   EFI_STATUS    Status;\r
2966   EFI_INPUT_KEY Key;\r
2967   CHAR16        BackSpaceString[2];\r
2968   CHAR16        SpaceString[2];\r
2969 \r
2970   do {\r
2971     Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);\r
2972     if (!EFI_ERROR (Status)) {\r
2973       //\r
2974       // if it's an ENTER, match password\r
2975       //\r
2976       if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {\r
2977         mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;\r
2978         if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {\r
2979           //\r
2980           // Password not match\r
2981           //\r
2982           ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");\r
2983           mConIn.PwdIndex = 0;\r
2984         } else {\r
2985           //\r
2986           // Key matches password sequence\r
2987           //\r
2988           gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);\r
2989           mConIn.PasswordEnabled  = FALSE;\r
2990           Status                  = EFI_NOT_READY;\r
2991         }\r
2992       } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {\r
2993         //\r
2994         // BackSpace met\r
2995         //\r
2996         if (mConIn.PwdIndex > 0) {\r
2997           BackSpaceString[0]  = CHAR_BACKSPACE;\r
2998           BackSpaceString[1]  = 0;\r
2999 \r
3000           SpaceString[0]      = ' ';\r
3001           SpaceString[1]      = 0;\r
3002 \r
3003           ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
3004           ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);\r
3005           ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
3006 \r
3007           mConIn.PwdIndex--;\r
3008         }\r
3009       } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {\r
3010         //\r
3011         // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input\r
3012         //\r
3013         if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {\r
3014           if (mConIn.PwdIndex == 0) {\r
3015             ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");\r
3016           }\r
3017 \r
3018           ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");\r
3019           mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;\r
3020           mConIn.PwdIndex++;\r
3021         }\r
3022       }\r
3023     }\r
3024   } while (!EFI_ERROR (Status));\r
3025 }\r
3026 \r
3027 EFI_STATUS\r
3028 EFIAPI\r
3029 ConSpliterConsoleControlLockStdIn (\r
3030   IN  EFI_CONSOLE_CONTROL_PROTOCOL    *This,\r
3031   IN  CHAR16                          *Password\r
3032   )\r
3033 /*++\r
3034 \r
3035 Routine Description:\r
3036   If Password is NULL unlock the password state variable and set the event\r
3037   timer. If the Password is too big return an error. If the Password is valid\r
3038   Copy the Password and enable state variable and then arm the periodic timer\r
3039 \r
3040 Arguments:\r
3041 \r
3042 Returns:\r
3043   EFI_SUCCESS           - Lock the StdIn device\r
3044   EFI_INVALID_PARAMETER - Password is NULL\r
3045   EFI_OUT_OF_RESOURCES  - Buffer allocation to store the password fails\r
3046 \r
3047 --*/\r
3048 {\r
3049   if (Password == NULL) {\r
3050     return EFI_INVALID_PARAMETER;\r
3051   }\r
3052 \r
3053   if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {\r
3054     //\r
3055     // Currently have a max password size\r
3056     //\r
3057     return EFI_OUT_OF_RESOURCES;\r
3058   }\r
3059   //\r
3060   // Save the password, initialize state variables and arm event timer\r
3061   //\r
3062   StrCpy (mConIn.Password, Password);\r
3063   mConIn.PasswordEnabled  = TRUE;\r
3064   mConIn.PwdIndex         = 0;\r
3065   gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));\r
3066 \r
3067   return EFI_SUCCESS;\r
3068 }\r
3069 \r
3070 EFI_STATUS\r
3071 EFIAPI\r
3072 ConSplitterTextInReadKeyStroke (\r
3073   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
3074   OUT EFI_INPUT_KEY                   *Key\r
3075   )\r
3076 /*++\r
3077 \r
3078   Routine Description:\r
3079     Reads the next keystroke from the input device. The WaitForKey Event can\r
3080     be used to test for existance of a keystroke via WaitForEvent () call.\r
3081     If the ConIn is password locked make it look like no keystroke is availible\r
3082 \r
3083   Arguments:\r
3084     This   - Protocol instance pointer.\r
3085     Key    - Driver may perform diagnostics on reset.\r
3086 \r
3087   Returns:\r
3088     EFI_SUCCESS       - The keystroke information was returned.\r
3089     EFI_NOT_READY     - There was no keystroke data availiable.\r
3090     EFI_DEVICE_ERROR  - The keydtroke information was not returned due to\r
3091                         hardware errors.\r
3092 \r
3093 --*/\r
3094 {\r
3095   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3096 \r
3097   Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3098   if (Private->PasswordEnabled) {\r
3099     //\r
3100     // If StdIn Locked return not ready\r
3101     //\r
3102     return EFI_NOT_READY;\r
3103   }\r
3104 \r
3105   Private->KeyEventSignalState = FALSE;\r
3106 \r
3107   return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
3108 }\r
3109 \r
3110 VOID\r
3111 EFIAPI\r
3112 ConSplitterTextInWaitForKey (\r
3113   IN  EFI_EVENT                       Event,\r
3114   IN  VOID                            *Context\r
3115   )\r
3116 /*++\r
3117 \r
3118 Routine Description:\r
3119   This event agregates all the events of the ConIn devices in the spliter.\r
3120   If the ConIn is password locked then return.\r
3121   If any events of physical ConIn devices are signaled, signal the ConIn\r
3122   spliter event. This will cause the calling code to call\r
3123   ConSplitterTextInReadKeyStroke ().\r
3124 \r
3125 Arguments:\r
3126   Event   - The Event assoicated with callback.\r
3127   Context - Context registered when Event was created.\r
3128 \r
3129 Returns:\r
3130   None\r
3131 \r
3132 --*/\r
3133 {\r
3134   EFI_STATUS                    Status;\r
3135   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3136   UINTN                         Index;\r
3137 \r
3138   Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
3139   if (Private->PasswordEnabled) {\r
3140     //\r
3141     // If StdIn Locked return not ready\r
3142     //\r
3143     return ;\r
3144   }\r
3145 \r
3146   //\r
3147   // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
3148   //\r
3149   if (Private->KeyEventSignalState) {\r
3150     gBS->SignalEvent (Event);\r
3151     return ;\r
3152   }\r
3153   //\r
3154   // if any physical console input device has key input, signal the event.\r
3155   //\r
3156   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3157     Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);\r
3158     if (!EFI_ERROR (Status)) {\r
3159       gBS->SignalEvent (Event);\r
3160       Private->KeyEventSignalState = TRUE;\r
3161     }\r
3162   }\r
3163 }\r
3164 \r
3165 \r
3166 STATIC\r
3167 BOOLEAN\r
3168 IsKeyRegistered (\r
3169   IN EFI_KEY_DATA  *RegsiteredData,\r
3170   IN EFI_KEY_DATA  *InputData\r
3171   )\r
3172 /*++\r
3173 \r
3174 Routine Description:\r
3175 \r
3176 Arguments:\r
3177 \r
3178   RegsiteredData    - A pointer to a buffer that is filled in with the keystroke \r
3179                       state data for the key that was registered.\r
3180   InputData         - A pointer to a buffer that is filled in with the keystroke \r
3181                       state data for the key that was pressed.\r
3182 \r
3183 Returns:\r
3184   TRUE              - Key be pressed matches a registered key.\r
3185   FLASE             - Match failed. \r
3186   \r
3187 --*/\r
3188 {\r
3189   ASSERT (RegsiteredData != NULL && InputData != NULL);\r
3190   \r
3191   if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||\r
3192       (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
3193     return FALSE;  \r
3194   }      \r
3195   \r
3196   //\r
3197   // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
3198   //\r
3199   if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
3200       RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
3201     return FALSE;    \r
3202   }   \r
3203   if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
3204       RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
3205     return FALSE;    \r
3206   }     \r
3207   \r
3208   return TRUE;\r
3209 \r
3210 }\r
3211 \r
3212 //\r
3213 // Simple Text Input Ex protocol functions\r
3214 //\r
3215 \r
3216 EFI_STATUS\r
3217 EFIAPI\r
3218 ConSplitterTextInResetEx (\r
3219   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
3220   IN BOOLEAN                            ExtendedVerification\r
3221   )\r
3222 /*++\r
3223 \r
3224   Routine Description:\r
3225     Reset the input device and optionaly run diagnostics\r
3226 \r
3227   Arguments:\r
3228     This                 - Protocol instance pointer.\r
3229     ExtendedVerification - Driver may perform diagnostics on reset.\r
3230 \r
3231   Returns:\r
3232     EFI_SUCCESS           - The device was reset.\r
3233     EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
3234                             not be reset.\r
3235 \r
3236 --*/\r
3237 {\r
3238   EFI_STATUS                    Status;\r
3239   EFI_STATUS                    ReturnStatus;\r
3240   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3241   UINTN                         Index;\r
3242 \r
3243   Private                       = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3244 \r
3245   Private->KeyEventSignalState  = FALSE;\r
3246 \r
3247   //\r
3248   // return the worst status met\r
3249   //\r
3250   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r