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