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