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
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.
18 Console Splitter Driver. Any Handle that attatched
19 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
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.
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.
37 #include "ConSplitter.h"
42 static TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
43 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
46 ConSplitterTextInReset
,
47 ConSplitterTextInReadKeyStroke
,
51 (EFI_SIMPLE_TEXT_IN_PROTOCOL
**) NULL
,
55 ConSplitterSimplePointerReset
,
56 ConSplitterSimplePointerGetState
,
58 (EFI_SIMPLE_POINTER_MODE
*) NULL
68 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
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
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
91 static TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
92 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
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
115 ConSpliterUgaDrawGetMode
,
116 ConSpliterUgaDrawSetMode
,
123 (EFI_UGA_PIXEL
*) NULL
,
126 ConSpliterConsoleControlGetMode
,
127 ConSpliterConsoleControlSetMode
,
128 ConSpliterConsoleControlLockStdIn
132 (TEXT_OUT_AND_UGA_DATA
*) NULL
,
134 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
138 EfiConsoleControlScreenText
,
145 static TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
146 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
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
169 ConSpliterUgaDrawGetMode
,
170 ConSpliterUgaDrawSetMode
,
177 (EFI_UGA_PIXEL
*) NULL
,
180 ConSpliterConsoleControlGetMode
,
181 ConSpliterConsoleControlSetMode
,
182 ConSpliterConsoleControlLockStdIn
186 (TEXT_OUT_AND_UGA_DATA
*) NULL
,
188 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
192 EfiConsoleControlScreenText
,
199 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
200 ConSplitterConInDriverBindingSupported
,
201 ConSplitterConInDriverBindingStart
,
202 ConSplitterConInDriverBindingStop
,
208 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
209 ConSplitterSimplePointerDriverBindingSupported
,
210 ConSplitterSimplePointerDriverBindingStart
,
211 ConSplitterSimplePointerDriverBindingStop
,
217 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
218 ConSplitterConOutDriverBindingSupported
,
219 ConSplitterConOutDriverBindingStart
,
220 ConSplitterConOutDriverBindingStop
,
226 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
227 ConSplitterStdErrDriverBindingSupported
,
228 ConSplitterStdErrDriverBindingStart
,
229 ConSplitterStdErrDriverBindingStop
,
237 ConSplitterDriverEntry (
238 IN EFI_HANDLE ImageHandle
,
239 IN EFI_SYSTEM_TABLE
*SystemTable
244 Intialize a virtual console device to act as an agrigator of physical console
248 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
249 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
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.
263 // Create virtual device handle for StdErr Splitter
265 Status
= ConSplitterTextOutConstructor (&mStdErr
);
266 if (!EFI_ERROR (Status
)) {
267 Status
= gBS
->InstallMultipleProtocolInterfaces (
268 &mStdErr
.VirtualHandle
,
269 &gEfiSimpleTextOutProtocolGuid
,
271 &gEfiPrimaryStandardErrorDeviceGuid
,
277 // Create virtual device handle for ConIn Splitter
279 Status
= ConSplitterTextInConstructor (&mConIn
);
280 if (!EFI_ERROR (Status
)) {
281 Status
= gBS
->InstallMultipleProtocolInterfaces (
282 &mConIn
.VirtualHandle
,
283 &gEfiSimpleTextInProtocolGuid
,
285 &gEfiSimplePointerProtocolGuid
,
286 &mConIn
.SimplePointer
,
287 &gEfiPrimaryConsoleInDeviceGuid
,
291 if (!EFI_ERROR (Status
)) {
293 // Update the EFI System Table with new virtual console
295 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
296 gST
->ConIn
= &mConIn
.TextIn
;
300 // Create virtual device handle for ConOut Splitter
302 Status
= ConSplitterTextOutConstructor (&mConOut
);
303 if (!EFI_ERROR (Status
)) {
304 Status
= gBS
->InstallMultipleProtocolInterfaces (
305 &mConOut
.VirtualHandle
,
306 &gEfiSimpleTextOutProtocolGuid
,
308 &gEfiUgaDrawProtocolGuid
,
310 &gEfiConsoleControlProtocolGuid
,
311 &mConOut
.ConsoleControl
,
312 &gEfiPrimaryConsoleOutDeviceGuid
,
316 if (!EFI_ERROR (Status
)) {
318 // Update the EFI System Table with new virtual console
320 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
321 gST
->ConOut
= &mConOut
.TextOut
;
326 // Update the CRC32 in the EFI System Table header
329 gBS
->CalculateCrc32 (
340 ConSplitterTextInConstructor (
341 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
347 Construct the ConSplitter.
351 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
354 EFI_OUT_OF_RESOURCES - Out of resources.
361 // Initilize console input splitter's private data.
363 Status
= ConSplitterGrowBuffer (
364 sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL
*),
365 &ConInPrivate
->TextInListCount
,
366 (VOID
**) &ConInPrivate
->TextInList
368 if (EFI_ERROR (Status
)) {
369 return EFI_OUT_OF_RESOURCES
;
372 // Create Event to support locking StdIn Device
374 Status
= gBS
->CreateEvent (
375 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
377 ConSpliterConsoleControlLockStdInEvent
,
379 &ConInPrivate
->LockEvent
381 ASSERT_EFI_ERROR (Status
);
383 Status
= gBS
->CreateEvent (
384 EFI_EVENT_NOTIFY_WAIT
,
386 ConSplitterTextInWaitForKey
,
388 &ConInPrivate
->TextIn
.WaitForKey
390 ASSERT_EFI_ERROR (Status
);
392 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
394 Status
= ConSplitterGrowBuffer (
395 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
396 &ConInPrivate
->PointerListCount
,
397 (VOID
**) &ConInPrivate
->PointerList
399 if (EFI_ERROR (Status
)) {
400 return EFI_OUT_OF_RESOURCES
;
403 Status
= gBS
->CreateEvent (
404 EFI_EVENT_NOTIFY_WAIT
,
406 ConSplitterSimplePointerWaitForInput
,
408 &ConInPrivate
->SimplePointer
.WaitForInput
416 ConSplitterTextOutConstructor (
417 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
423 // Initilize console output splitter's private data.
425 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
427 Status
= ConSplitterGrowBuffer (
428 sizeof (TEXT_OUT_AND_UGA_DATA
),
429 &ConOutPrivate
->TextOutListCount
,
430 (VOID
**) &ConOutPrivate
->TextOutList
432 if (EFI_ERROR (Status
)) {
433 return EFI_OUT_OF_RESOURCES
;
436 Status
= ConSplitterGrowBuffer (
437 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
438 &ConOutPrivate
->TextOutQueryDataCount
,
439 (VOID
**) &ConOutPrivate
->TextOutQueryData
441 if (EFI_ERROR (Status
)) {
442 return EFI_OUT_OF_RESOURCES
;
445 // Setup the DevNullTextOut console to 80 x 25
447 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
448 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
449 DevNullTextOutSetMode (ConOutPrivate
, 0);
452 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
454 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
461 ConSplitterSupported (
462 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
463 IN EFI_HANDLE ControllerHandle
,
469 Generic Supported Check
472 This - Pointer to protocol.
473 ControllerHandle - Controller Handle.
478 EFI_UNSUPPORTED - unsupported.
479 EFI_SUCCESS - operation is OK.
487 // Make sure the Console Splitter does not attempt to attach to itself
489 if (ControllerHandle
== mConIn
.VirtualHandle
) {
490 return EFI_UNSUPPORTED
;
493 if (ControllerHandle
== mConOut
.VirtualHandle
) {
494 return EFI_UNSUPPORTED
;
497 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
498 return EFI_UNSUPPORTED
;
501 // Check to see whether the handle has the ConsoleInDevice GUID on it
503 Status
= gBS
->OpenProtocol (
507 This
->DriverBindingHandle
,
509 EFI_OPEN_PROTOCOL_BY_DRIVER
512 if (EFI_ERROR (Status
)) {
519 This
->DriverBindingHandle
,
529 ConSplitterConInDriverBindingSupported (
530 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
531 IN EFI_HANDLE ControllerHandle
,
532 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
537 Console In Supported Check
540 This - Pointer to protocol.
541 ControllerHandle - Controller handle.
542 RemainingDevicePath - Remaining device path.
550 return ConSplitterSupported (
553 &gEfiConsoleInDeviceGuid
560 ConSplitterSimplePointerDriverBindingSupported (
561 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
562 IN EFI_HANDLE ControllerHandle
,
563 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
568 Standard Error Supported Check
571 This - Pointer to protocol.
572 ControllerHandle - Controller handle.
573 RemainingDevicePath - Remaining device path.
581 return ConSplitterSupported (
584 &gEfiSimplePointerProtocolGuid
591 ConSplitterConOutDriverBindingSupported (
592 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
593 IN EFI_HANDLE ControllerHandle
,
594 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
599 Console Out Supported Check
602 This - Pointer to protocol.
603 ControllerHandle - Controller handle.
604 RemainingDevicePath - Remaining device path.
612 return ConSplitterSupported (
615 &gEfiConsoleOutDeviceGuid
622 ConSplitterStdErrDriverBindingSupported (
623 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
624 IN EFI_HANDLE ControllerHandle
,
625 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
630 Standard Error Supported Check
633 This - Pointer to protocol.
634 ControllerHandle - Controller handle.
635 RemainingDevicePath - Remaining device path.
643 return ConSplitterSupported (
646 &gEfiStandardErrorDeviceGuid
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
,
664 Start ConSplitter on ControllerHandle, and create the virtual
665 agrogated console device on first call Start for a SimpleTextIn handle.
668 (Standard DriverBinding Protocol Start() function)
671 EFI_ERROR if a SimpleTextIn protocol is not started.
679 // Check to see whether the handle has the ConsoleInDevice GUID on it
681 Status
= gBS
->OpenProtocol (
685 This
->DriverBindingHandle
,
687 EFI_OPEN_PROTOCOL_BY_DRIVER
689 if (EFI_ERROR (Status
)) {
693 Status
= gBS
->OpenProtocol (
697 This
->DriverBindingHandle
,
698 ConSplitterVirtualHandle
,
699 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
701 if (EFI_ERROR (Status
)) {
705 return gBS
->OpenProtocol (
709 This
->DriverBindingHandle
,
710 ConSplitterVirtualHandle
,
711 EFI_OPEN_PROTOCOL_GET_PROTOCOL
718 ConSplitterConInDriverBindingStart (
719 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
720 IN EFI_HANDLE ControllerHandle
,
721 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
726 Start ConSplitter on ControllerHandle, and create the virtual
727 agrogated console device on first call Start for a SimpleTextIn handle.
730 This - Pointer to protocol.
731 ControllerHandle - Controller handle.
732 RemainingDevicePath - Remaining device path.
737 EFI_ERROR if a SimpleTextIn protocol is not started.
742 EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
;
745 // Start ConSplitter on ControllerHandle, and create the virtual
746 // agrogated console device on first call Start for a SimpleTextIn handle.
748 Status
= ConSplitterStart (
751 mConIn
.VirtualHandle
,
752 &gEfiConsoleInDeviceGuid
,
753 &gEfiSimpleTextInProtocolGuid
,
756 if (EFI_ERROR (Status
)) {
760 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
766 ConSplitterSimplePointerDriverBindingStart (
767 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
768 IN EFI_HANDLE ControllerHandle
,
769 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
774 Start ConSplitter on ControllerHandle, and create the virtual
775 agrogated console device on first call Start for a SimpleTextIn handle.
778 This - Pointer to protocol.
779 ControllerHandle - Controller handle.
780 RemainingDevicePath - Remaining device path.
784 EFI_ERROR if a SimpleTextIn protocol is not started.
789 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
791 Status
= ConSplitterStart (
794 mConIn
.VirtualHandle
,
795 &gEfiSimplePointerProtocolGuid
,
796 &gEfiSimplePointerProtocolGuid
,
797 (VOID
**) &SimplePointer
799 if (EFI_ERROR (Status
)) {
803 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
809 ConSplitterConOutDriverBindingStart (
810 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
811 IN EFI_HANDLE ControllerHandle
,
812 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
817 Start ConSplitter on ControllerHandle, and create the virtual
818 agrogated console device on first call Start for a SimpleTextIn handle.
821 This - Pointer to protocol.
822 ControllerHandle - Controller handle.
823 RemainingDevicePath - Remaining device path.
826 EFI_ERROR if a SimpleTextIn protocol is not started.
831 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
832 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
834 Status
= ConSplitterStart (
837 mConOut
.VirtualHandle
,
838 &gEfiConsoleOutDeviceGuid
,
839 &gEfiSimpleTextOutProtocolGuid
,
842 if (EFI_ERROR (Status
)) {
846 // Open UGA_DRAW protocol
848 Status
= gBS
->OpenProtocol (
850 &gEfiUgaDrawProtocolGuid
,
852 This
->DriverBindingHandle
,
853 mConOut
.VirtualHandle
,
854 EFI_OPEN_PROTOCOL_GET_PROTOCOL
856 if (EFI_ERROR (Status
)) {
860 // If both ConOut and StdErr incorporate the same Text Out device,
861 // their MaxMode and QueryData should be the intersection of both.
863 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, UgaDraw
);
864 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
866 // Match the UGA mode data of ConOut with the current mode
871 &mConOut
.UgaHorizontalResolution
,
872 &mConOut
.UgaVerticalResolution
,
873 &mConOut
.UgaColorDepth
,
874 &mConOut
.UgaRefreshRate
883 ConSplitterStdErrDriverBindingStart (
884 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
885 IN EFI_HANDLE ControllerHandle
,
886 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
891 Start ConSplitter on ControllerHandle, and create the virtual
892 agrogated console device on first call Start for a SimpleTextIn handle.
895 This - Pointer to protocol.
896 ControllerHandle - Controller handle.
897 RemainingDevicePath - Remaining device path.
900 EFI_ERROR if a SimpleTextIn protocol is not started.
905 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
907 Status
= ConSplitterStart (
910 mStdErr
.VirtualHandle
,
911 &gEfiStandardErrorDeviceGuid
,
912 &gEfiSimpleTextOutProtocolGuid
,
915 if (EFI_ERROR (Status
)) {
919 // If both ConOut and StdErr incorporate the same Text Out device,
920 // their MaxMode and QueryData should be the intersection of both.
922 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
);
923 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
924 if (EFI_ERROR (Status
)) {
928 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
929 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
930 gST
->StdErr
= &mStdErr
.TextOut
;
932 // Update the CRC32 in the EFI System Table header
935 gBS
->CalculateCrc32 (
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
,
961 (Standard DriverBinding Protocol Stop() function)
971 Status
= gBS
->OpenProtocol (
975 This
->DriverBindingHandle
,
977 EFI_OPEN_PROTOCOL_GET_PROTOCOL
979 if (EFI_ERROR (Status
)) {
983 // close the protocol refered.
988 This
->DriverBindingHandle
,
989 ConSplitterVirtualHandle
994 This
->DriverBindingHandle
,
1004 ConSplitterConInDriverBindingStop (
1005 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1006 IN EFI_HANDLE ControllerHandle
,
1007 IN UINTN NumberOfChildren
,
1008 IN EFI_HANDLE
*ChildHandleBuffer
1012 Routine Description:
1015 (Standard DriverBinding Protocol Stop() function)
1024 EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
;
1026 if (NumberOfChildren
== 0) {
1030 Status
= ConSplitterStop (
1033 mConIn
.VirtualHandle
,
1034 &gEfiConsoleInDeviceGuid
,
1035 &gEfiSimpleTextInProtocolGuid
,
1038 if (EFI_ERROR (Status
)) {
1042 // Delete this console input device's data structures.
1044 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1050 ConSplitterSimplePointerDriverBindingStop (
1051 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1052 IN EFI_HANDLE ControllerHandle
,
1053 IN UINTN NumberOfChildren
,
1054 IN EFI_HANDLE
*ChildHandleBuffer
1058 Routine Description:
1061 (Standard DriverBinding Protocol Stop() function)
1070 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1072 if (NumberOfChildren
== 0) {
1076 Status
= ConSplitterStop (
1079 mConIn
.VirtualHandle
,
1080 &gEfiSimplePointerProtocolGuid
,
1081 &gEfiSimplePointerProtocolGuid
,
1082 (VOID
**) &SimplePointer
1084 if (EFI_ERROR (Status
)) {
1088 // Delete this console input device's data structures.
1090 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1096 ConSplitterConOutDriverBindingStop (
1097 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1098 IN EFI_HANDLE ControllerHandle
,
1099 IN UINTN NumberOfChildren
,
1100 IN EFI_HANDLE
*ChildHandleBuffer
1104 Routine Description:
1107 (Standard DriverBinding Protocol Stop() function)
1116 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1117 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1119 if (NumberOfChildren
== 0) {
1123 Status
= ConSplitterStop (
1126 mConOut
.VirtualHandle
,
1127 &gEfiConsoleOutDeviceGuid
,
1128 &gEfiSimpleTextOutProtocolGuid
,
1131 if (EFI_ERROR (Status
)) {
1135 // Remove any UGA devices
1137 Status
= gBS
->OpenProtocol (
1139 &gEfiUgaDrawProtocolGuid
,
1141 This
->DriverBindingHandle
,
1142 mConOut
.VirtualHandle
,
1143 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1147 // Delete this console output device's data structures.
1149 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1155 ConSplitterStdErrDriverBindingStop (
1156 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1157 IN EFI_HANDLE ControllerHandle
,
1158 IN UINTN NumberOfChildren
,
1159 IN EFI_HANDLE
*ChildHandleBuffer
1163 Routine Description:
1166 (Standard DriverBinding Protocol Stop() function)
1170 EFI_SUCCESS - Complete successfully.
1175 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1177 if (NumberOfChildren
== 0) {
1181 Status
= ConSplitterStop (
1184 mStdErr
.VirtualHandle
,
1185 &gEfiStandardErrorDeviceGuid
,
1186 &gEfiSimpleTextOutProtocolGuid
,
1189 if (EFI_ERROR (Status
)) {
1193 // Delete this console error out device's data structures.
1195 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1196 if (EFI_ERROR (Status
)) {
1200 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1201 gST
->StandardErrorHandle
= NULL
;
1204 // Update the CRC32 in the EFI System Table header
1207 gBS
->CalculateCrc32 (
1208 (UINT8
*) &gST
->Hdr
,
1209 gST
->Hdr
.HeaderSize
,
1218 ConSplitterGrowBuffer (
1219 IN UINTN SizeOfCount
,
1221 IN OUT VOID
**Buffer
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.
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
1238 EFI_SUCCESS - Buffer size has grown
1239 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
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.
1254 OldSize
= *Count
* SizeOfCount
;
1255 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1256 NewSize
= *Count
* SizeOfCount
;
1258 Ptr
= AllocateZeroPool (NewSize
);
1260 return EFI_OUT_OF_RESOURCES
;
1263 CopyMem (Ptr
, *Buffer
, OldSize
);
1265 if (*Buffer
!= NULL
) {
1266 gBS
->FreePool (*Buffer
);
1275 ConSplitterTextInAddDevice (
1276 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1277 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
1281 Routine Description:
1288 EFI_OUT_OF_RESOURCES
1295 // If the Text In List is full, enlarge it by calling growbuffer().
1297 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1298 Status
= ConSplitterGrowBuffer (
1299 sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL
*),
1300 &Private
->TextInListCount
,
1301 (VOID
**) &Private
->TextInList
1303 if (EFI_ERROR (Status
)) {
1304 return EFI_OUT_OF_RESOURCES
;
1308 // Add the new text-in device data structure into the Text In List.
1310 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1311 Private
->CurrentNumberOfConsoles
++;
1314 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1316 gBS
->CheckEvent (TextIn
->WaitForKey
);
1322 ConSplitterTextInDeleteDevice (
1323 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1324 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
1328 Routine Description:
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.
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];
1350 Private
->CurrentNumberOfConsoles
--;
1355 return EFI_NOT_FOUND
;
1359 ConSplitterSimplePointerAddDevice (
1360 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1361 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1365 Routine Description:
1371 EFI_OUT_OF_RESOURCES
1379 // If the Text In List is full, enlarge it by calling growbuffer().
1381 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1382 Status
= ConSplitterGrowBuffer (
1383 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1384 &Private
->PointerListCount
,
1385 (VOID
**) &Private
->PointerList
1387 if (EFI_ERROR (Status
)) {
1388 return EFI_OUT_OF_RESOURCES
;
1392 // Add the new text-in device data structure into the Text In List.
1394 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1395 Private
->CurrentNumberOfPointers
++;
1400 ConSplitterSimplePointerDeleteDevice (
1401 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1402 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1406 Routine Description:
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.
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];
1427 Private
->CurrentNumberOfPointers
--;
1432 return EFI_NOT_FOUND
;
1436 ConSplitterGrowMapTable (
1437 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1441 Routine Description:
1454 INT32
*TextOutModeMap
;
1455 INT32
*OldTextOutModeMap
;
1459 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1460 OldTextOutModeMap
= Private
->TextOutModeMap
;
1461 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1463 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1464 if (TextOutModeMap
== NULL
) {
1465 return EFI_OUT_OF_RESOURCES
;
1468 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1469 Private
->TextOutModeMap
= TextOutModeMap
;
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.
1476 // 0 ---------> TextOutListCount ----> TextOutListCount
1477 // | -------------------------------------------
1484 // -------------------------------------------
1487 if (OldTextOutModeMap
!= NULL
) {
1489 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1491 SrcAddress
= OldTextOutModeMap
;
1494 // Copy the old data to the new one
1496 while (Index
< Private
->TextOutMode
.MaxMode
) {
1497 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1498 TextOutModeMap
+= NewSize
;
1503 // Free the old buffer
1505 gBS
->FreePool (OldTextOutModeMap
);
1512 ConSplitterAddOutputMode (
1513 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1514 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1518 Routine Description:
1533 MaxMode
= TextOut
->Mode
->MaxMode
;
1534 Private
->TextOutMode
.MaxMode
= MaxMode
;
1537 // Grow the buffer if query data buffer is not large enough to
1538 // hold all the mode supported by the first console.
1540 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1541 Status
= ConSplitterGrowBuffer (
1542 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1543 &Private
->TextOutQueryDataCount
,
1544 (VOID
**) &Private
->TextOutQueryData
1546 if (EFI_ERROR (Status
)) {
1547 return EFI_OUT_OF_RESOURCES
;
1551 // Allocate buffer for the output mode map
1553 Status
= ConSplitterGrowMapTable (Private
);
1554 if (EFI_ERROR (Status
)) {
1555 return EFI_OUT_OF_RESOURCES
;
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.
1563 while (Mode
< MaxMode
) {
1564 TextOut
->QueryMode (
1567 &Private
->TextOutQueryData
[Mode
].Columns
,
1568 &Private
->TextOutQueryData
[Mode
].Rows
1570 Private
->TextOutModeMap
[Index
] = Mode
;
1572 Index
+= Private
->TextOutListCount
;
1579 ConSplitterGetIntersection (
1580 IN INT32
*TextOutModeMap
,
1581 IN INT32
*NewlyAddedMap
,
1582 IN UINTN MapStepSize
,
1583 IN UINTN NewMapStepSize
,
1585 OUT INT32
*CurrentMode
1589 INT32
*CurrentMapEntry
;
1590 INT32
*NextMapEntry
;
1591 INT32 CurrentMaxMode
;
1595 CurrentMapEntry
= TextOutModeMap
;
1596 NextMapEntry
= TextOutModeMap
;
1597 CurrentMaxMode
= *MaxMode
;
1598 Mode
= *CurrentMode
;
1600 while (Index
< CurrentMaxMode
) {
1601 if (*NewlyAddedMap
== -1) {
1603 // This mode is not supported any more. Remove it. Special care
1604 // must be taken as this remove will also affect current mode;
1606 if (Index
== *CurrentMode
) {
1608 } else if (Index
< *CurrentMode
) {
1613 if (CurrentMapEntry
!= NextMapEntry
) {
1614 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1617 NextMapEntry
+= MapStepSize
;
1620 CurrentMapEntry
+= MapStepSize
;
1621 NewlyAddedMap
+= NewMapStepSize
;
1625 *CurrentMode
= Mode
;
1631 ConSplitterSyncOutputMode (
1632 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1633 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1637 Routine Description:
1640 Private - Private data structure.
1641 TextOut - Text Out Protocol.
1649 INT32 CurrentMaxMode
;
1652 INT32
*TextOutModeMap
;
1654 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1660 // Must make sure that current mode won't change even if mode number changes
1662 CurrentMode
= Private
->TextOutMode
.Mode
;
1663 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1664 TextOutModeMap
= Private
->TextOutModeMap
;
1665 StepSize
= Private
->TextOutListCount
;
1666 TextOutQueryData
= Private
->TextOutQueryData
;
1669 // Query all the mode that the newly added TextOut supports
1672 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1673 while (Mode
< TextOut
->Mode
->MaxMode
) {
1674 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1677 // Search the QueryData database to see if they intersects
1680 while (Index
< CurrentMaxMode
) {
1681 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1682 MapTable
[Index
* StepSize
] = Mode
;
1692 // Now search the TextOutModeMap table to find the intersection of supported
1693 // mode between ConSplitter and the newly added device.
1695 ConSplitterGetIntersection (
1700 &Private
->TextOutMode
.MaxMode
,
1701 &Private
->TextOutMode
.Mode
1708 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1713 Routine Description:
1723 UINTN ConOutNumOfConsoles
;
1724 UINTN StdErrNumOfConsoles
;
1725 TEXT_OUT_AND_UGA_DATA
*ConOutTextOutList
;
1726 TEXT_OUT_AND_UGA_DATA
*StdErrTextOutList
;
1731 INT32 ConOutCurrentMode
;
1732 INT32 StdErrCurrentMode
;
1733 INT32 ConOutMaxMode
;
1734 INT32 StdErrMaxMode
;
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
;
1749 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1750 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1751 ConOutTextOutList
= mConOut
.TextOutList
;
1752 StdErrTextOutList
= mStdErr
.TextOutList
;
1755 FoundTheSameTextOut
= FALSE
;
1756 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1758 while (Indexj
< StdErrNumOfConsoles
) {
1759 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1760 FoundTheSameTextOut
= TRUE
;
1765 StdErrTextOutList
++;
1769 ConOutTextOutList
++;
1772 if (!FoundTheSameTextOut
) {
1776 // Must make sure that current mode won't change even if mode number changes
1778 ConOutCurrentMode
= mConOut
.TextOutMode
.Mode
;
1779 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1780 ConOutModeMap
= mConOut
.TextOutModeMap
;
1781 ConOutStepSize
= mConOut
.TextOutListCount
;
1782 ConOutQueryData
= mConOut
.TextOutQueryData
;
1784 StdErrCurrentMode
= mStdErr
.TextOutMode
.Mode
;
1785 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1786 StdErrModeMap
= mStdErr
.TextOutModeMap
;
1787 StdErrStepSize
= mStdErr
.TextOutListCount
;
1788 StdErrQueryData
= mStdErr
.TextOutQueryData
;
1791 // Allocate the map table and set the map table's index to -1.
1793 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
1794 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
1795 if (ConOutMapTable
== NULL
) {
1796 return EFI_OUT_OF_RESOURCES
;
1799 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
1801 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
1802 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
1803 if (StdErrMapTable
== NULL
) {
1804 return EFI_OUT_OF_RESOURCES
;
1807 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
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.
1814 while (Mode
< ConOutMaxMode
) {
1816 // Search the other's QueryData database to see if they intersect
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;
1834 // Now search the TextOutModeMap table to find the intersection of supported
1835 // mode between ConSplitter and the newly added device.
1837 ConSplitterGetIntersection (
1840 mConOut
.TextOutListCount
,
1842 &(mConOut
.TextOutMode
.MaxMode
),
1843 &(mConOut
.TextOutMode
.Mode
)
1845 if (mConOut
.TextOutMode
.Mode
< 0) {
1846 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
1849 ConSplitterGetIntersection (
1852 mStdErr
.TextOutListCount
,
1854 &(mStdErr
.TextOutMode
.MaxMode
),
1855 &(mStdErr
.TextOutMode
.Mode
)
1857 if (mStdErr
.TextOutMode
.Mode
< 0) {
1858 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
1861 gBS
->FreePool (ConOutMapTable
);
1862 gBS
->FreePool (StdErrMapTable
);
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
1875 Routine Description:
1886 UINTN CurrentNumOfConsoles
;
1889 TEXT_OUT_AND_UGA_DATA
*TextAndUga
;
1891 Status
= EFI_SUCCESS
;
1892 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
1895 // If the Text Out List is full, enlarge it by calling growbuffer().
1897 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
1898 Status
= ConSplitterGrowBuffer (
1899 sizeof (TEXT_OUT_AND_UGA_DATA
),
1900 &Private
->TextOutListCount
,
1901 (VOID
**) &Private
->TextOutList
1903 if (EFI_ERROR (Status
)) {
1904 return EFI_OUT_OF_RESOURCES
;
1907 // Also need to reallocate the TextOutModeMap table
1909 Status
= ConSplitterGrowMapTable (Private
);
1910 if (EFI_ERROR (Status
)) {
1911 return EFI_OUT_OF_RESOURCES
;
1915 TextAndUga
= &Private
->TextOutList
[CurrentNumOfConsoles
];
1917 TextAndUga
->TextOut
= TextOut
;
1918 TextAndUga
->UgaDraw
= UgaDraw
;
1919 if (UgaDraw
== NULL
) {
1921 // If No UGA device then use the ConOut device
1923 TextAndUga
->TextOutEnabled
= TRUE
;
1926 // If UGA device use ConOut device only used if UGA screen is in Text mode
1928 TextAndUga
->TextOutEnabled
= (BOOLEAN
) (Private
->UgaMode
== EfiConsoleControlScreenText
);
1931 if (CurrentNumOfConsoles
== 0) {
1933 // Add the first device's output mode to console splitter's mode list
1935 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
1937 ConSplitterSyncOutputMode (Private
, TextOut
);
1940 Private
->CurrentNumberOfConsoles
++;
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.
1947 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
1949 CurrentMode
= Private
->TextOutMode
.Mode
;
1950 MaxMode
= Private
->TextOutMode
.MaxMode
;
1951 ASSERT (MaxMode
>= 1);
1953 if (Private
->UgaMode
== EfiConsoleControlScreenGraphics
&& UgaDraw
!= NULL
) {
1955 // We just added a new UGA device in graphics mode
1957 DevNullUgaSync (Private
, UgaDraw
);
1959 } else if ((CurrentMode
>= 0) && (UgaDraw
!= NULL
) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
1961 // The new console supports the same mode of the current console so sync up
1963 DevNullSyncUgaStdOut (Private
);
1966 // If ConOut, then set the mode to Mode #0 which us 80 x 25
1968 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
1975 ConSplitterTextOutDeleteDevice (
1976 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1977 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1981 Routine Description:
1992 UINTN CurrentNumOfConsoles
;
1993 TEXT_OUT_AND_UGA_DATA
*TextOutList
;
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.
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
--;
2014 // The specified TextOut is not managed by the ConSplitter driver
2017 return EFI_NOT_FOUND
;
2020 if (CurrentNumOfConsoles
== 0) {
2022 // If the number of consoles is zero clear the Dev NULL device
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);
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
2038 Private
->TextOutQueryData
,
2039 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2042 gBS
->FreePool (Private
->TextOutModeMap
);
2043 Private
->TextOutModeMap
= NULL
;
2044 TextOutList
= Private
->TextOutList
;
2047 // Add the first TextOut to the QueryData array and ModeMap table
2049 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2052 // Now add one by one
2055 Private
->CurrentNumberOfConsoles
= 1;
2057 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2058 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2060 Private
->CurrentNumberOfConsoles
++;
2064 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2069 // ConSplitter TextIn member functions
2073 ConSplitterTextInReset (
2074 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*This
,
2075 IN BOOLEAN ExtendedVerification
2079 Routine Description:
2080 Reset the input device and optionaly run diagnostics
2083 This - Protocol instance pointer.
2084 ExtendedVerification - Driver may perform diagnostics on reset.
2087 EFI_SUCCESS - The device was reset.
2088 EFI_DEVICE_ERROR - The device is not functioning properly and could
2094 EFI_STATUS ReturnStatus
;
2095 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2098 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2100 Private
->KeyEventSignalState
= FALSE
;
2103 // return the worst status met
2105 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2106 Status
= Private
->TextInList
[Index
]->Reset (
2107 Private
->TextInList
[Index
],
2108 ExtendedVerification
2110 if (EFI_ERROR (Status
)) {
2111 ReturnStatus
= Status
;
2115 return ReturnStatus
;
2120 ConSplitterTextInPrivateReadKeyStroke (
2121 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2122 OUT EFI_INPUT_KEY
*Key
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.
2131 This - Protocol instance pointer.
2132 Key - Driver may perform diagnostics on reset.
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
2144 EFI_INPUT_KEY CurrentKey
;
2146 Key
->UnicodeChar
= 0;
2147 Key
->ScanCode
= SCAN_NULL
;
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.
2154 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2155 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2156 Private
->TextInList
[Index
],
2159 if (!EFI_ERROR (Status
)) {
2165 return EFI_NOT_READY
;
2169 ConSpliterConssoleControlStdInLocked (
2174 Routine Description:
2175 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2176 the only device locked.
2183 FALSE - StdIn working normally
2187 return mConIn
.PasswordEnabled
;
2192 ConSpliterConsoleControlLockStdInEvent (
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.
2205 (Standard EFI_EVENT_NOTIFY)
2214 CHAR16 BackSpaceString
[2];
2215 CHAR16 SpaceString
[2];
2218 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2219 if (!EFI_ERROR (Status
)) {
2221 // if it's an ENTER, match password
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
)) {
2227 // Password not match
2229 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2230 mConIn
.PwdIndex
= 0;
2233 // Key matches password sequence
2235 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2236 mConIn
.PasswordEnabled
= FALSE
;
2237 Status
= EFI_NOT_READY
;
2239 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2243 if (mConIn
.PwdIndex
> 0) {
2244 BackSpaceString
[0] = CHAR_BACKSPACE
;
2245 BackSpaceString
[1] = 0;
2247 SpaceString
[0] = ' ';
2250 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2251 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2252 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2256 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2258 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2260 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2261 if (mConIn
.PwdIndex
== 0) {
2262 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2265 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2266 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2271 } while (!EFI_ERROR (Status
));
2276 ConSpliterConsoleControlLockStdIn (
2277 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
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
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
2296 if (Password
== NULL
) {
2297 return EFI_INVALID_PARAMETER
;
2300 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2302 // Currently have a max password size
2304 return EFI_OUT_OF_RESOURCES
;
2307 // Save the password, initialize state variables and arm event timer
2309 StrCpy (mConIn
.Password
, Password
);
2310 mConIn
.PasswordEnabled
= TRUE
;
2311 mConIn
.PwdIndex
= 0;
2312 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2319 ConSplitterTextInReadKeyStroke (
2320 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*This
,
2321 OUT EFI_INPUT_KEY
*Key
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
2331 This - Protocol instance pointer.
2332 Key - Driver may perform diagnostics on reset.
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
2342 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2344 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2345 if (Private
->PasswordEnabled
) {
2347 // If StdIn Locked return not ready
2349 return EFI_NOT_READY
;
2352 Private
->KeyEventSignalState
= FALSE
;
2354 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2359 ConSplitterTextInWaitForKey (
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 ().
2373 Event - The Event assoicated with callback.
2374 Context - Context registered when Event was created.
2382 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2385 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2386 if (Private
->PasswordEnabled
) {
2388 // If StdIn Locked return not ready
2394 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2396 if (Private
->KeyEventSignalState
) {
2397 gBS
->SignalEvent (Event
);
2401 // if any physical console input device has key input, signal the event.
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
;
2414 ConSplitterSimplePointerReset (
2415 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2416 IN BOOLEAN ExtendedVerification
2420 Routine Description:
2421 Reset the input device and optionaly run diagnostics
2424 This - Protocol instance pointer.
2425 ExtendedVerification - Driver may perform diagnostics on reset.
2428 EFI_SUCCESS - The device was reset.
2429 EFI_DEVICE_ERROR - The device is not functioning properly and could
2435 EFI_STATUS ReturnStatus
;
2436 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2439 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2441 Private
->InputEventSignalState
= FALSE
;
2443 if (Private
->CurrentNumberOfPointers
== 0) {
2447 // return the worst status met
2449 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2450 Status
= Private
->PointerList
[Index
]->Reset (
2451 Private
->PointerList
[Index
],
2452 ExtendedVerification
2454 if (EFI_ERROR (Status
)) {
2455 ReturnStatus
= Status
;
2459 return ReturnStatus
;
2464 ConSplitterSimplePointerPrivateGetState (
2465 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2466 IN OUT EFI_SIMPLE_POINTER_STATE
*State
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.
2475 This - Protocol instance pointer.
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
2487 EFI_STATUS ReturnStatus
;
2489 EFI_SIMPLE_POINTER_STATE CurrentState
;
2491 State
->RelativeMovementX
= 0;
2492 State
->RelativeMovementY
= 0;
2493 State
->RelativeMovementZ
= 0;
2494 State
->LeftButton
= FALSE
;
2495 State
->RightButton
= FALSE
;
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.
2502 ReturnStatus
= EFI_NOT_READY
;
2503 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2505 Status
= Private
->PointerList
[Index
]->GetState (
2506 Private
->PointerList
[Index
],
2509 if (!EFI_ERROR (Status
)) {
2510 if (ReturnStatus
== EFI_NOT_READY
) {
2511 ReturnStatus
= EFI_SUCCESS
;
2514 if (CurrentState
.LeftButton
) {
2515 State
->LeftButton
= TRUE
;
2518 if (CurrentState
.RightButton
) {
2519 State
->RightButton
= TRUE
;
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
;
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
;
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
;
2533 } else if (Status
== EFI_DEVICE_ERROR
) {
2534 ReturnStatus
= EFI_DEVICE_ERROR
;
2538 return ReturnStatus
;
2543 ConSplitterSimplePointerGetState (
2544 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2545 IN OUT EFI_SIMPLE_POINTER_STATE
*State
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
2555 This - Protocol instance pointer.
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
2566 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2568 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2569 if (Private
->PasswordEnabled
) {
2571 // If StdIn Locked return not ready
2573 return EFI_NOT_READY
;
2576 Private
->InputEventSignalState
= FALSE
;
2578 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2583 ConSplitterSimplePointerWaitForInput (
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 ().
2597 Event - The Event assoicated with callback.
2598 Context - Context registered when Event was created.
2606 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2609 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2610 if (Private
->PasswordEnabled
) {
2612 // If StdIn Locked return not ready
2618 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2620 if (Private
->InputEventSignalState
) {
2621 gBS
->SignalEvent (Event
);
2625 // if any physical console input device has key input, signal the event.
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
;
2638 ConSplitterTextOutReset (
2639 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2640 IN BOOLEAN ExtendedVerification
2644 Routine Description:
2645 Reset the text output device hardware and optionaly run diagnostics
2648 This - Protocol instance pointer.
2649 ExtendedVerification - Driver may perform more exhaustive verfication
2650 operation of the device during reset.
2653 EFI_SUCCESS - The text output device was reset.
2654 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
2660 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2662 EFI_STATUS ReturnStatus
;
2664 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2667 // return the worst status met
2669 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2671 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2673 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
2674 Private
->TextOutList
[Index
].TextOut
,
2675 ExtendedVerification
2677 if (EFI_ERROR (Status
)) {
2678 ReturnStatus
= Status
;
2683 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
2685 Status
= DevNullTextOutSetMode (Private
, 0);
2686 if (EFI_ERROR (Status
)) {
2687 ReturnStatus
= Status
;
2690 return ReturnStatus
;
2695 ConSplitterTextOutOutputString (
2696 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2701 Routine Description:
2702 Write a Unicode string to the output device.
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.
2711 EFI_SUCCESS - The string was output to the device.
2712 EFI_DEVICE_ERROR - The device reported an error while attempting to output
2714 EFI_UNSUPPORTED - The output device's mode is not currently in a
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.
2723 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2725 UINTN BackSpaceCount
;
2726 EFI_STATUS ReturnStatus
;
2727 CHAR16
*TargetString
;
2729 This
->SetAttribute (This
, This
->Mode
->Attribute
);
2731 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2734 for (TargetString
= WString
; *TargetString
; TargetString
++) {
2735 if (*TargetString
== CHAR_BACKSPACE
) {
2741 if (BackSpaceCount
== 0) {
2742 TargetString
= WString
;
2744 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
2745 StrCpy (TargetString
, WString
);
2748 // return the worst status met
2750 Status
= DevNullTextOutOutputString (Private
, TargetString
);
2751 if (EFI_ERROR (Status
)) {
2752 ReturnStatus
= Status
;
2755 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2757 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2758 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
2759 Private
->TextOutList
[Index
].TextOut
,
2762 if (EFI_ERROR (Status
)) {
2763 ReturnStatus
= Status
;
2768 if (BackSpaceCount
) {
2769 gBS
->FreePool (TargetString
);
2772 return ReturnStatus
;
2777 ConSplitterTextOutTestString (
2778 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2783 Routine Description:
2784 Verifies that all characters in a Unicode string can be output to the
2788 This - Protocol instance pointer.
2789 String - The NULL-terminated Unicode string to be examined for the output
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
2801 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2803 EFI_STATUS ReturnStatus
;
2805 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2808 // return the worst status met
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
,
2816 if (EFI_ERROR (Status
)) {
2817 ReturnStatus
= Status
;
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
2826 return ReturnStatus
;
2831 ConSplitterTextOutQueryMode (
2832 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2833 IN UINTN ModeNumber
,
2839 Routine Description:
2840 Returns information for an available text mode that the output device(s)
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.
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.
2857 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2859 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2862 // Check whether param ModeNumber is valid.
2863 // ModeNumber should be within range 0 ~ MaxMode - 1.
2865 if (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) {
2866 return EFI_UNSUPPORTED
;
2869 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
2870 return EFI_UNSUPPORTED
;
2873 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
2874 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
2876 if (*Columns
<= 0 && *Rows
<= 0) {
2877 return EFI_UNSUPPORTED
;
2886 ConSplitterTextOutSetMode (
2887 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2892 Routine Description:
2893 Sets the output device(s) to a specified mode.
2896 This - Protocol instance pointer.
2897 ModeNumber - The mode number to set.
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.
2908 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2910 INT32
*TextOutModeMap
;
2911 EFI_STATUS ReturnStatus
;
2913 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2916 // Check whether param ModeNumber is valid.
2917 // ModeNumber should be within range 0 ~ MaxMode - 1.
2919 if (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) {
2920 return EFI_UNSUPPORTED
;
2923 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
2924 return EFI_UNSUPPORTED
;
2927 // If the mode is being set to the curent mode, then just clear the screen and return.
2929 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
2930 return ConSplitterTextOutClearScreen (This
);
2933 // return the worst status met
2935 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
2936 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2938 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2939 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
2940 Private
->TextOutList
[Index
].TextOut
,
2941 TextOutModeMap
[Index
]
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.
2947 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
2948 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
2951 if (EFI_ERROR (Status
)) {
2952 ReturnStatus
= Status
;
2957 // The DevNull Console will support any possible mode as it allocates memory
2959 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
2960 if (EFI_ERROR (Status
)) {
2961 ReturnStatus
= Status
;
2964 return ReturnStatus
;
2969 ConSplitterTextOutSetAttribute (
2970 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2975 Routine Description:
2976 Sets the background and foreground colors for the OutputString () and
2977 ClearScreen () functions.
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.
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.
2994 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2996 EFI_STATUS ReturnStatus
;
2998 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3001 // Check whether param Attribute is valid.
3003 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3004 return EFI_UNSUPPORTED
;
3008 // return the worst status met
3010 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3012 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3013 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3014 Private
->TextOutList
[Index
].TextOut
,
3017 if (EFI_ERROR (Status
)) {
3018 ReturnStatus
= Status
;
3023 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3025 return ReturnStatus
;
3030 ConSplitterTextOutClearScreen (
3031 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
3035 Routine Description:
3036 Clears the output device(s) display to the currently selected background
3040 This - Protocol instance pointer.
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.
3051 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3053 EFI_STATUS ReturnStatus
;
3055 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3058 // return the worst status met
3060 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
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
;
3070 Status
= DevNullTextOutClearScreen (Private
);
3071 if (EFI_ERROR (Status
)) {
3072 ReturnStatus
= Status
;
3075 return ReturnStatus
;
3080 ConSplitterTextOutSetCursorPosition (
3081 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3087 Routine Description:
3088 Sets the current coordinates of the cursor position
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
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.
3106 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3108 EFI_STATUS ReturnStatus
;
3112 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3114 MaxColumn
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Columns
;
3115 MaxRow
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Rows
;
3117 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3118 return EFI_UNSUPPORTED
;
3121 // return the worst status met
3123 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3125 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3126 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3127 Private
->TextOutList
[Index
].TextOut
,
3131 if (EFI_ERROR (Status
)) {
3132 ReturnStatus
= Status
;
3137 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3139 return ReturnStatus
;
3144 ConSplitterTextOutEnableCursor (
3145 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3150 Routine Description:
3151 Makes the cursor visible or invisible
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.
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
3163 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3168 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3170 EFI_STATUS ReturnStatus
;
3172 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3175 // return the worst status met
3177 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3179 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3180 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3181 Private
->TextOutList
[Index
].TextOut
,
3184 if (EFI_ERROR (Status
)) {
3185 ReturnStatus
= Status
;
3190 DevNullTextOutEnableCursor (Private
, Visible
);
3192 return ReturnStatus
;