2 Console Splitter Driver. Any Handle that attatched
3 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
5 So far it works like any other driver by opening a SimpleTextIn and/or
6 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
7 difference is this driver does not layer a protocol on the passed in
8 handle, or construct a child handle like a standard device or bus driver.
9 This driver produces three virtual handles as children, one for console input
10 splitter, one for console output splitter and one for error output splitter.
11 EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
12 identify the splitter type.
14 Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
15 and Console I/O protocol, will be produced in the driver entry point.
16 The virtual handle are added on driver entry and never removed.
17 Such design ensures sytem function well during none console device situation.
19 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
20 All rights reserved. This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 #include "ConSplitter.h"
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
36 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
39 ConSplitterTextInReset
,
40 ConSplitterTextInReadKeyStroke
,
44 (EFI_SIMPLE_TEXT_IN_PROTOCOL
**) NULL
,
48 ConSplitterSimplePointerReset
,
49 ConSplitterSimplePointerGetState
,
51 (EFI_SIMPLE_POINTER_MODE
*) NULL
61 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
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
84 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
85 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
88 ConSplitterTextOutReset
,
89 ConSplitterTextOutOutputString
,
90 ConSplitterTextOutTestString
,
91 ConSplitterTextOutQueryMode
,
92 ConSplitterTextOutSetMode
,
93 ConSplitterTextOutSetAttribute
,
94 ConSplitterTextOutClearScreen
,
95 ConSplitterTextOutSetCursorPosition
,
96 ConSplitterTextOutEnableCursor
,
97 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
108 ConSpliterGraphicsOutputQueryMode
,
109 ConSpliterGraphicsOutputSetMode
,
110 ConSpliterGraphicsOutputBlt
,
113 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
114 (TEXT_OUT_GOP_MODE
*) NULL
,
118 ConSpliterConsoleControlGetMode
,
119 ConSpliterConsoleControlSetMode
,
120 ConSpliterConsoleControlLockStdIn
124 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
126 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
130 EfiConsoleControlScreenText
,
137 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
138 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
141 ConSplitterTextOutReset
,
142 ConSplitterTextOutOutputString
,
143 ConSplitterTextOutTestString
,
144 ConSplitterTextOutQueryMode
,
145 ConSplitterTextOutSetMode
,
146 ConSplitterTextOutSetAttribute
,
147 ConSplitterTextOutClearScreen
,
148 ConSplitterTextOutSetCursorPosition
,
149 ConSplitterTextOutEnableCursor
,
150 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
161 ConSpliterGraphicsOutputQueryMode
,
162 ConSpliterGraphicsOutputSetMode
,
163 ConSpliterGraphicsOutputBlt
,
166 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
167 (TEXT_OUT_GOP_MODE
*) NULL
,
171 ConSpliterConsoleControlGetMode
,
172 ConSpliterConsoleControlSetMode
,
173 ConSpliterConsoleControlLockStdIn
177 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
179 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
183 EfiConsoleControlScreenText
,
190 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
191 ConSplitterConInDriverBindingSupported
,
192 ConSplitterConInDriverBindingStart
,
193 ConSplitterConInDriverBindingStop
,
199 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
200 ConSplitterSimplePointerDriverBindingSupported
,
201 ConSplitterSimplePointerDriverBindingStart
,
202 ConSplitterSimplePointerDriverBindingStop
,
208 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
209 ConSplitterConOutDriverBindingSupported
,
210 ConSplitterConOutDriverBindingStart
,
211 ConSplitterConOutDriverBindingStop
,
217 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
218 ConSplitterStdErrDriverBindingSupported
,
219 ConSplitterStdErrDriverBindingStart
,
220 ConSplitterStdErrDriverBindingStop
,
228 ConSplitterDriverEntry (
229 IN EFI_HANDLE ImageHandle
,
230 IN EFI_SYSTEM_TABLE
*SystemTable
235 Intialize a virtual console device to act as an agrigator of physical console
239 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
240 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
249 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
250 // The virtual handles will always exist even if no console exist in the
251 // system. This is need to support hotplug devices like USB.
254 // Create virtual device handle for StdErr Splitter
256 Status
= ConSplitterTextOutConstructor (&mStdErr
);
257 if (!EFI_ERROR (Status
)) {
258 Status
= gBS
->InstallMultipleProtocolInterfaces (
259 &mStdErr
.VirtualHandle
,
260 &gEfiSimpleTextOutProtocolGuid
,
262 &gEfiPrimaryStandardErrorDeviceGuid
,
268 // Create virtual device handle for ConIn Splitter
270 Status
= ConSplitterTextInConstructor (&mConIn
);
271 if (!EFI_ERROR (Status
)) {
272 Status
= gBS
->InstallMultipleProtocolInterfaces (
273 &mConIn
.VirtualHandle
,
274 &gEfiSimpleTextInProtocolGuid
,
276 &gEfiSimplePointerProtocolGuid
,
277 &mConIn
.SimplePointer
,
278 &gEfiPrimaryConsoleInDeviceGuid
,
282 if (!EFI_ERROR (Status
)) {
284 // Update the EFI System Table with new virtual console
286 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
287 gST
->ConIn
= &mConIn
.TextIn
;
291 // Create virtual device handle for ConOut Splitter
293 Status
= ConSplitterTextOutConstructor (&mConOut
);
294 if (!EFI_ERROR (Status
)) {
296 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
298 Status
= gBS
->InstallMultipleProtocolInterfaces (
299 &mConOut
.VirtualHandle
,
300 &gEfiSimpleTextOutProtocolGuid
,
302 &gEfiGraphicsOutputProtocolGuid
,
303 &mConOut
.GraphicsOutput
,
304 &gEfiConsoleControlProtocolGuid
,
305 &mConOut
.ConsoleControl
,
306 &gEfiPrimaryConsoleOutDeviceGuid
,
311 if (!EFI_ERROR (Status
)) {
313 // Update the EFI System Table with new virtual console
315 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
316 gST
->ConOut
= &mConOut
.TextOut
;
321 // Update the CRC32 in the EFI System Table header
324 gBS
->CalculateCrc32 (
334 ConSplitterTextInConstructor (
335 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
341 Construct the ConSplitter.
345 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
348 EFI_OUT_OF_RESOURCES - Out of resources.
355 // Initilize console input splitter's private data.
357 Status
= ConSplitterGrowBuffer (
358 sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL
*),
359 &ConInPrivate
->TextInListCount
,
360 (VOID
**) &ConInPrivate
->TextInList
362 if (EFI_ERROR (Status
)) {
363 return EFI_OUT_OF_RESOURCES
;
366 // Create Event to support locking StdIn Device
368 Status
= gBS
->CreateEvent (
369 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
371 ConSpliterConsoleControlLockStdInEvent
,
373 &ConInPrivate
->LockEvent
375 ASSERT_EFI_ERROR (Status
);
377 Status
= gBS
->CreateEvent (
380 ConSplitterTextInWaitForKey
,
382 &ConInPrivate
->TextIn
.WaitForKey
384 ASSERT_EFI_ERROR (Status
);
386 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
388 Status
= ConSplitterGrowBuffer (
389 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
390 &ConInPrivate
->PointerListCount
,
391 (VOID
**) &ConInPrivate
->PointerList
393 if (EFI_ERROR (Status
)) {
394 return EFI_OUT_OF_RESOURCES
;
397 Status
= gBS
->CreateEvent (
400 ConSplitterSimplePointerWaitForInput
,
402 &ConInPrivate
->SimplePointer
.WaitForInput
409 ConSplitterTextOutConstructor (
410 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
416 // Initilize console output splitter's private data.
418 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
420 Status
= ConSplitterGrowBuffer (
421 sizeof (TEXT_OUT_AND_GOP_DATA
),
422 &ConOutPrivate
->TextOutListCount
,
423 (VOID
**) &ConOutPrivate
->TextOutList
425 if (EFI_ERROR (Status
)) {
426 return EFI_OUT_OF_RESOURCES
;
429 Status
= ConSplitterGrowBuffer (
430 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
431 &ConOutPrivate
->TextOutQueryDataCount
,
432 (VOID
**) &ConOutPrivate
->TextOutQueryData
434 if (EFI_ERROR (Status
)) {
435 return EFI_OUT_OF_RESOURCES
;
438 // Setup the DevNullTextOut console to 80 x 25
440 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
441 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
442 DevNullTextOutSetMode (ConOutPrivate
, 0);
445 // Setup resource for mode information in Graphics Output Protocol interface
447 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
448 return EFI_OUT_OF_RESOURCES
;
450 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
451 return EFI_OUT_OF_RESOURCES
;
454 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
456 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
457 return EFI_OUT_OF_RESOURCES
;
459 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
460 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
463 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
464 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
465 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
467 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
468 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
469 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
470 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
471 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
473 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
475 // Initial current mode to unknow state, and then set to mode 0
477 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
478 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
485 ConSplitterSupported (
486 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
487 IN EFI_HANDLE ControllerHandle
,
493 Generic Supported Check
496 This - Pointer to protocol.
497 ControllerHandle - Controller Handle.
502 EFI_UNSUPPORTED - unsupported.
503 EFI_SUCCESS - operation is OK.
511 // Make sure the Console Splitter does not attempt to attach to itself
513 if (ControllerHandle
== mConIn
.VirtualHandle
) {
514 return EFI_UNSUPPORTED
;
517 if (ControllerHandle
== mConOut
.VirtualHandle
) {
518 return EFI_UNSUPPORTED
;
521 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
522 return EFI_UNSUPPORTED
;
525 // Check to see whether the handle has the ConsoleInDevice GUID on it
527 Status
= gBS
->OpenProtocol (
531 This
->DriverBindingHandle
,
533 EFI_OPEN_PROTOCOL_BY_DRIVER
536 if (EFI_ERROR (Status
)) {
543 This
->DriverBindingHandle
,
552 ConSplitterConInDriverBindingSupported (
553 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
554 IN EFI_HANDLE ControllerHandle
,
555 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
560 Console In Supported Check
563 This - Pointer to protocol.
564 ControllerHandle - Controller handle.
565 RemainingDevicePath - Remaining device path.
573 return ConSplitterSupported (
576 &gEfiConsoleInDeviceGuid
582 ConSplitterSimplePointerDriverBindingSupported (
583 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
584 IN EFI_HANDLE ControllerHandle
,
585 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
590 Standard Error Supported Check
593 This - Pointer to protocol.
594 ControllerHandle - Controller handle.
595 RemainingDevicePath - Remaining device path.
603 return ConSplitterSupported (
606 &gEfiSimplePointerProtocolGuid
612 ConSplitterConOutDriverBindingSupported (
613 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
614 IN EFI_HANDLE ControllerHandle
,
615 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
620 Console Out Supported Check
623 This - Pointer to protocol.
624 ControllerHandle - Controller handle.
625 RemainingDevicePath - Remaining device path.
633 return ConSplitterSupported (
636 &gEfiConsoleOutDeviceGuid
642 ConSplitterStdErrDriverBindingSupported (
643 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
644 IN EFI_HANDLE ControllerHandle
,
645 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
650 Standard Error Supported Check
653 This - Pointer to protocol.
654 ControllerHandle - Controller handle.
655 RemainingDevicePath - Remaining device path.
663 return ConSplitterSupported (
666 &gEfiStandardErrorDeviceGuid
674 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
675 IN EFI_HANDLE ControllerHandle
,
676 IN EFI_HANDLE ConSplitterVirtualHandle
,
677 IN EFI_GUID
*DeviceGuid
,
678 IN EFI_GUID
*InterfaceGuid
,
684 Start ConSplitter on ControllerHandle, and create the virtual
685 agrogated console device on first call Start for a SimpleTextIn handle.
688 (Standard DriverBinding Protocol Start() function)
691 EFI_ERROR if a SimpleTextIn protocol is not started.
699 // Check to see whether the handle has the ConsoleInDevice GUID on it
701 Status
= gBS
->OpenProtocol (
705 This
->DriverBindingHandle
,
707 EFI_OPEN_PROTOCOL_BY_DRIVER
709 if (EFI_ERROR (Status
)) {
713 Status
= gBS
->OpenProtocol (
717 This
->DriverBindingHandle
,
718 ConSplitterVirtualHandle
,
719 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
721 if (EFI_ERROR (Status
)) {
725 return gBS
->OpenProtocol (
729 This
->DriverBindingHandle
,
730 ConSplitterVirtualHandle
,
731 EFI_OPEN_PROTOCOL_GET_PROTOCOL
737 ConSplitterConInDriverBindingStart (
738 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
739 IN EFI_HANDLE ControllerHandle
,
740 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
745 Start ConSplitter on ControllerHandle, and create the virtual
746 agrogated console device on first call Start for a SimpleTextIn handle.
749 This - Pointer to protocol.
750 ControllerHandle - Controller handle.
751 RemainingDevicePath - Remaining device path.
756 EFI_ERROR if a SimpleTextIn protocol is not started.
761 EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
;
764 // Start ConSplitter on ControllerHandle, and create the virtual
765 // agrogated console device on first call Start for a SimpleTextIn handle.
767 Status
= ConSplitterStart (
770 mConIn
.VirtualHandle
,
771 &gEfiConsoleInDeviceGuid
,
772 &gEfiSimpleTextInProtocolGuid
,
775 if (EFI_ERROR (Status
)) {
779 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
784 ConSplitterSimplePointerDriverBindingStart (
785 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
786 IN EFI_HANDLE ControllerHandle
,
787 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
792 Start ConSplitter on ControllerHandle, and create the virtual
793 agrogated console device on first call Start for a SimpleTextIn handle.
796 This - Pointer to protocol.
797 ControllerHandle - Controller handle.
798 RemainingDevicePath - Remaining device path.
802 EFI_ERROR if a SimpleTextIn protocol is not started.
807 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
809 Status
= ConSplitterStart (
812 mConIn
.VirtualHandle
,
813 &gEfiSimplePointerProtocolGuid
,
814 &gEfiSimplePointerProtocolGuid
,
815 (VOID
**) &SimplePointer
817 if (EFI_ERROR (Status
)) {
821 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
826 ConSplitterConOutDriverBindingStart (
827 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
828 IN EFI_HANDLE ControllerHandle
,
829 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
834 Start ConSplitter on ControllerHandle, and create the virtual
835 agrogated console device on first call Start for a SimpleTextIn handle.
838 This - Pointer to protocol.
839 ControllerHandle - Controller handle.
840 RemainingDevicePath - Remaining device path.
843 EFI_ERROR if a SimpleTextIn protocol is not started.
848 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
849 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
850 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
852 Status
= ConSplitterStart (
855 mConOut
.VirtualHandle
,
856 &gEfiConsoleOutDeviceGuid
,
857 &gEfiSimpleTextOutProtocolGuid
,
860 if (EFI_ERROR (Status
)) {
864 // Try to Open Graphics Output protocol
866 Status
= gBS
->OpenProtocol (
868 &gEfiGraphicsOutputProtocolGuid
,
869 (VOID
**) &GraphicsOutput
,
870 This
->DriverBindingHandle
,
871 mConOut
.VirtualHandle
,
872 EFI_OPEN_PROTOCOL_GET_PROTOCOL
874 if (EFI_ERROR (Status
)) {
875 GraphicsOutput
= NULL
;
878 // Open UGA_DRAW protocol
880 Status
= gBS
->OpenProtocol (
882 &gEfiUgaDrawProtocolGuid
,
884 This
->DriverBindingHandle
,
885 mConOut
.VirtualHandle
,
886 EFI_OPEN_PROTOCOL_GET_PROTOCOL
888 if (EFI_ERROR (Status
)) {
892 // If both ConOut and StdErr incorporate the same Text Out device,
893 // their MaxMode and QueryData should be the intersection of both.
895 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
896 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
903 ConSplitterStdErrDriverBindingStart (
904 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
905 IN EFI_HANDLE ControllerHandle
,
906 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
911 Start ConSplitter on ControllerHandle, and create the virtual
912 agrogated console device on first call Start for a SimpleTextIn handle.
915 This - Pointer to protocol.
916 ControllerHandle - Controller handle.
917 RemainingDevicePath - Remaining device path.
920 EFI_ERROR if a SimpleTextIn protocol is not started.
925 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
927 Status
= ConSplitterStart (
930 mStdErr
.VirtualHandle
,
931 &gEfiStandardErrorDeviceGuid
,
932 &gEfiSimpleTextOutProtocolGuid
,
935 if (EFI_ERROR (Status
)) {
939 // If both ConOut and StdErr incorporate the same Text Out device,
940 // their MaxMode and QueryData should be the intersection of both.
942 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
943 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
944 if (EFI_ERROR (Status
)) {
948 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
949 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
950 gST
->StdErr
= &mStdErr
.TextOut
;
952 // Update the CRC32 in the EFI System Table header
955 gBS
->CalculateCrc32 (
969 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
970 IN EFI_HANDLE ControllerHandle
,
971 IN EFI_HANDLE ConSplitterVirtualHandle
,
972 IN EFI_GUID
*DeviceGuid
,
973 IN EFI_GUID
*InterfaceGuid
,
981 (Standard DriverBinding Protocol Stop() function)
991 Status
= gBS
->OpenProtocol (
995 This
->DriverBindingHandle
,
997 EFI_OPEN_PROTOCOL_GET_PROTOCOL
999 if (EFI_ERROR (Status
)) {
1003 // close the protocol refered.
1005 gBS
->CloseProtocol (
1008 This
->DriverBindingHandle
,
1009 ConSplitterVirtualHandle
1011 gBS
->CloseProtocol (
1014 This
->DriverBindingHandle
,
1023 ConSplitterConInDriverBindingStop (
1024 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1025 IN EFI_HANDLE ControllerHandle
,
1026 IN UINTN NumberOfChildren
,
1027 IN EFI_HANDLE
*ChildHandleBuffer
1031 Routine Description:
1034 (Standard DriverBinding Protocol Stop() function)
1043 EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
;
1045 if (NumberOfChildren
== 0) {
1049 Status
= ConSplitterStop (
1052 mConIn
.VirtualHandle
,
1053 &gEfiConsoleInDeviceGuid
,
1054 &gEfiSimpleTextInProtocolGuid
,
1057 if (EFI_ERROR (Status
)) {
1061 // Delete this console input device's data structures.
1063 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1068 ConSplitterSimplePointerDriverBindingStop (
1069 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1070 IN EFI_HANDLE ControllerHandle
,
1071 IN UINTN NumberOfChildren
,
1072 IN EFI_HANDLE
*ChildHandleBuffer
1076 Routine Description:
1079 (Standard DriverBinding Protocol Stop() function)
1088 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1090 if (NumberOfChildren
== 0) {
1094 Status
= ConSplitterStop (
1097 mConIn
.VirtualHandle
,
1098 &gEfiSimplePointerProtocolGuid
,
1099 &gEfiSimplePointerProtocolGuid
,
1100 (VOID
**) &SimplePointer
1102 if (EFI_ERROR (Status
)) {
1106 // Delete this console input device's data structures.
1108 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1113 ConSplitterConOutDriverBindingStop (
1114 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1115 IN EFI_HANDLE ControllerHandle
,
1116 IN UINTN NumberOfChildren
,
1117 IN EFI_HANDLE
*ChildHandleBuffer
1121 Routine Description:
1124 (Standard DriverBinding Protocol Stop() function)
1133 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1135 if (NumberOfChildren
== 0) {
1139 Status
= ConSplitterStop (
1142 mConOut
.VirtualHandle
,
1143 &gEfiConsoleOutDeviceGuid
,
1144 &gEfiSimpleTextOutProtocolGuid
,
1147 if (EFI_ERROR (Status
)) {
1152 // Delete this console output device's data structures.
1154 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1159 ConSplitterStdErrDriverBindingStop (
1160 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1161 IN EFI_HANDLE ControllerHandle
,
1162 IN UINTN NumberOfChildren
,
1163 IN EFI_HANDLE
*ChildHandleBuffer
1167 Routine Description:
1170 (Standard DriverBinding Protocol Stop() function)
1174 EFI_SUCCESS - Complete successfully.
1179 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1181 if (NumberOfChildren
== 0) {
1185 Status
= ConSplitterStop (
1188 mStdErr
.VirtualHandle
,
1189 &gEfiStandardErrorDeviceGuid
,
1190 &gEfiSimpleTextOutProtocolGuid
,
1193 if (EFI_ERROR (Status
)) {
1197 // Delete this console error out device's data structures.
1199 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1200 if (EFI_ERROR (Status
)) {
1204 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1205 gST
->StandardErrorHandle
= NULL
;
1208 // Update the CRC32 in the EFI System Table header
1211 gBS
->CalculateCrc32 (
1212 (UINT8
*) &gST
->Hdr
,
1213 gST
->Hdr
.HeaderSize
,
1222 ConSplitterGrowBuffer (
1223 IN UINTN SizeOfCount
,
1225 IN OUT VOID
**Buffer
1229 Routine Description:
1230 Take the passed in Buffer of size SizeOfCount and grow the buffer
1231 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1232 bytes. Copy the current data in Buffer to the new version of Buffer
1233 and free the old version of buffer.
1237 SizeOfCount - Size of element in array
1238 Count - Current number of elements in array
1239 Buffer - Bigger version of passed in Buffer with all the data
1242 EFI_SUCCESS - Buffer size has grown
1243 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1254 // grow the buffer to new buffer size,
1255 // copy the old buffer's content to the new-size buffer,
1256 // then free the old buffer.
1258 OldSize
= *Count
* SizeOfCount
;
1259 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1260 NewSize
= *Count
* SizeOfCount
;
1262 Ptr
= AllocateZeroPool (NewSize
);
1264 return EFI_OUT_OF_RESOURCES
;
1267 CopyMem (Ptr
, *Buffer
, OldSize
);
1269 if (*Buffer
!= NULL
) {
1279 ConSplitterTextInAddDevice (
1280 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1281 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
1285 Routine Description:
1292 EFI_OUT_OF_RESOURCES
1299 // If the Text In List is full, enlarge it by calling growbuffer().
1301 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1302 Status
= ConSplitterGrowBuffer (
1303 sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL
*),
1304 &Private
->TextInListCount
,
1305 (VOID
**) &Private
->TextInList
1307 if (EFI_ERROR (Status
)) {
1308 return EFI_OUT_OF_RESOURCES
;
1312 // Add the new text-in device data structure into the Text In List.
1314 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1315 Private
->CurrentNumberOfConsoles
++;
1318 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1320 gBS
->CheckEvent (TextIn
->WaitForKey
);
1326 ConSplitterTextInDeleteDevice (
1327 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1328 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
1332 Routine Description:
1345 // Remove the specified text-in device data structure from the Text In List,
1346 // and rearrange the remaining data structures in the Text In List.
1348 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1349 if (Private
->TextInList
[Index
] == TextIn
) {
1350 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1351 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1354 Private
->CurrentNumberOfConsoles
--;
1359 return EFI_NOT_FOUND
;
1363 ConSplitterSimplePointerAddDevice (
1364 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1365 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1369 Routine Description:
1375 EFI_OUT_OF_RESOURCES
1383 // If the Text In List is full, enlarge it by calling growbuffer().
1385 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1386 Status
= ConSplitterGrowBuffer (
1387 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1388 &Private
->PointerListCount
,
1389 (VOID
**) &Private
->PointerList
1391 if (EFI_ERROR (Status
)) {
1392 return EFI_OUT_OF_RESOURCES
;
1396 // Add the new text-in device data structure into the Text In List.
1398 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1399 Private
->CurrentNumberOfPointers
++;
1404 ConSplitterSimplePointerDeleteDevice (
1405 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1406 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1410 Routine Description:
1422 // Remove the specified text-in device data structure from the Text In List,
1423 // and rearrange the remaining data structures in the Text In List.
1425 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1426 if (Private
->PointerList
[Index
] == SimplePointer
) {
1427 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1428 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1431 Private
->CurrentNumberOfPointers
--;
1436 return EFI_NOT_FOUND
;
1441 ConSplitterGrowMapTable (
1442 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1446 Routine Description:
1459 INT32
*TextOutModeMap
;
1460 INT32
*OldTextOutModeMap
;
1464 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1465 OldTextOutModeMap
= Private
->TextOutModeMap
;
1466 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1468 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1469 if (TextOutModeMap
== NULL
) {
1470 return EFI_OUT_OF_RESOURCES
;
1473 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1474 Private
->TextOutModeMap
= TextOutModeMap
;
1477 // If TextOutList has been enlarged, need to realloc the mode map table
1478 // The mode map table is regarded as a two dimension array.
1481 // 0 ---------> TextOutListCount ----> TextOutListCount
1482 // | -------------------------------------------
1489 // -------------------------------------------
1492 if (OldTextOutModeMap
!= NULL
) {
1494 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1496 SrcAddress
= OldTextOutModeMap
;
1499 // Copy the old data to the new one
1501 while (Index
< Private
->TextOutMode
.MaxMode
) {
1502 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1503 TextOutModeMap
+= NewSize
;
1508 // Free the old buffer
1510 FreePool (OldTextOutModeMap
);
1518 ConSplitterAddOutputMode (
1519 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1520 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1524 Routine Description:
1539 MaxMode
= TextOut
->Mode
->MaxMode
;
1540 Private
->TextOutMode
.MaxMode
= MaxMode
;
1543 // Grow the buffer if query data buffer is not large enough to
1544 // hold all the mode supported by the first console.
1546 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1547 Status
= ConSplitterGrowBuffer (
1548 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1549 &Private
->TextOutQueryDataCount
,
1550 (VOID
**) &Private
->TextOutQueryData
1552 if (EFI_ERROR (Status
)) {
1553 return EFI_OUT_OF_RESOURCES
;
1557 // Allocate buffer for the output mode map
1559 Status
= ConSplitterGrowMapTable (Private
);
1560 if (EFI_ERROR (Status
)) {
1561 return EFI_OUT_OF_RESOURCES
;
1564 // As the first textout device, directly add the mode in to QueryData
1565 // and at the same time record the mapping between QueryData and TextOut.
1569 while (Mode
< MaxMode
) {
1570 TextOut
->QueryMode (
1573 &Private
->TextOutQueryData
[Mode
].Columns
,
1574 &Private
->TextOutQueryData
[Mode
].Rows
1576 Private
->TextOutModeMap
[Index
] = Mode
;
1578 Index
+= Private
->TextOutListCount
;
1586 ConSplitterGetIntersection (
1587 IN INT32
*TextOutModeMap
,
1588 IN INT32
*NewlyAddedMap
,
1589 IN UINTN MapStepSize
,
1590 IN UINTN NewMapStepSize
,
1592 OUT INT32
*CurrentMode
1596 INT32
*CurrentMapEntry
;
1597 INT32
*NextMapEntry
;
1598 INT32 CurrentMaxMode
;
1602 CurrentMapEntry
= TextOutModeMap
;
1603 NextMapEntry
= TextOutModeMap
;
1604 CurrentMaxMode
= *MaxMode
;
1605 Mode
= *CurrentMode
;
1607 while (Index
< CurrentMaxMode
) {
1608 if (*NewlyAddedMap
== -1) {
1610 // This mode is not supported any more. Remove it. Special care
1611 // must be taken as this remove will also affect current mode;
1613 if (Index
== *CurrentMode
) {
1615 } else if (Index
< *CurrentMode
) {
1620 if (CurrentMapEntry
!= NextMapEntry
) {
1621 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1624 NextMapEntry
+= MapStepSize
;
1627 CurrentMapEntry
+= MapStepSize
;
1628 NewlyAddedMap
+= NewMapStepSize
;
1632 *CurrentMode
= Mode
;
1639 ConSplitterSyncOutputMode (
1640 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1641 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1645 Routine Description:
1648 Private - Private data structure.
1649 TextOut - Text Out Protocol.
1656 INT32 CurrentMaxMode
;
1659 INT32
*TextOutModeMap
;
1661 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1667 // Must make sure that current mode won't change even if mode number changes
1669 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1670 TextOutModeMap
= Private
->TextOutModeMap
;
1671 StepSize
= Private
->TextOutListCount
;
1672 TextOutQueryData
= Private
->TextOutQueryData
;
1675 // Query all the mode that the newly added TextOut supports
1678 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1679 while (Mode
< TextOut
->Mode
->MaxMode
) {
1680 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1683 // Search the QueryData database to see if they intersects
1686 while (Index
< CurrentMaxMode
) {
1687 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1688 MapTable
[Index
* StepSize
] = Mode
;
1698 // Now search the TextOutModeMap table to find the intersection of supported
1699 // mode between ConSplitter and the newly added device.
1701 ConSplitterGetIntersection (
1706 &Private
->TextOutMode
.MaxMode
,
1707 &Private
->TextOutMode
.Mode
1715 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1720 Routine Description:
1727 EFI_OUT_OF_RESOURCES
1731 UINTN ConOutNumOfConsoles
;
1732 UINTN StdErrNumOfConsoles
;
1733 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
1734 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
1739 INT32 ConOutMaxMode
;
1740 INT32 StdErrMaxMode
;
1743 INT32
*ConOutModeMap
;
1744 INT32
*StdErrModeMap
;
1745 INT32
*ConOutMapTable
;
1746 INT32
*StdErrMapTable
;
1747 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
1748 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
1749 BOOLEAN FoundTheSameTextOut
;
1750 UINTN ConOutMapTableSize
;
1751 UINTN StdErrMapTableSize
;
1753 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1754 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1755 ConOutTextOutList
= mConOut
.TextOutList
;
1756 StdErrTextOutList
= mStdErr
.TextOutList
;
1759 FoundTheSameTextOut
= FALSE
;
1760 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1762 while (Indexj
< StdErrNumOfConsoles
) {
1763 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1764 FoundTheSameTextOut
= TRUE
;
1769 StdErrTextOutList
++;
1773 ConOutTextOutList
++;
1776 if (!FoundTheSameTextOut
) {
1780 // Must make sure that current mode won't change even if mode number changes
1782 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1783 ConOutModeMap
= mConOut
.TextOutModeMap
;
1784 ConOutQueryData
= mConOut
.TextOutQueryData
;
1786 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1787 StdErrModeMap
= mStdErr
.TextOutModeMap
;
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 FreePool (ConOutMapTable
);
1862 FreePool (StdErrMapTable
);
1869 ConSplitterAddGraphicsOutputMode (
1870 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1871 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1872 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1876 Routine Description:
1888 TEXT_OUT_GOP_MODE
*Mode
;
1890 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
1891 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
1892 TEXT_OUT_GOP_MODE
*ModeBuffer
;
1893 TEXT_OUT_GOP_MODE
*MatchedMode
;
1897 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
1898 return EFI_UNSUPPORTED
;
1901 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
1903 if (GraphicsOutput
!= NULL
) {
1904 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
1906 // This is the first Graphics Output device added
1908 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
1909 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
1910 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
1911 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
1912 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
1913 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
1916 // Allocate resource for the private mode buffer
1918 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
1919 if (ModeBuffer
== NULL
) {
1920 return EFI_OUT_OF_RESOURCES
;
1922 FreePool (Private
->GraphicsOutputModeBuffer
);
1923 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
1926 // Store all supported display modes to the private mode buffer
1929 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
1930 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
1931 if (EFI_ERROR (Status
)) {
1934 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
1935 Mode
->VerticalResolution
= Info
->VerticalResolution
;
1941 // Check intersection of display mode
1943 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
1944 if (ModeBuffer
== NULL
) {
1945 return EFI_OUT_OF_RESOURCES
;
1948 MatchedMode
= ModeBuffer
;
1949 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
1950 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
1953 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
1954 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
1955 if (EFI_ERROR (Status
)) {
1958 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
1959 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
1968 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
1976 // Drop the old mode buffer, assign it to a new one
1978 FreePool (Private
->GraphicsOutputModeBuffer
);
1979 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
1982 // Physical frame buffer is no longer available when there are more than one physical GOP devices
1984 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
1985 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
1986 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
1987 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1988 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
1989 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
1993 // Select a prefered Display mode 800x600
1995 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
1996 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
1997 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2002 // Prefered mode is not found, set to mode 0
2004 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2009 // Current mode number may need update now, so set it to an invalide mode number
2011 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2014 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2015 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2017 CurrentGraphicsOutputMode
->MaxMode
= 1;
2018 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2019 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2020 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2021 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2022 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2023 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2024 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2025 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2028 // Update the private mode buffer
2030 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2031 ModeBuffer
->HorizontalResolution
= 800;
2032 ModeBuffer
->VerticalResolution
= 600;
2035 // Current mode is unknow now, set it to an invalid mode number 0xffff
2037 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2042 // Force GraphicsOutput mode to be set,
2043 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2045 Private
->HardwareNeedsStarting
= TRUE
;
2046 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2048 Private
->CurrentNumberOfGraphicsOutput
++;
2054 ConSplitterTextOutAddDevice (
2055 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2056 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
,
2057 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2058 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2062 Routine Description:
2073 UINTN CurrentNumOfConsoles
;
2076 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2078 Status
= EFI_SUCCESS
;
2079 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2082 // If the Text Out List is full, enlarge it by calling growbuffer().
2084 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2085 Status
= ConSplitterGrowBuffer (
2086 sizeof (TEXT_OUT_AND_GOP_DATA
),
2087 &Private
->TextOutListCount
,
2088 (VOID
**) &Private
->TextOutList
2090 if (EFI_ERROR (Status
)) {
2091 return EFI_OUT_OF_RESOURCES
;
2094 // Also need to reallocate the TextOutModeMap table
2096 Status
= ConSplitterGrowMapTable (Private
);
2097 if (EFI_ERROR (Status
)) {
2098 return EFI_OUT_OF_RESOURCES
;
2102 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2104 TextAndGop
->TextOut
= TextOut
;
2105 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2106 TextAndGop
->UgaDraw
= UgaDraw
;
2108 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2110 // If No UGA device then use the ConOut device
2112 TextAndGop
->TextOutEnabled
= TRUE
;
2115 // If UGA device use ConOut device only used if UGA screen is in Text mode
2117 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2120 if (CurrentNumOfConsoles
== 0) {
2122 // Add the first device's output mode to console splitter's mode list
2124 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2126 ConSplitterSyncOutputMode (Private
, TextOut
);
2129 Private
->CurrentNumberOfConsoles
++;
2132 // Scan both TextOutList, for the intersection TextOut device
2133 // maybe both ConOut and StdErr incorporate the same Text Out
2134 // device in them, thus the output of both should be synced.
2136 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2138 CurrentMode
= Private
->TextOutMode
.Mode
;
2139 MaxMode
= Private
->TextOutMode
.MaxMode
;
2140 ASSERT (MaxMode
>= 1);
2142 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2143 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2146 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2148 // We just added a new UGA device in graphics mode
2150 DevNullGopSync (Private
, GraphicsOutput
, UgaDraw
);
2151 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2153 // The new console supports the same mode of the current console so sync up
2155 DevNullSyncGopStdOut (Private
);
2158 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2160 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2167 ConSplitterTextOutDeleteDevice (
2168 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2169 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
2173 Routine Description:
2184 UINTN CurrentNumOfConsoles
;
2185 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2189 // Remove the specified text-out device data structure from the Text out List,
2190 // and rearrange the remaining data structures in the Text out List.
2192 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2193 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2194 TextOutList
= Private
->TextOutList
;
2195 while (Index
>= 0) {
2196 if (TextOutList
->TextOut
== TextOut
) {
2197 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2198 CurrentNumOfConsoles
--;
2206 // The specified TextOut is not managed by the ConSplitter driver
2209 return EFI_NOT_FOUND
;
2212 if (CurrentNumOfConsoles
== 0) {
2214 // If the number of consoles is zero clear the Dev NULL device
2216 Private
->CurrentNumberOfConsoles
= 0;
2217 Private
->TextOutMode
.MaxMode
= 1;
2218 Private
->TextOutQueryData
[0].Columns
= 80;
2219 Private
->TextOutQueryData
[0].Rows
= 25;
2220 DevNullTextOutSetMode (Private
, 0);
2225 // Max Mode is realy an intersection of the QueryMode command to all
2226 // devices. So we must copy the QueryMode of the first device to
2230 Private
->TextOutQueryData
,
2231 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2234 FreePool (Private
->TextOutModeMap
);
2235 Private
->TextOutModeMap
= NULL
;
2236 TextOutList
= Private
->TextOutList
;
2239 // Add the first TextOut to the QueryData array and ModeMap table
2241 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2244 // Now add one by one
2247 Private
->CurrentNumberOfConsoles
= 1;
2249 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2250 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2252 Private
->CurrentNumberOfConsoles
++;
2256 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2261 // ConSplitter TextIn member functions
2265 ConSplitterTextInReset (
2266 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*This
,
2267 IN BOOLEAN ExtendedVerification
2271 Routine Description:
2272 Reset the input device and optionaly run diagnostics
2275 This - Protocol instance pointer.
2276 ExtendedVerification - Driver may perform diagnostics on reset.
2279 EFI_SUCCESS - The device was reset.
2280 EFI_DEVICE_ERROR - The device is not functioning properly and could
2286 EFI_STATUS ReturnStatus
;
2287 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2290 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2292 Private
->KeyEventSignalState
= FALSE
;
2295 // return the worst status met
2297 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2298 Status
= Private
->TextInList
[Index
]->Reset (
2299 Private
->TextInList
[Index
],
2300 ExtendedVerification
2302 if (EFI_ERROR (Status
)) {
2303 ReturnStatus
= Status
;
2307 return ReturnStatus
;
2312 ConSplitterTextInPrivateReadKeyStroke (
2313 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2314 OUT EFI_INPUT_KEY
*Key
2318 Routine Description:
2319 Reads the next keystroke from the input device. The WaitForKey Event can
2320 be used to test for existance of a keystroke via WaitForEvent () call.
2323 This - Protocol instance pointer.
2324 Key - Driver may perform diagnostics on reset.
2327 EFI_SUCCESS - The keystroke information was returned.
2328 EFI_NOT_READY - There was no keystroke data availiable.
2329 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2336 EFI_INPUT_KEY CurrentKey
;
2338 Key
->UnicodeChar
= 0;
2339 Key
->ScanCode
= SCAN_NULL
;
2342 // if no physical console input device exists, return EFI_NOT_READY;
2343 // if any physical console input device has key input,
2344 // return the key and EFI_SUCCESS.
2346 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2347 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2348 Private
->TextInList
[Index
],
2351 if (!EFI_ERROR (Status
)) {
2357 return EFI_NOT_READY
;
2361 ConSpliterConssoleControlStdInLocked (
2366 Routine Description:
2367 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2368 the only device locked.
2375 FALSE - StdIn working normally
2379 return mConIn
.PasswordEnabled
;
2384 ConSpliterConsoleControlLockStdInEvent (
2390 Routine Description:
2391 This timer event will fire when StdIn is locked. It will check the key
2392 sequence on StdIn to see if it matches the password. Any error in the
2393 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2394 TRUE the StdIn splitter will not report any input.
2397 (Standard EFI_EVENT_NOTIFY)
2406 CHAR16 BackSpaceString
[2];
2407 CHAR16 SpaceString
[2];
2410 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2411 if (!EFI_ERROR (Status
)) {
2413 // if it's an ENTER, match password
2415 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2416 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2417 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2419 // Password not match
2421 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2422 mConIn
.PwdIndex
= 0;
2425 // Key matches password sequence
2427 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2428 mConIn
.PasswordEnabled
= FALSE
;
2429 Status
= EFI_NOT_READY
;
2431 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2435 if (mConIn
.PwdIndex
> 0) {
2436 BackSpaceString
[0] = CHAR_BACKSPACE
;
2437 BackSpaceString
[1] = 0;
2439 SpaceString
[0] = ' ';
2442 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2443 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2444 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2448 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2450 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2452 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2453 if (mConIn
.PwdIndex
== 0) {
2454 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2457 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2458 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2463 } while (!EFI_ERROR (Status
));
2468 ConSpliterConsoleControlLockStdIn (
2469 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2474 Routine Description:
2475 If Password is NULL unlock the password state variable and set the event
2476 timer. If the Password is too big return an error. If the Password is valid
2477 Copy the Password and enable state variable and then arm the periodic timer
2482 EFI_SUCCESS - Lock the StdIn device
2483 EFI_INVALID_PARAMETER - Password is NULL
2484 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2488 if (Password
== NULL
) {
2489 return EFI_INVALID_PARAMETER
;
2492 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2494 // Currently have a max password size
2496 return EFI_OUT_OF_RESOURCES
;
2499 // Save the password, initialize state variables and arm event timer
2501 StrCpy (mConIn
.Password
, Password
);
2502 mConIn
.PasswordEnabled
= TRUE
;
2503 mConIn
.PwdIndex
= 0;
2504 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2511 ConSplitterTextInReadKeyStroke (
2512 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*This
,
2513 OUT EFI_INPUT_KEY
*Key
2517 Routine Description:
2518 Reads the next keystroke from the input device. The WaitForKey Event can
2519 be used to test for existance of a keystroke via WaitForEvent () call.
2520 If the ConIn is password locked make it look like no keystroke is availible
2523 This - Protocol instance pointer.
2524 Key - Driver may perform diagnostics on reset.
2527 EFI_SUCCESS - The keystroke information was returned.
2528 EFI_NOT_READY - There was no keystroke data availiable.
2529 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2534 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2536 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2537 if (Private
->PasswordEnabled
) {
2539 // If StdIn Locked return not ready
2541 return EFI_NOT_READY
;
2544 Private
->KeyEventSignalState
= FALSE
;
2546 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2551 ConSplitterTextInWaitForKey (
2557 Routine Description:
2558 This event agregates all the events of the ConIn devices in the spliter.
2559 If the ConIn is password locked then return.
2560 If any events of physical ConIn devices are signaled, signal the ConIn
2561 spliter event. This will cause the calling code to call
2562 ConSplitterTextInReadKeyStroke ().
2565 Event - The Event assoicated with callback.
2566 Context - Context registered when Event was created.
2574 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2577 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2578 if (Private
->PasswordEnabled
) {
2580 // If StdIn Locked return not ready
2586 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2588 if (Private
->KeyEventSignalState
) {
2589 gBS
->SignalEvent (Event
);
2593 // if any physical console input device has key input, signal the event.
2595 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2596 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2597 if (!EFI_ERROR (Status
)) {
2598 gBS
->SignalEvent (Event
);
2599 Private
->KeyEventSignalState
= TRUE
;
2606 ConSplitterSimplePointerReset (
2607 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2608 IN BOOLEAN ExtendedVerification
2612 Routine Description:
2613 Reset the input device and optionaly run diagnostics
2616 This - Protocol instance pointer.
2617 ExtendedVerification - Driver may perform diagnostics on reset.
2620 EFI_SUCCESS - The device was reset.
2621 EFI_DEVICE_ERROR - The device is not functioning properly and could
2627 EFI_STATUS ReturnStatus
;
2628 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2631 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2633 Private
->InputEventSignalState
= FALSE
;
2635 if (Private
->CurrentNumberOfPointers
== 0) {
2639 // return the worst status met
2641 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2642 Status
= Private
->PointerList
[Index
]->Reset (
2643 Private
->PointerList
[Index
],
2644 ExtendedVerification
2646 if (EFI_ERROR (Status
)) {
2647 ReturnStatus
= Status
;
2651 return ReturnStatus
;
2657 ConSplitterSimplePointerPrivateGetState (
2658 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2659 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2663 Routine Description:
2664 Reads the next keystroke from the input device. The WaitForKey Event can
2665 be used to test for existance of a keystroke via WaitForEvent () call.
2668 This - Protocol instance pointer.
2672 EFI_SUCCESS - The keystroke information was returned.
2673 EFI_NOT_READY - There was no keystroke data availiable.
2674 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2680 EFI_STATUS ReturnStatus
;
2682 EFI_SIMPLE_POINTER_STATE CurrentState
;
2684 State
->RelativeMovementX
= 0;
2685 State
->RelativeMovementY
= 0;
2686 State
->RelativeMovementZ
= 0;
2687 State
->LeftButton
= FALSE
;
2688 State
->RightButton
= FALSE
;
2691 // if no physical console input device exists, return EFI_NOT_READY;
2692 // if any physical console input device has key input,
2693 // return the key and EFI_SUCCESS.
2695 ReturnStatus
= EFI_NOT_READY
;
2696 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2698 Status
= Private
->PointerList
[Index
]->GetState (
2699 Private
->PointerList
[Index
],
2702 if (!EFI_ERROR (Status
)) {
2703 if (ReturnStatus
== EFI_NOT_READY
) {
2704 ReturnStatus
= EFI_SUCCESS
;
2707 if (CurrentState
.LeftButton
) {
2708 State
->LeftButton
= TRUE
;
2711 if (CurrentState
.RightButton
) {
2712 State
->RightButton
= TRUE
;
2715 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
2716 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
2719 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
2720 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
2723 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
2724 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
2726 } else if (Status
== EFI_DEVICE_ERROR
) {
2727 ReturnStatus
= EFI_DEVICE_ERROR
;
2731 return ReturnStatus
;
2736 ConSplitterSimplePointerGetState (
2737 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2738 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2742 Routine Description:
2743 Reads the next keystroke from the input device. The WaitForKey Event can
2744 be used to test for existance of a keystroke via WaitForEvent () call.
2745 If the ConIn is password locked make it look like no keystroke is availible
2748 This - Protocol instance pointer.
2752 EFI_SUCCESS - The keystroke information was returned.
2753 EFI_NOT_READY - There was no keystroke data availiable.
2754 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2759 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2761 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2762 if (Private
->PasswordEnabled
) {
2764 // If StdIn Locked return not ready
2766 return EFI_NOT_READY
;
2769 Private
->InputEventSignalState
= FALSE
;
2771 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2776 ConSplitterSimplePointerWaitForInput (
2782 Routine Description:
2783 This event agregates all the events of the ConIn devices in the spliter.
2784 If the ConIn is password locked then return.
2785 If any events of physical ConIn devices are signaled, signal the ConIn
2786 spliter event. This will cause the calling code to call
2787 ConSplitterTextInReadKeyStroke ().
2790 Event - The Event assoicated with callback.
2791 Context - Context registered when Event was created.
2799 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2802 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2803 if (Private
->PasswordEnabled
) {
2805 // If StdIn Locked return not ready
2811 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2813 if (Private
->InputEventSignalState
) {
2814 gBS
->SignalEvent (Event
);
2818 // if any physical console input device has key input, signal the event.
2820 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2821 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
2822 if (!EFI_ERROR (Status
)) {
2823 gBS
->SignalEvent (Event
);
2824 Private
->InputEventSignalState
= TRUE
;
2831 ConSplitterTextOutReset (
2832 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2833 IN BOOLEAN ExtendedVerification
2837 Routine Description:
2838 Reset the text output device hardware and optionaly run diagnostics
2841 This - Protocol instance pointer.
2842 ExtendedVerification - Driver may perform more exhaustive verfication
2843 operation of the device during reset.
2846 EFI_SUCCESS - The text output device was reset.
2847 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
2853 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2855 EFI_STATUS ReturnStatus
;
2857 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2860 // return the worst status met
2862 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2864 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2866 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
2867 Private
->TextOutList
[Index
].TextOut
,
2868 ExtendedVerification
2870 if (EFI_ERROR (Status
)) {
2871 ReturnStatus
= Status
;
2876 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
2878 Status
= DevNullTextOutSetMode (Private
, 0);
2879 if (EFI_ERROR (Status
)) {
2880 ReturnStatus
= Status
;
2883 return ReturnStatus
;
2888 ConSplitterTextOutOutputString (
2889 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2894 Routine Description:
2895 Write a Unicode string to the output device.
2898 This - Protocol instance pointer.
2899 String - The NULL-terminated Unicode string to be displayed on the output
2900 device(s). All output devices must also support the Unicode
2901 drawing defined in this file.
2904 EFI_SUCCESS - The string was output to the device.
2905 EFI_DEVICE_ERROR - The device reported an error while attempting to output
2907 EFI_UNSUPPORTED - The output device's mode is not currently in a
2909 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
2910 characters in the Unicode string could not be
2911 rendered and were skipped.
2916 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2918 UINTN BackSpaceCount
;
2919 EFI_STATUS ReturnStatus
;
2920 CHAR16
*TargetString
;
2922 This
->SetAttribute (This
, This
->Mode
->Attribute
);
2924 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2927 for (TargetString
= WString
; *TargetString
; TargetString
++) {
2928 if (*TargetString
== CHAR_BACKSPACE
) {
2934 if (BackSpaceCount
== 0) {
2935 TargetString
= WString
;
2937 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
2938 StrCpy (TargetString
, WString
);
2941 // return the worst status met
2943 Status
= DevNullTextOutOutputString (Private
, TargetString
);
2944 if (EFI_ERROR (Status
)) {
2945 ReturnStatus
= Status
;
2948 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2950 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2951 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
2952 Private
->TextOutList
[Index
].TextOut
,
2955 if (EFI_ERROR (Status
)) {
2956 ReturnStatus
= Status
;
2961 if (BackSpaceCount
) {
2962 FreePool (TargetString
);
2965 return ReturnStatus
;
2970 ConSplitterTextOutTestString (
2971 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2976 Routine Description:
2977 Verifies that all characters in a Unicode string can be output to the
2981 This - Protocol instance pointer.
2982 String - The NULL-terminated Unicode string to be examined for the output
2986 EFI_SUCCESS - The device(s) are capable of rendering the output string.
2987 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
2988 rendered by one or more of the output devices mapped
2994 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2996 EFI_STATUS ReturnStatus
;
2998 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3001 // return the worst status met
3003 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3004 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3005 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3006 Private
->TextOutList
[Index
].TextOut
,
3009 if (EFI_ERROR (Status
)) {
3010 ReturnStatus
= Status
;
3015 // There is no DevNullTextOutTestString () since a Unicode buffer would
3016 // always return EFI_SUCCESS.
3017 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3019 return ReturnStatus
;
3024 ConSplitterTextOutQueryMode (
3025 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3026 IN UINTN ModeNumber
,
3032 Routine Description:
3033 Returns information for an available text mode that the output device(s)
3037 This - Protocol instance pointer.
3038 ModeNumber - The mode number to return information on.
3039 Columns, Rows - Returns the geometry of the text output device for the
3040 requested ModeNumber.
3043 EFI_SUCCESS - The requested mode information was returned.
3044 EFI_DEVICE_ERROR - The device had an error and could not
3045 complete the request.
3046 EFI_UNSUPPORTED - The mode number was not valid.
3050 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3052 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3055 // Check whether param ModeNumber is valid.
3056 // ModeNumber should be within range 0 ~ MaxMode - 1.
3058 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3059 return EFI_UNSUPPORTED
;
3062 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3063 return EFI_UNSUPPORTED
;
3066 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3067 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3069 if (*Columns
<= 0 && *Rows
<= 0) {
3070 return EFI_UNSUPPORTED
;
3079 ConSplitterTextOutSetMode (
3080 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3085 Routine Description:
3086 Sets the output device(s) to a specified mode.
3089 This - Protocol instance pointer.
3090 ModeNumber - The mode number to set.
3093 EFI_SUCCESS - The requested text mode was set.
3094 EFI_DEVICE_ERROR - The device had an error and
3095 could not complete the request.
3096 EFI_UNSUPPORTED - The mode number was not valid.
3101 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3103 INT32
*TextOutModeMap
;
3104 EFI_STATUS ReturnStatus
;
3106 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3109 // Check whether param ModeNumber is valid.
3110 // ModeNumber should be within range 0 ~ MaxMode - 1.
3112 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3113 return EFI_UNSUPPORTED
;
3116 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3117 return EFI_UNSUPPORTED
;
3120 // If the mode is being set to the curent mode, then just clear the screen and return.
3122 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3123 return ConSplitterTextOutClearScreen (This
);
3126 // return the worst status met
3128 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3129 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3131 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3132 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3133 Private
->TextOutList
[Index
].TextOut
,
3134 TextOutModeMap
[Index
]
3137 // If this console device is based on a UGA device, then sync up the bitmap from
3138 // the UGA splitter and reclear the text portion of the display in the new mode.
3140 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3141 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3144 if (EFI_ERROR (Status
)) {
3145 ReturnStatus
= Status
;
3150 // The DevNull Console will support any possible mode as it allocates memory
3152 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3153 if (EFI_ERROR (Status
)) {
3154 ReturnStatus
= Status
;
3157 return ReturnStatus
;
3162 ConSplitterTextOutSetAttribute (
3163 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3168 Routine Description:
3169 Sets the background and foreground colors for the OutputString () and
3170 ClearScreen () functions.
3173 This - Protocol instance pointer.
3174 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3175 bits 4..6 are the background color. All other bits are undefined
3176 and must be zero. The valid Attributes are defined in this file.
3179 EFI_SUCCESS - The attribute was set.
3180 EFI_DEVICE_ERROR - The device had an error and
3181 could not complete the request.
3182 EFI_UNSUPPORTED - The attribute requested is not defined.
3187 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3189 EFI_STATUS ReturnStatus
;
3191 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3194 // Check whether param Attribute is valid.
3196 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3197 return EFI_UNSUPPORTED
;
3201 // return the worst status met
3203 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3205 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3206 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3207 Private
->TextOutList
[Index
].TextOut
,
3210 if (EFI_ERROR (Status
)) {
3211 ReturnStatus
= Status
;
3216 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3218 return ReturnStatus
;
3223 ConSplitterTextOutClearScreen (
3224 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
3228 Routine Description:
3229 Clears the output device(s) display to the currently selected background
3233 This - Protocol instance pointer.
3236 EFI_SUCCESS - The operation completed successfully.
3237 EFI_DEVICE_ERROR - The device had an error and
3238 could not complete the request.
3239 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3244 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3246 EFI_STATUS ReturnStatus
;
3248 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3251 // return the worst status met
3253 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3255 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3256 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3257 if (EFI_ERROR (Status
)) {
3258 ReturnStatus
= Status
;
3263 Status
= DevNullTextOutClearScreen (Private
);
3264 if (EFI_ERROR (Status
)) {
3265 ReturnStatus
= Status
;
3268 return ReturnStatus
;
3273 ConSplitterTextOutSetCursorPosition (
3274 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3280 Routine Description:
3281 Sets the current coordinates of the cursor position
3284 This - Protocol instance pointer.
3285 Column, Row - the position to set the cursor to. Must be greater than or
3286 equal to zero and less than the number of columns and rows
3290 EFI_SUCCESS - The operation completed successfully.
3291 EFI_DEVICE_ERROR - The device had an error and
3292 could not complete the request.
3293 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
3294 cursor position is invalid for the current mode.
3299 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3301 EFI_STATUS ReturnStatus
;
3305 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3307 MaxColumn
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Columns
;
3308 MaxRow
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Rows
;
3310 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3311 return EFI_UNSUPPORTED
;
3314 // return the worst status met
3316 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3318 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3319 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3320 Private
->TextOutList
[Index
].TextOut
,
3324 if (EFI_ERROR (Status
)) {
3325 ReturnStatus
= Status
;
3330 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3332 return ReturnStatus
;
3337 ConSplitterTextOutEnableCursor (
3338 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3343 Routine Description:
3344 Makes the cursor visible or invisible
3347 This - Protocol instance pointer.
3348 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
3349 set to be invisible.
3352 EFI_SUCCESS - The operation completed successfully.
3353 EFI_DEVICE_ERROR - The device had an error and could not complete the
3354 request, or the device does not support changing
3356 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3361 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3363 EFI_STATUS ReturnStatus
;
3365 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3368 // return the worst status met
3370 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3372 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3373 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3374 Private
->TextOutList
[Index
].TextOut
,
3377 if (EFI_ERROR (Status
)) {
3378 ReturnStatus
= Status
;
3383 DevNullTextOutEnableCursor (Private
, Visible
);
3385 return ReturnStatus
;