2 Console Splitter Driver. Any Handle that attatched console I/O protocols
3 (Console In device, Console Out device, Console Error device, Simple Pointer
4 protocol, Absolute Pointer protocol) can be bound by this driver.
6 So far it works like any other driver by opening a SimpleTextIn and/or
7 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
8 difference is this driver does not layer a protocol on the passed in
9 handle, or construct a child handle like a standard device or bus driver.
10 This driver produces three virtual handles as children, one for console input
11 splitter, one for console output splitter and one for error output splitter.
12 These 3 virtual handles would be installed on gST.
14 Each virtual handle, that supports the Console I/O protocol, will be produced
15 in the driver entry point. The virtual handle are added on driver entry and
16 never removed. Such design ensures sytem function well during none console
19 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
20 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
21 This program and the accompanying materials
22 are licensed and made available under the terms and conditions of the BSD License
23 which accompanies this distribution. The full text of the license may be found at
24 http://opensource.org/licenses/bsd-license.php
26 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
27 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
31 #include "ConSplitter.h"
34 // Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.
35 // default not connect
37 BOOLEAN mConInIsConnect
= FALSE
;
40 // Text In Splitter Private Data template
42 GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
43 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
47 ConSplitterTextInReset
,
48 ConSplitterTextInReadKeyStroke
,
52 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
**) NULL
,
56 ConSplitterTextInResetEx
,
57 ConSplitterTextInReadKeyStrokeEx
,
59 ConSplitterTextInSetState
,
60 ConSplitterTextInRegisterKeyNotify
,
61 ConSplitterTextInUnregisterKeyNotify
64 (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
**) NULL
,
74 ConSplitterSimplePointerReset
,
75 ConSplitterSimplePointerGetState
,
77 (EFI_SIMPLE_POINTER_MODE
*) NULL
87 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
91 ConSplitterAbsolutePointerReset
,
92 ConSplitterAbsolutePointerGetState
,
94 (EFI_ABSOLUTE_POINTER_MODE
*) NULL
100 0x10000, // AbsoluteMaxX
101 0x10000, // AbsoluteMaxY
102 0x10000, // AbsoluteMaxZ
106 (EFI_ABSOLUTE_POINTER_PROTOCOL
**) NULL
,
116 // Uga Draw Protocol Private Data template
118 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL mUgaDrawProtocolTemplate
= {
119 ConSplitterUgaDrawGetMode
,
120 ConSplitterUgaDrawSetMode
,
121 ConSplitterUgaDrawBlt
125 // Graphics Output Protocol Private Data template
127 GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL mGraphicsOutputProtocolTemplate
= {
128 ConSplitterGraphicsOutputQueryMode
,
129 ConSplitterGraphicsOutputSetMode
,
130 ConSplitterGraphicsOutputBlt
,
136 // Text Out Splitter Private Data template
138 GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
139 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
142 ConSplitterTextOutReset
,
143 ConSplitterTextOutOutputString
,
144 ConSplitterTextOutTestString
,
145 ConSplitterTextOutQueryMode
,
146 ConSplitterTextOutSetMode
,
147 ConSplitterTextOutSetAttribute
,
148 ConSplitterTextOutClearScreen
,
149 ConSplitterTextOutSetCursorPosition
,
150 ConSplitterTextOutEnableCursor
,
151 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
178 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) NULL
,
183 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
185 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
191 // Standard Error Text Out Splitter Data Template
193 GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
194 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
197 ConSplitterTextOutReset
,
198 ConSplitterTextOutOutputString
,
199 ConSplitterTextOutTestString
,
200 ConSplitterTextOutQueryMode
,
201 ConSplitterTextOutSetMode
,
202 ConSplitterTextOutSetAttribute
,
203 ConSplitterTextOutClearScreen
,
204 ConSplitterTextOutSetCursorPosition
,
205 ConSplitterTextOutEnableCursor
,
206 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
233 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) NULL
,
238 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
240 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
246 // Driver binding instance for Console Input Device
248 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
249 ConSplitterConInDriverBindingSupported
,
250 ConSplitterConInDriverBindingStart
,
251 ConSplitterConInDriverBindingStop
,
258 // Driver binding instance for Console Out device
260 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
261 ConSplitterConOutDriverBindingSupported
,
262 ConSplitterConOutDriverBindingStart
,
263 ConSplitterConOutDriverBindingStop
,
270 // Driver binding instance for Standard Error device
272 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
273 ConSplitterStdErrDriverBindingSupported
,
274 ConSplitterStdErrDriverBindingStart
,
275 ConSplitterStdErrDriverBindingStop
,
282 // Driver binding instance for Simple Pointer protocol
284 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
285 ConSplitterSimplePointerDriverBindingSupported
,
286 ConSplitterSimplePointerDriverBindingStart
,
287 ConSplitterSimplePointerDriverBindingStop
,
294 // Driver binding instance for Absolute Pointer protocol
296 EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding
= {
297 ConSplitterAbsolutePointerDriverBindingSupported
,
298 ConSplitterAbsolutePointerDriverBindingStart
,
299 ConSplitterAbsolutePointerDriverBindingStop
,
306 Key notify for toggle state sync.
308 @param KeyData A pointer to a buffer that is filled in with
309 the keystroke information for the key that was
312 @retval EFI_SUCCESS Toggle state sync successfully.
317 ToggleStateSyncKeyNotify (
318 IN EFI_KEY_DATA
*KeyData
323 if (((KeyData
->KeyState
.KeyToggleState
& KEY_STATE_VALID_EXPOSED
) == KEY_STATE_VALID_EXPOSED
) &&
324 (KeyData
->KeyState
.KeyToggleState
!= mConIn
.PhysicalKeyToggleState
)) {
326 // There is toggle state change, sync to other console input devices.
328 for (Index
= 0; Index
< mConIn
.CurrentNumberOfExConsoles
; Index
++) {
329 mConIn
.TextInExList
[Index
]->SetState (
330 mConIn
.TextInExList
[Index
],
331 &KeyData
->KeyState
.KeyToggleState
334 mConIn
.PhysicalKeyToggleState
= KeyData
->KeyState
.KeyToggleState
;
335 DEBUG ((EFI_D_INFO
, "Current toggle state is 0x%02x\n", mConIn
.PhysicalKeyToggleState
));
342 Initialization for toggle state sync.
344 @param Private Text In Splitter pointer.
348 ToggleStateSyncInitialization (
349 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
352 EFI_KEY_DATA KeyData
;
356 // Initialize PhysicalKeyToggleState that will be synced to new console
357 // input device to turn on physical TextInEx partial key report for
358 // toggle state sync.
360 Private
->PhysicalKeyToggleState
= KEY_STATE_VALID_EXPOSED
;
363 // Initialize VirtualKeyStateExported to let the virtual TextInEx not report
364 // the partial key even though the physical TextInEx turns on the partial
365 // key report. The virtual TextInEx will report the partial key after it is
366 // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.
368 Private
->VirtualKeyStateExported
= FALSE
;
371 // Register key notify for toggle state sync.
373 KeyData
.Key
.ScanCode
= SCAN_NULL
;
374 KeyData
.Key
.UnicodeChar
= CHAR_NULL
;
375 KeyData
.KeyState
.KeyShiftState
= 0;
376 KeyData
.KeyState
.KeyToggleState
= 0;
377 Private
->TextInEx
.RegisterKeyNotify (
380 ToggleStateSyncKeyNotify
,
386 Reinitialization for toggle state sync.
388 @param Private Text In Splitter pointer.
392 ToggleStateSyncReInitialization (
393 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
399 // Reinitialize PhysicalKeyToggleState that will be synced to new console
400 // input device to turn on physical TextInEx partial key report for
401 // toggle state sync.
403 Private
->PhysicalKeyToggleState
= KEY_STATE_VALID_EXPOSED
;
406 // Reinitialize VirtualKeyStateExported to let the virtual TextInEx not report
407 // the partial key even though the physical TextInEx turns on the partial
408 // key report. The virtual TextInEx will report the partial key after it is
409 // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.
411 Private
->VirtualKeyStateExported
= FALSE
;
413 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
414 Private
->TextInExList
[Index
]->SetState (
415 Private
->TextInExList
[Index
],
416 &Private
->PhysicalKeyToggleState
422 The Entry Point for module ConSplitter. The user code starts with this function.
424 Installs driver module protocols and. Creates virtual device handles for ConIn,
425 ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
426 Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
427 Installs Graphics Output protocol and/or UGA Draw protocol if needed.
429 @param[in] ImageHandle The firmware allocated handle for the EFI image.
430 @param[in] SystemTable A pointer to the EFI System Table.
432 @retval EFI_SUCCESS The entry point is executed successfully.
433 @retval other Some error occurs when executing this entry point.
438 ConSplitterDriverEntry(
439 IN EFI_HANDLE ImageHandle
,
440 IN EFI_SYSTEM_TABLE
*SystemTable
446 // Install driver model protocol(s).
448 Status
= EfiLibInstallDriverBindingComponentName2 (
451 &gConSplitterConInDriverBinding
,
453 &gConSplitterConInComponentName
,
454 &gConSplitterConInComponentName2
456 ASSERT_EFI_ERROR (Status
);
458 Status
= EfiLibInstallDriverBindingComponentName2 (
461 &gConSplitterSimplePointerDriverBinding
,
463 &gConSplitterSimplePointerComponentName
,
464 &gConSplitterSimplePointerComponentName2
466 ASSERT_EFI_ERROR (Status
);
468 Status
= EfiLibInstallDriverBindingComponentName2 (
471 &gConSplitterAbsolutePointerDriverBinding
,
473 &gConSplitterAbsolutePointerComponentName
,
474 &gConSplitterAbsolutePointerComponentName2
476 ASSERT_EFI_ERROR (Status
);
478 Status
= EfiLibInstallDriverBindingComponentName2 (
481 &gConSplitterConOutDriverBinding
,
483 &gConSplitterConOutComponentName
,
484 &gConSplitterConOutComponentName2
486 ASSERT_EFI_ERROR (Status
);
488 Status
= EfiLibInstallDriverBindingComponentName2 (
491 &gConSplitterStdErrDriverBinding
,
493 &gConSplitterStdErrComponentName
,
494 &gConSplitterStdErrComponentName2
496 ASSERT_EFI_ERROR (Status
);
499 // Either Graphics Output protocol or UGA Draw protocol must be supported.
501 ASSERT (FeaturePcdGet (PcdConOutGopSupport
) ||
502 FeaturePcdGet (PcdConOutUgaSupport
));
505 // The driver creates virtual handles for ConIn, ConOut, StdErr.
506 // The virtual handles will always exist even if no console exist in the
507 // system. This is need to support hotplug devices like USB.
510 // Create virtual device handle for ConIn Splitter
512 Status
= ConSplitterTextInConstructor (&mConIn
);
513 if (!EFI_ERROR (Status
)) {
514 Status
= gBS
->InstallMultipleProtocolInterfaces (
515 &mConIn
.VirtualHandle
,
516 &gEfiSimpleTextInProtocolGuid
,
518 &gEfiSimpleTextInputExProtocolGuid
,
520 &gEfiSimplePointerProtocolGuid
,
521 &mConIn
.SimplePointer
,
522 &gEfiAbsolutePointerProtocolGuid
,
523 &mConIn
.AbsolutePointer
,
526 if (!EFI_ERROR (Status
)) {
528 // Update the EFI System Table with new virtual console
529 // and update the pointer to Simple Text Input protocol.
531 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
532 gST
->ConIn
= &mConIn
.TextIn
;
536 // Create virtual device handle for ConOut Splitter
538 Status
= ConSplitterTextOutConstructor (&mConOut
);
539 if (!EFI_ERROR (Status
)) {
540 Status
= gBS
->InstallMultipleProtocolInterfaces (
541 &mConOut
.VirtualHandle
,
542 &gEfiSimpleTextOutProtocolGuid
,
546 if (!EFI_ERROR (Status
)) {
548 // Update the EFI System Table with new virtual console
549 // and Update the pointer to Text Output protocol.
551 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
552 gST
->ConOut
= &mConOut
.TextOut
;
558 // Create virtual device handle for StdErr Splitter
560 Status
= ConSplitterTextOutConstructor (&mStdErr
);
561 if (!EFI_ERROR (Status
)) {
562 Status
= gBS
->InstallMultipleProtocolInterfaces (
563 &mStdErr
.VirtualHandle
,
564 &gEfiSimpleTextOutProtocolGuid
,
568 if (!EFI_ERROR (Status
)) {
570 // Update the EFI System Table with new virtual console
571 // and update the pointer to Text Output protocol.
573 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
574 gST
->StdErr
= &mStdErr
.TextOut
;
579 // Update the CRC32 in the EFI System Table header
582 gBS
->CalculateCrc32 (
593 Construct console input devices' private data.
595 @param ConInPrivate A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA
598 @retval EFI_OUT_OF_RESOURCES Out of resources.
599 @retval EFI_SUCCESS Text Input Devcie's private data has been constructed.
600 @retval other Failed to construct private data.
604 ConSplitterTextInConstructor (
605 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
611 // Allocate buffer for Simple Text Input device
613 Status
= ConSplitterGrowBuffer (
614 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
615 &ConInPrivate
->TextInListCount
,
616 (VOID
**) &ConInPrivate
->TextInList
618 if (EFI_ERROR (Status
)) {
619 return EFI_OUT_OF_RESOURCES
;
623 // Create Event to wait for a key
625 Status
= gBS
->CreateEvent (
628 ConSplitterTextInWaitForKey
,
630 &ConInPrivate
->TextIn
.WaitForKey
632 ASSERT_EFI_ERROR (Status
);
635 // Allocate buffer for Simple Text Input Ex device
637 Status
= ConSplitterGrowBuffer (
638 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
639 &ConInPrivate
->TextInExListCount
,
640 (VOID
**) &ConInPrivate
->TextInExList
642 if (EFI_ERROR (Status
)) {
643 return EFI_OUT_OF_RESOURCES
;
646 // Create Event to wait for a key Ex
648 Status
= gBS
->CreateEvent (
651 ConSplitterTextInWaitForKey
,
653 &ConInPrivate
->TextInEx
.WaitForKeyEx
655 ASSERT_EFI_ERROR (Status
);
657 InitializeListHead (&ConInPrivate
->NotifyList
);
659 ToggleStateSyncInitialization (ConInPrivate
);
661 ConInPrivate
->AbsolutePointer
.Mode
= &ConInPrivate
->AbsolutePointerMode
;
663 // Allocate buffer for Absolute Pointer device
665 Status
= ConSplitterGrowBuffer (
666 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
667 &ConInPrivate
->AbsolutePointerListCount
,
668 (VOID
**) &ConInPrivate
->AbsolutePointerList
670 if (EFI_ERROR (Status
)) {
671 return EFI_OUT_OF_RESOURCES
;
674 // Create Event to wait for device input for Absolute pointer device
676 Status
= gBS
->CreateEvent (
679 ConSplitterAbsolutePointerWaitForInput
,
681 &ConInPrivate
->AbsolutePointer
.WaitForInput
683 ASSERT_EFI_ERROR (Status
);
685 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
687 // Allocate buffer for Simple Pointer device
689 Status
= ConSplitterGrowBuffer (
690 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
691 &ConInPrivate
->PointerListCount
,
692 (VOID
**) &ConInPrivate
->PointerList
694 if (EFI_ERROR (Status
)) {
695 return EFI_OUT_OF_RESOURCES
;
698 // Create Event to wait for device input for Simple pointer device
700 Status
= gBS
->CreateEvent (
703 ConSplitterSimplePointerWaitForInput
,
705 &ConInPrivate
->SimplePointer
.WaitForInput
707 ASSERT_EFI_ERROR (Status
);
709 // Create Event to signal ConIn connection request
711 Status
= gBS
->CreateEventEx (
714 EfiEventEmptyFunction
,
716 &gConnectConInEventGuid
,
717 &ConInPrivate
->ConnectConInEvent
724 Construct console output devices' private data.
726 @param ConOutPrivate A pointer to the TEXT_OUT_SPLITTER_PRIVATE_DATA
729 @retval EFI_OUT_OF_RESOURCES Out of resources.
730 @retval EFI_SUCCESS Text Input Devcie's private data has been constructed.
734 ConSplitterTextOutConstructor (
735 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
739 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
742 // Copy protocols template
744 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
745 CopyMem (&ConOutPrivate
->UgaDraw
, &mUgaDrawProtocolTemplate
, sizeof (EFI_UGA_DRAW_PROTOCOL
));
747 if (FeaturePcdGet (PcdConOutGopSupport
)) {
748 CopyMem (&ConOutPrivate
->GraphicsOutput
, &mGraphicsOutputProtocolTemplate
, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL
));
752 // Initilize console output splitter's private data.
754 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
757 // When new console device is added, the new mode will be set later,
758 // so put current mode back to init state.
760 ConOutPrivate
->TextOutMode
.Mode
= 0xFF;
762 // Allocate buffer for Console Out device
764 Status
= ConSplitterGrowBuffer (
765 sizeof (TEXT_OUT_AND_GOP_DATA
),
766 &ConOutPrivate
->TextOutListCount
,
767 (VOID
**) &ConOutPrivate
->TextOutList
769 if (EFI_ERROR (Status
)) {
770 return EFI_OUT_OF_RESOURCES
;
773 // Allocate buffer for Text Out query data
775 Status
= ConSplitterGrowBuffer (
776 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
777 &ConOutPrivate
->TextOutQueryDataCount
,
778 (VOID
**) &ConOutPrivate
->TextOutQueryData
780 if (EFI_ERROR (Status
)) {
781 return EFI_OUT_OF_RESOURCES
;
785 // Setup the default console to 80 x 25 and mode to 0
787 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
788 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
789 TextOutSetMode (ConOutPrivate
, 0);
792 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
794 // Setup the UgaDraw to 800 x 600 x 32 bits per pixel, 60Hz.
796 ConSplitterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
798 if (FeaturePcdGet (PcdConOutGopSupport
)) {
800 // Setup resource for mode information in Graphics Output Protocol interface
802 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
803 return EFI_OUT_OF_RESOURCES
;
805 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
806 return EFI_OUT_OF_RESOURCES
;
809 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
810 // DevNull will be updated to user-defined mode after driver has started.
812 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
813 return EFI_OUT_OF_RESOURCES
;
815 Info
= &ConOutPrivate
->GraphicsOutputModeBuffer
[0];
817 Info
->HorizontalResolution
= 800;
818 Info
->VerticalResolution
= 600;
819 Info
->PixelFormat
= PixelBltOnly
;
820 Info
->PixelsPerScanLine
= 800;
821 CopyMem (ConOutPrivate
->GraphicsOutput
.Mode
->Info
, Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
822 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
825 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
826 // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
828 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
829 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
831 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
833 // Initial current mode to unknown state, and then set to mode 0
835 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
836 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
844 Test to see if the specified protocol could be supported on the specified device.
846 @param This Driver Binding protocol pointer.
847 @param ControllerHandle Handle of device to test.
848 @param Guid The specified protocol.
850 @retval EFI_SUCCESS The specified protocol is supported on this device.
851 @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtul handle.
852 @retval other Failed to open specified protocol on this device.
856 ConSplitterSupported (
857 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
858 IN EFI_HANDLE ControllerHandle
,
866 // Make sure the Console Splitter does not attempt to attach to itself
868 if (ControllerHandle
== mConIn
.VirtualHandle
||
869 ControllerHandle
== mConOut
.VirtualHandle
||
870 ControllerHandle
== mStdErr
.VirtualHandle
872 return EFI_UNSUPPORTED
;
876 // Check to see whether the specific protocol could be opened BY_DRIVER
878 Status
= gBS
->OpenProtocol (
882 This
->DriverBindingHandle
,
884 EFI_OPEN_PROTOCOL_BY_DRIVER
887 if (EFI_ERROR (Status
)) {
894 This
->DriverBindingHandle
,
902 Test to see if Console In Device could be supported on the Controller.
904 @param This Driver Binding protocol instance pointer.
905 @param ControllerHandle Handle of device to test.
906 @param RemainingDevicePath Optional parameter use to pick a specific child
909 @retval EFI_SUCCESS This driver supports this device.
910 @retval other This driver does not support this device.
915 ConSplitterConInDriverBindingSupported (
916 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
917 IN EFI_HANDLE ControllerHandle
,
918 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
921 return ConSplitterSupported (
924 &gEfiConsoleInDeviceGuid
929 Test to see if Simple Pointer protocol could be supported on the Controller.
931 @param This Driver Binding protocol instance pointer.
932 @param ControllerHandle Handle of device to test.
933 @param RemainingDevicePath Optional parameter use to pick a specific child
936 @retval EFI_SUCCESS This driver supports this device.
937 @retval other This driver does not support this device.
942 ConSplitterSimplePointerDriverBindingSupported (
943 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
944 IN EFI_HANDLE ControllerHandle
,
945 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
948 return ConSplitterSupported (
951 &gEfiSimplePointerProtocolGuid
956 Test to see if Absolute Pointer protocol could be supported on the Controller.
958 @param This Driver Binding protocol instance pointer.
959 @param ControllerHandle Handle of device to test.
960 @param RemainingDevicePath Optional parameter use to pick a specific child
963 @retval EFI_SUCCESS This driver supports this device.
964 @retval other This driver does not support this device.
969 ConSplitterAbsolutePointerDriverBindingSupported (
970 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
971 IN EFI_HANDLE ControllerHandle
,
972 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
975 return ConSplitterSupported (
978 &gEfiAbsolutePointerProtocolGuid
984 Test to see if Console Out Device could be supported on the Controller.
986 @param This Driver Binding protocol instance pointer.
987 @param ControllerHandle Handle of device to test.
988 @param RemainingDevicePath Optional parameter use to pick a specific child
991 @retval EFI_SUCCESS This driver supports this device.
992 @retval other This driver does not support this device.
997 ConSplitterConOutDriverBindingSupported (
998 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
999 IN EFI_HANDLE ControllerHandle
,
1000 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1003 return ConSplitterSupported (
1006 &gEfiConsoleOutDeviceGuid
1011 Test to see if Standard Error Device could be supported on the Controller.
1013 @param This Driver Binding protocol instance pointer.
1014 @param ControllerHandle Handle of device to test.
1015 @param RemainingDevicePath Optional parameter use to pick a specific child
1018 @retval EFI_SUCCESS This driver supports this device.
1019 @retval other This driver does not support this device.
1024 ConSplitterStdErrDriverBindingSupported (
1025 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1026 IN EFI_HANDLE ControllerHandle
,
1027 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1030 return ConSplitterSupported (
1033 &gEfiStandardErrorDeviceGuid
1039 Start ConSplitter on devcie handle by opening Console Device Guid on device handle
1040 and the console virtual handle. And Get the console interface on controller handle.
1042 @param This Driver Binding protocol instance pointer.
1043 @param ControllerHandle Handle of device.
1044 @param ConSplitterVirtualHandle Console virtual Handle.
1045 @param DeviceGuid The specified Console Device, such as ConInDev,
1047 @param InterfaceGuid The specified protocol to be opened.
1048 @param Interface Protocol interface returned.
1050 @retval EFI_SUCCESS This driver supports this device.
1051 @retval other Failed to open the specified Console Device Guid
1052 or specified protocol.
1057 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1058 IN EFI_HANDLE ControllerHandle
,
1059 IN EFI_HANDLE ConSplitterVirtualHandle
,
1060 IN EFI_GUID
*DeviceGuid
,
1061 IN EFI_GUID
*InterfaceGuid
,
1062 OUT VOID
**Interface
1069 // Check to see whether the ControllerHandle has the DeviceGuid on it.
1071 Status
= gBS
->OpenProtocol (
1075 This
->DriverBindingHandle
,
1077 EFI_OPEN_PROTOCOL_BY_DRIVER
1079 if (EFI_ERROR (Status
)) {
1084 // Open the Parent Handle for the child.
1086 Status
= gBS
->OpenProtocol (
1090 This
->DriverBindingHandle
,
1091 ConSplitterVirtualHandle
,
1092 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1094 if (EFI_ERROR (Status
)) {
1099 // Open InterfaceGuid on the virtul handle.
1101 Status
= gBS
->OpenProtocol (
1105 This
->DriverBindingHandle
,
1106 ConSplitterVirtualHandle
,
1107 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1110 if (!EFI_ERROR (Status
)) {
1115 // close the DeviceGuid on ConSplitter VirtualHandle.
1117 gBS
->CloseProtocol (
1120 This
->DriverBindingHandle
,
1121 ConSplitterVirtualHandle
1126 // close the DeviceGuid on ControllerHandle.
1128 gBS
->CloseProtocol (
1131 This
->DriverBindingHandle
,
1140 Start Console In Consplitter on device handle.
1142 @param This Driver Binding protocol instance pointer.
1143 @param ControllerHandle Handle of device to bind driver to.
1144 @param RemainingDevicePath Optional parameter use to pick a specific child
1147 @retval EFI_SUCCESS Console In Consplitter is added to ControllerHandle.
1148 @retval other Console In Consplitter does not support this device.
1153 ConSplitterConInDriverBindingStart (
1154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1155 IN EFI_HANDLE ControllerHandle
,
1156 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1160 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1161 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1164 // Start ConSplitter on ControllerHandle, and create the virtual
1165 // agrogated console device on first call Start for a SimpleTextIn handle.
1167 Status
= ConSplitterStart (
1170 mConIn
.VirtualHandle
,
1171 &gEfiConsoleInDeviceGuid
,
1172 &gEfiSimpleTextInProtocolGuid
,
1175 if (EFI_ERROR (Status
)) {
1180 // Add this device into Text In devices list.
1182 Status
= ConSplitterTextInAddDevice (&mConIn
, TextIn
);
1183 if (EFI_ERROR (Status
)) {
1187 Status
= gBS
->OpenProtocol (
1189 &gEfiSimpleTextInputExProtocolGuid
,
1190 (VOID
**) &TextInEx
,
1191 This
->DriverBindingHandle
,
1192 mConIn
.VirtualHandle
,
1193 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1195 if (!EFI_ERROR (Status
)) {
1197 // If Simple Text Input Ex protocol exists,
1198 // add this device into Text In Ex devices list.
1200 Status
= ConSplitterTextInExAddDevice (&mConIn
, TextInEx
);
1208 Start Simple Pointer Consplitter on device handle.
1210 @param This Driver Binding protocol instance pointer.
1211 @param ControllerHandle Handle of device to bind driver to.
1212 @param RemainingDevicePath Optional parameter use to pick a specific child
1215 @retval EFI_SUCCESS Simple Pointer Consplitter is added to ControllerHandle.
1216 @retval other Simple Pointer Consplitter does not support this device.
1221 ConSplitterSimplePointerDriverBindingStart (
1222 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1223 IN EFI_HANDLE ControllerHandle
,
1224 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1228 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1231 // Start ConSplitter on ControllerHandle, and create the virtual
1232 // agrogated console device on first call Start for a SimplePointer handle.
1234 Status
= ConSplitterStart (
1237 mConIn
.VirtualHandle
,
1238 &gEfiSimplePointerProtocolGuid
,
1239 &gEfiSimplePointerProtocolGuid
,
1240 (VOID
**) &SimplePointer
1242 if (EFI_ERROR (Status
)) {
1247 // Add this devcie into Simple Pointer devices list.
1249 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
1254 Start Absolute Pointer Consplitter on device handle.
1256 @param This Driver Binding protocol instance pointer.
1257 @param ControllerHandle Handle of device to bind driver to.
1258 @param RemainingDevicePath Optional parameter use to pick a specific child
1261 @retval EFI_SUCCESS Absolute Pointer Consplitter is added to ControllerHandle.
1262 @retval other Absolute Pointer Consplitter does not support this device.
1267 ConSplitterAbsolutePointerDriverBindingStart (
1268 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1269 IN EFI_HANDLE ControllerHandle
,
1270 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1274 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1277 // Start ConSplitter on ControllerHandle, and create the virtual
1278 // agrogated console device on first call Start for a AbsolutePointer handle.
1280 Status
= ConSplitterStart (
1283 mConIn
.VirtualHandle
,
1284 &gEfiAbsolutePointerProtocolGuid
,
1285 &gEfiAbsolutePointerProtocolGuid
,
1286 (VOID
**) &AbsolutePointer
1289 if (EFI_ERROR (Status
)) {
1294 // Add this devcie into Absolute Pointer devices list.
1296 return ConSplitterAbsolutePointerAddDevice (&mConIn
, AbsolutePointer
);
1301 Start Console Out Consplitter on device handle.
1303 @param This Driver Binding protocol instance pointer.
1304 @param ControllerHandle Handle of device to bind driver to.
1305 @param RemainingDevicePath Optional parameter use to pick a specific child
1308 @retval EFI_SUCCESS Console Out Consplitter is added to ControllerHandle.
1309 @retval other Console Out Consplitter does not support this device.
1314 ConSplitterConOutDriverBindingStart (
1315 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1316 IN EFI_HANDLE ControllerHandle
,
1317 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1321 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1322 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1323 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1325 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
1328 // Start ConSplitter on ControllerHandle, and create the virtual
1329 // agrogated console device on first call Start for a ConsoleOut handle.
1331 Status
= ConSplitterStart (
1334 mConOut
.VirtualHandle
,
1335 &gEfiConsoleOutDeviceGuid
,
1336 &gEfiSimpleTextOutProtocolGuid
,
1339 if (EFI_ERROR (Status
)) {
1343 GraphicsOutput
= NULL
;
1346 // Try to Open Graphics Output protocol
1348 Status
= gBS
->OpenProtocol (
1350 &gEfiGraphicsOutputProtocolGuid
,
1351 (VOID
**) &GraphicsOutput
,
1352 This
->DriverBindingHandle
,
1353 mConOut
.VirtualHandle
,
1354 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1357 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
1359 // Open UGA DRAW protocol
1363 &gEfiUgaDrawProtocolGuid
,
1365 This
->DriverBindingHandle
,
1366 mConOut
.VirtualHandle
,
1367 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1372 // When new console device is added, the new mode will be set later,
1373 // so put current mode back to init state.
1375 mConOut
.TextOutMode
.Mode
= 0xFF;
1378 // If both ConOut and StdErr incorporate the same Text Out device,
1379 // their MaxMode and QueryData should be the intersection of both.
1381 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1382 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1384 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
1386 // Get the UGA mode data of ConOut from the current mode
1388 if (GraphicsOutput
!= NULL
) {
1389 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, GraphicsOutput
->Mode
->Mode
, &SizeOfInfo
, &Info
);
1390 if (EFI_ERROR (Status
)) {
1393 ASSERT ( SizeOfInfo
<= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
1395 mConOut
.UgaHorizontalResolution
= Info
->HorizontalResolution
;
1396 mConOut
.UgaVerticalResolution
= Info
->VerticalResolution
;
1397 mConOut
.UgaColorDepth
= 32;
1398 mConOut
.UgaRefreshRate
= 60;
1402 } else if (UgaDraw
!= NULL
) {
1403 Status
= UgaDraw
->GetMode (
1405 &mConOut
.UgaHorizontalResolution
,
1406 &mConOut
.UgaVerticalResolution
,
1407 &mConOut
.UgaColorDepth
,
1408 &mConOut
.UgaRefreshRate
1418 Start Standard Error Consplitter on device handle.
1420 @param This Driver Binding protocol instance pointer.
1421 @param ControllerHandle Handle of device to bind driver to.
1422 @param RemainingDevicePath Optional parameter use to pick a specific child
1425 @retval EFI_SUCCESS Standard Error Consplitter is added to ControllerHandle.
1426 @retval other Standard Error Consplitter does not support this device.
1431 ConSplitterStdErrDriverBindingStart (
1432 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1433 IN EFI_HANDLE ControllerHandle
,
1434 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1438 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1441 // Start ConSplitter on ControllerHandle, and create the virtual
1442 // agrogated console device on first call Start for a StandardError handle.
1444 Status
= ConSplitterStart (
1447 mStdErr
.VirtualHandle
,
1448 &gEfiStandardErrorDeviceGuid
,
1449 &gEfiSimpleTextOutProtocolGuid
,
1452 if (EFI_ERROR (Status
)) {
1457 // When new console device is added, the new mode will be set later,
1458 // so put current mode back to init state.
1460 mStdErr
.TextOutMode
.Mode
= 0xFF;
1463 // If both ConOut and StdErr incorporate the same Text Out device,
1464 // their MaxMode and QueryData should be the intersection of both.
1466 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1467 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1474 Stop ConSplitter on device handle by closing Console Device Guid on device handle
1475 and the console virtual handle.
1477 @param This Protocol instance pointer.
1478 @param ControllerHandle Handle of device.
1479 @param ConSplitterVirtualHandle Console virtual Handle.
1480 @param DeviceGuid The specified Console Device, such as ConInDev,
1482 @param InterfaceGuid The specified protocol to be opened.
1483 @param Interface Protocol interface returned.
1485 @retval EFI_SUCCESS Stop ConSplitter on ControllerHandle successfully.
1486 @retval other Failed to Stop ConSplitter on ControllerHandle.
1491 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1492 IN EFI_HANDLE ControllerHandle
,
1493 IN EFI_HANDLE ConSplitterVirtualHandle
,
1494 IN EFI_GUID
*DeviceGuid
,
1495 IN EFI_GUID
*InterfaceGuid
,
1501 Status
= gBS
->OpenProtocol (
1505 This
->DriverBindingHandle
,
1507 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1509 if (EFI_ERROR (Status
)) {
1513 // close the protocol refered.
1515 gBS
->CloseProtocol (
1518 This
->DriverBindingHandle
,
1519 ConSplitterVirtualHandle
1522 gBS
->CloseProtocol (
1525 This
->DriverBindingHandle
,
1534 Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID.
1536 @param This Driver Binding protocol instance pointer.
1537 @param ControllerHandle Handle of device to stop driver on
1538 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1539 children is zero stop the entire bus driver.
1540 @param ChildHandleBuffer List of Child Handles to Stop.
1542 @retval EFI_SUCCESS This driver is removed ControllerHandle
1543 @retval other This driver was not removed from this device
1548 ConSplitterConInDriverBindingStop (
1549 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1550 IN EFI_HANDLE ControllerHandle
,
1551 IN UINTN NumberOfChildren
,
1552 IN EFI_HANDLE
*ChildHandleBuffer
1556 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1557 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1559 if (NumberOfChildren
== 0) {
1563 Status
= gBS
->OpenProtocol (
1565 &gEfiSimpleTextInputExProtocolGuid
,
1566 (VOID
**) &TextInEx
,
1567 This
->DriverBindingHandle
,
1569 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1571 if (!EFI_ERROR (Status
)) {
1573 // If Simple Text Input Ex protocol exists,
1574 // remove device from Text Input Ex devices list.
1576 Status
= ConSplitterTextInExDeleteDevice (&mConIn
, TextInEx
);
1577 if (EFI_ERROR (Status
)) {
1583 // Close Simple Text In protocol on controller handle and virtual handle.
1585 Status
= ConSplitterStop (
1588 mConIn
.VirtualHandle
,
1589 &gEfiConsoleInDeviceGuid
,
1590 &gEfiSimpleTextInProtocolGuid
,
1593 if (EFI_ERROR (Status
)) {
1598 // Remove device from Text Input devices list.
1600 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1605 Stop Simple Pointer protocol ConSplitter on ControllerHandle by closing
1606 Simple Pointer protocol.
1608 @param This Driver Binding protocol instance pointer.
1609 @param ControllerHandle Handle of device to stop driver on
1610 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1611 children is zero stop the entire bus driver.
1612 @param ChildHandleBuffer List of Child Handles to Stop.
1614 @retval EFI_SUCCESS This driver is removed ControllerHandle
1615 @retval other This driver was not removed from this device
1620 ConSplitterSimplePointerDriverBindingStop (
1621 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1622 IN EFI_HANDLE ControllerHandle
,
1623 IN UINTN NumberOfChildren
,
1624 IN EFI_HANDLE
*ChildHandleBuffer
1628 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1630 if (NumberOfChildren
== 0) {
1635 // Close Simple Pointer protocol on controller handle and virtual handle.
1637 Status
= ConSplitterStop (
1640 mConIn
.VirtualHandle
,
1641 &gEfiSimplePointerProtocolGuid
,
1642 &gEfiSimplePointerProtocolGuid
,
1643 (VOID
**) &SimplePointer
1645 if (EFI_ERROR (Status
)) {
1650 // Remove this device from Simple Pointer device list.
1652 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1657 Stop Absolute Pointer protocol ConSplitter on ControllerHandle by closing
1658 Absolute Pointer protocol.
1660 @param This Driver Binding protocol instance pointer.
1661 @param ControllerHandle Handle of device to stop driver on
1662 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1663 children is zero stop the entire bus driver.
1664 @param ChildHandleBuffer List of Child Handles to Stop.
1666 @retval EFI_SUCCESS This driver is removed ControllerHandle
1667 @retval other This driver was not removed from this device
1672 ConSplitterAbsolutePointerDriverBindingStop (
1673 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1674 IN EFI_HANDLE ControllerHandle
,
1675 IN UINTN NumberOfChildren
,
1676 IN EFI_HANDLE
*ChildHandleBuffer
1680 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1682 if (NumberOfChildren
== 0) {
1687 // Close Absolute Pointer protocol on controller handle and virtual handle.
1689 Status
= ConSplitterStop (
1692 mConIn
.VirtualHandle
,
1693 &gEfiAbsolutePointerProtocolGuid
,
1694 &gEfiAbsolutePointerProtocolGuid
,
1695 (VOID
**) &AbsolutePointer
1697 if (EFI_ERROR (Status
)) {
1702 // Remove this device from Absolute Pointer device list.
1704 return ConSplitterAbsolutePointerDeleteDevice (&mConIn
, AbsolutePointer
);
1709 Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID.
1711 @param This Driver Binding protocol instance pointer.
1712 @param ControllerHandle Handle of device to stop driver on
1713 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1714 children is zero stop the entire bus driver.
1715 @param ChildHandleBuffer List of Child Handles to Stop.
1717 @retval EFI_SUCCESS This driver is removed ControllerHandle
1718 @retval other This driver was not removed from this device
1723 ConSplitterConOutDriverBindingStop (
1724 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1725 IN EFI_HANDLE ControllerHandle
,
1726 IN UINTN NumberOfChildren
,
1727 IN EFI_HANDLE
*ChildHandleBuffer
1731 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1733 if (NumberOfChildren
== 0) {
1738 // Close Absolute Pointer protocol on controller handle and virtual handle.
1740 Status
= ConSplitterStop (
1743 mConOut
.VirtualHandle
,
1744 &gEfiConsoleOutDeviceGuid
,
1745 &gEfiSimpleTextOutProtocolGuid
,
1748 if (EFI_ERROR (Status
)) {
1753 // Remove this device from Text Out device list.
1755 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1760 Stop Standard Error ConSplitter on ControllerHandle by closing Standard Error GUID.
1762 @param This Driver Binding protocol instance pointer.
1763 @param ControllerHandle Handle of device to stop driver on
1764 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1765 children is zero stop the entire bus driver.
1766 @param ChildHandleBuffer List of Child Handles to Stop.
1768 @retval EFI_SUCCESS This driver is removed ControllerHandle
1769 @retval other This driver was not removed from this device
1774 ConSplitterStdErrDriverBindingStop (
1775 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1776 IN EFI_HANDLE ControllerHandle
,
1777 IN UINTN NumberOfChildren
,
1778 IN EFI_HANDLE
*ChildHandleBuffer
1782 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1784 if (NumberOfChildren
== 0) {
1789 // Close Standard Error Device on controller handle and virtual handle.
1791 Status
= ConSplitterStop (
1794 mStdErr
.VirtualHandle
,
1795 &gEfiStandardErrorDeviceGuid
,
1796 &gEfiSimpleTextOutProtocolGuid
,
1799 if (EFI_ERROR (Status
)) {
1803 // Delete this console error out device's data structures.
1805 return ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1810 Take the passed in Buffer of size ElementSize and grow the buffer
1811 by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes.
1812 Copy the current data in Buffer to the new version of Buffer and
1813 free the old version of buffer.
1815 @param ElementSize Size of element in array.
1816 @param Count Current number of elements in array.
1817 @param Buffer Bigger version of passed in Buffer with all the
1820 @retval EFI_SUCCESS Buffer size has grown.
1821 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1825 ConSplitterGrowBuffer (
1826 IN UINTN ElementSize
,
1827 IN OUT UINTN
*Count
,
1828 IN OUT VOID
**Buffer
1834 // grow the buffer to new buffer size,
1835 // copy the old buffer's content to the new-size buffer,
1836 // then free the old buffer.
1838 Ptr
= ReallocatePool (
1839 ElementSize
* (*Count
),
1840 ElementSize
* ((*Count
) + CONSOLE_SPLITTER_ALLOC_UNIT
),
1844 return EFI_OUT_OF_RESOURCES
;
1846 *Count
+= CONSOLE_SPLITTER_ALLOC_UNIT
;
1853 Add Text Input Device in Consplitter Text Input list.
1855 @param Private Text In Splitter pointer.
1856 @param TextIn Simple Text Input protocol pointer.
1858 @retval EFI_SUCCESS Text Input Device added successfully.
1859 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1863 ConSplitterTextInAddDevice (
1864 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1865 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1871 // If the Text In List is full, enlarge it by calling ConSplitterGrowBuffer().
1873 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1874 Status
= ConSplitterGrowBuffer (
1875 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1876 &Private
->TextInListCount
,
1877 (VOID
**) &Private
->TextInList
1879 if (EFI_ERROR (Status
)) {
1880 return EFI_OUT_OF_RESOURCES
;
1884 // Add the new text-in device data structure into the Text In List.
1886 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1887 Private
->CurrentNumberOfConsoles
++;
1890 // Extra CheckEvent added to reduce the double CheckEvent().
1892 gBS
->CheckEvent (TextIn
->WaitForKey
);
1899 Remove Text Input Device from Consplitter Text Input list.
1901 @param Private Text In Splitter pointer.
1902 @param TextIn Simple Text protocol pointer.
1904 @retval EFI_SUCCESS Simple Text Device removed successfully.
1905 @retval EFI_NOT_FOUND No Simple Text Device found.
1909 ConSplitterTextInDeleteDevice (
1910 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1911 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1916 // Remove the specified text-in device data structure from the Text In List,
1917 // and rearrange the remaining data structures in the Text In List.
1919 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1920 if (Private
->TextInList
[Index
] == TextIn
) {
1921 for (; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1922 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1925 Private
->CurrentNumberOfConsoles
--;
1930 return EFI_NOT_FOUND
;
1934 Add Text Input Ex Device in Consplitter Text Input Ex list.
1936 @param Private Text In Splitter pointer.
1937 @param TextInEx Simple Text Input Ex Input protocol pointer.
1939 @retval EFI_SUCCESS Text Input Ex Device added successfully.
1940 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1944 ConSplitterTextInExAddDevice (
1945 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1946 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1951 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
1952 UINTN TextInExListCount
;
1955 // Enlarge the NotifyHandleList and the TextInExList
1957 if (Private
->CurrentNumberOfExConsoles
>= Private
->TextInExListCount
) {
1958 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
1959 CurrentNotify
= TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link
);
1960 TextInExListCount
= Private
->TextInExListCount
;
1962 Status
= ConSplitterGrowBuffer (
1963 sizeof (EFI_HANDLE
),
1965 (VOID
**) &CurrentNotify
->NotifyHandleList
1967 if (EFI_ERROR (Status
)) {
1968 return EFI_OUT_OF_RESOURCES
;
1971 Status
= ConSplitterGrowBuffer (
1972 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
1973 &Private
->TextInExListCount
,
1974 (VOID
**) &Private
->TextInExList
1976 if (EFI_ERROR (Status
)) {
1977 return EFI_OUT_OF_RESOURCES
;
1982 // Register the key notify in the new text-in device
1984 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
1985 CurrentNotify
= TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link
);
1986 Status
= TextInEx
->RegisterKeyNotify (
1988 &CurrentNotify
->KeyData
,
1989 CurrentNotify
->KeyNotificationFn
,
1990 &CurrentNotify
->NotifyHandleList
[Private
->CurrentNumberOfExConsoles
]
1992 if (EFI_ERROR (Status
)) {
1993 for (Link
= Link
->BackLink
; Link
!= &Private
->NotifyList
; Link
= Link
->BackLink
) {
1994 CurrentNotify
= TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link
);
1995 TextInEx
->UnregisterKeyNotify (
1997 CurrentNotify
->NotifyHandleList
[Private
->CurrentNumberOfExConsoles
]
2005 // Add the new text-in device data structure into the Text Input Ex List.
2007 Private
->TextInExList
[Private
->CurrentNumberOfExConsoles
] = TextInEx
;
2008 Private
->CurrentNumberOfExConsoles
++;
2011 // Sync current toggle state to this new console input device.
2013 TextInEx
->SetState (TextInEx
, &Private
->PhysicalKeyToggleState
);
2016 // Extra CheckEvent added to reduce the double CheckEvent().
2018 gBS
->CheckEvent (TextInEx
->WaitForKeyEx
);
2024 Remove Text Ex Device from Consplitter Text Input Ex list.
2026 @param Private Text In Splitter pointer.
2027 @param TextInEx Simple Text Ex protocol pointer.
2029 @retval EFI_SUCCESS Simple Text Input Ex Device removed successfully.
2030 @retval EFI_NOT_FOUND No Simple Text Input Ex Device found.
2034 ConSplitterTextInExDeleteDevice (
2035 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2036 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
2041 // Remove the specified text-in device data structure from the Text Input Ex List,
2042 // and rearrange the remaining data structures in the Text In List.
2044 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
2045 if (Private
->TextInExList
[Index
] == TextInEx
) {
2046 for (; Index
< Private
->CurrentNumberOfExConsoles
- 1; Index
++) {
2047 Private
->TextInExList
[Index
] = Private
->TextInExList
[Index
+ 1];
2050 Private
->CurrentNumberOfExConsoles
--;
2055 return EFI_NOT_FOUND
;
2060 Add Simple Pointer Device in Consplitter Simple Pointer list.
2062 @param Private Text In Splitter pointer.
2063 @param SimplePointer Simple Pointer protocol pointer.
2065 @retval EFI_SUCCESS Simple Pointer Device added successfully.
2066 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2070 ConSplitterSimplePointerAddDevice (
2071 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2072 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
2078 // If the Simple Pointer List is full, enlarge it by calling ConSplitterGrowBuffer().
2080 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
2081 Status
= ConSplitterGrowBuffer (
2082 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
2083 &Private
->PointerListCount
,
2084 (VOID
**) &Private
->PointerList
2086 if (EFI_ERROR (Status
)) {
2087 return EFI_OUT_OF_RESOURCES
;
2091 // Add the new text-in device data structure into the Simple Pointer List.
2093 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
2094 Private
->CurrentNumberOfPointers
++;
2101 Remove Simple Pointer Device from Consplitter Simple Pointer list.
2103 @param Private Text In Splitter pointer.
2104 @param SimplePointer Simple Pointer protocol pointer.
2106 @retval EFI_SUCCESS Simple Pointer Device removed successfully.
2107 @retval EFI_NOT_FOUND No Simple Pointer Device found.
2111 ConSplitterSimplePointerDeleteDevice (
2112 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2113 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
2118 // Remove the specified text-in device data structure from the Simple Pointer List,
2119 // and rearrange the remaining data structures in the Text In List.
2121 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2122 if (Private
->PointerList
[Index
] == SimplePointer
) {
2123 for (; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
2124 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
2127 Private
->CurrentNumberOfPointers
--;
2132 return EFI_NOT_FOUND
;
2137 Add Absolute Pointer Device in Consplitter Absolute Pointer list.
2139 @param Private Text In Splitter pointer.
2140 @param AbsolutePointer Absolute Pointer protocol pointer.
2142 @retval EFI_SUCCESS Absolute Pointer Device added successfully.
2143 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2147 ConSplitterAbsolutePointerAddDevice (
2148 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2149 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
2155 // If the Absolute Pointer List is full, enlarge it by calling ConSplitterGrowBuffer().
2157 if (Private
->CurrentNumberOfAbsolutePointers
>= Private
->AbsolutePointerListCount
) {
2158 Status
= ConSplitterGrowBuffer (
2159 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
2160 &Private
->AbsolutePointerListCount
,
2161 (VOID
**) &Private
->AbsolutePointerList
2163 if (EFI_ERROR (Status
)) {
2164 return EFI_OUT_OF_RESOURCES
;
2168 // Add the new text-in device data structure into the Absolute Pointer List.
2170 Private
->AbsolutePointerList
[Private
->CurrentNumberOfAbsolutePointers
] = AbsolutePointer
;
2171 Private
->CurrentNumberOfAbsolutePointers
++;
2178 Remove Absolute Pointer Device from Consplitter Absolute Pointer list.
2180 @param Private Text In Splitter pointer.
2181 @param AbsolutePointer Absolute Pointer protocol pointer.
2183 @retval EFI_SUCCESS Absolute Pointer Device removed successfully.
2184 @retval EFI_NOT_FOUND No Absolute Pointer Device found.
2188 ConSplitterAbsolutePointerDeleteDevice (
2189 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2190 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
2195 // Remove the specified text-in device data structure from the Absolute Pointer List,
2196 // and rearrange the remaining data structures from the Absolute Pointer List.
2198 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
2199 if (Private
->AbsolutePointerList
[Index
] == AbsolutePointer
) {
2200 for (; Index
< Private
->CurrentNumberOfAbsolutePointers
- 1; Index
++) {
2201 Private
->AbsolutePointerList
[Index
] = Private
->AbsolutePointerList
[Index
+ 1];
2204 Private
->CurrentNumberOfAbsolutePointers
--;
2209 return EFI_NOT_FOUND
;
2213 Reallocate Text Out mode map.
2215 Allocate new buffer and copy original buffer into the new buffer.
2217 @param Private Consplitter Text Out pointer.
2219 @retval EFI_SUCCESS Buffer size has grown
2220 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2224 ConSplitterGrowMapTable (
2225 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
2231 INT32
*TextOutModeMap
;
2232 INT32
*OldTextOutModeMap
;
2238 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
2239 OldTextOutModeMap
= Private
->TextOutModeMap
;
2240 TotalSize
= NewSize
* (Private
->TextOutQueryDataCount
);
2243 // Allocate new buffer for Text Out List.
2245 TextOutModeMap
= AllocatePool (TotalSize
);
2246 if (TextOutModeMap
== NULL
) {
2247 return EFI_OUT_OF_RESOURCES
;
2250 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
2251 Private
->TextOutModeMap
= TextOutModeMap
;
2254 // If TextOutList has been enlarged, need to realloc the mode map table
2255 // The mode map table is regarded as a two dimension array.
2258 // 0 ---------> TextOutListCount ----> TextOutListCount
2259 // | -------------------------------------------
2266 // -------------------------------------------
2269 if (OldTextOutModeMap
!= NULL
) {
2271 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
2273 SrcAddress
= OldTextOutModeMap
;
2274 NewStepSize
= NewSize
/ sizeof(INT32
);
2275 // If Private->CurrentNumberOfConsoles is not zero and OldTextOutModeMap
2276 // is not NULL, it indicates that the original TextOutModeMap is not enough
2277 // for the new console devices and has been enlarged by CONSOLE_SPLITTER_ALLOC_UNIT columns.
2279 OldStepSize
= NewStepSize
- CONSOLE_SPLITTER_ALLOC_UNIT
;
2282 // Copy the old data to the new one
2284 while (Index
< Private
->TextOutMode
.MaxMode
) {
2285 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
2287 // Go to next row of new TextOutModeMap.
2289 TextOutModeMap
+= NewStepSize
;
2291 // Go to next row of old TextOutModeMap.
2293 SrcAddress
+= OldStepSize
;
2297 // Free the old buffer
2299 FreePool (OldTextOutModeMap
);
2307 Add new device's output mode to console splitter's mode list.
2309 @param Private Text Out Splitter pointer
2310 @param TextOut Simple Text Output protocol pointer.
2312 @retval EFI_SUCCESS Device added successfully.
2313 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2317 ConSplitterAddOutputMode (
2318 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2319 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2327 MaxMode
= TextOut
->Mode
->MaxMode
;
2328 Private
->TextOutMode
.MaxMode
= MaxMode
;
2331 // Grow the buffer if query data buffer is not large enough to
2332 // hold all the mode supported by the first console.
2334 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
2335 Status
= ConSplitterGrowBuffer (
2336 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
2337 &Private
->TextOutQueryDataCount
,
2338 (VOID
**) &Private
->TextOutQueryData
2340 if (EFI_ERROR (Status
)) {
2341 return EFI_OUT_OF_RESOURCES
;
2345 // Allocate buffer for the output mode map
2347 Status
= ConSplitterGrowMapTable (Private
);
2348 if (EFI_ERROR (Status
)) {
2349 return EFI_OUT_OF_RESOURCES
;
2352 // As the first textout device, directly add the mode in to QueryData
2353 // and at the same time record the mapping between QueryData and TextOut.
2357 while (Mode
< MaxMode
) {
2358 Status
= TextOut
->QueryMode (
2361 &Private
->TextOutQueryData
[Mode
].Columns
,
2362 &Private
->TextOutQueryData
[Mode
].Rows
2365 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2368 if ((EFI_ERROR(Status
)) && (Mode
== 1)) {
2369 Private
->TextOutQueryData
[Mode
].Columns
= 0;
2370 Private
->TextOutQueryData
[Mode
].Rows
= 0;
2372 Private
->TextOutModeMap
[Index
] = Mode
;
2374 Index
+= Private
->TextOutListCount
;
2381 Reconstruct TextOutModeMap to get intersection of modes.
2383 This routine reconstruct TextOutModeMap to get the intersection
2384 of modes for all console out devices. Because EFI/UEFI spec require
2385 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the
2386 intersection for mode 0 and mode 1.
2388 @param TextOutModeMap Current text out mode map, begin with the mode 80x25
2389 @param NewlyAddedMap New text out mode map, begin with the mode 80x25
2390 @param MapStepSize Mode step size for one console device
2391 @param NewMapStepSize New Mode step size for one console device
2392 @param MaxMode IN: Current max text mode, OUT: Updated max text mode.
2393 @param CurrentMode IN: Current text mode, OUT: Updated current text mode.
2397 ConSplitterGetIntersection (
2398 IN INT32
*TextOutModeMap
,
2399 IN INT32
*NewlyAddedMap
,
2400 IN UINTN MapStepSize
,
2401 IN UINTN NewMapStepSize
,
2402 IN OUT INT32
*MaxMode
,
2403 IN OUT INT32
*CurrentMode
2407 INT32
*CurrentMapEntry
;
2408 INT32
*NextMapEntry
;
2410 INT32 CurrentMaxMode
;
2414 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved
2415 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection
2416 // for mode 0 and mode 1, mode number starts from 2.
2419 CurrentMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2420 NextMapEntry
= CurrentMapEntry
;
2421 NewMapEntry
= &NewlyAddedMap
[NewMapStepSize
* 2];
2423 CurrentMaxMode
= *MaxMode
;
2424 Mode
= *CurrentMode
;
2426 while (Index
< CurrentMaxMode
) {
2427 if (*NewMapEntry
== -1) {
2429 // This mode is not supported any more. Remove it. Special care
2430 // must be taken as this remove will also affect current mode;
2432 if (Index
== *CurrentMode
) {
2434 } else if (Index
< *CurrentMode
) {
2439 if (CurrentMapEntry
!= NextMapEntry
) {
2440 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
2443 NextMapEntry
+= MapStepSize
;
2446 CurrentMapEntry
+= MapStepSize
;
2447 NewMapEntry
+= NewMapStepSize
;
2451 *CurrentMode
= Mode
;
2457 Sync the device's output mode to console splitter's mode list.
2459 @param Private Text Out Splitter pointer.
2460 @param TextOut Simple Text Output protocol pointer.
2464 ConSplitterSyncOutputMode (
2465 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2466 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2469 INT32 CurrentMaxMode
;
2472 INT32
*TextOutModeMap
;
2475 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
2482 // Must make sure that current mode won't change even if mode number changes
2484 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
2485 TextOutModeMap
= Private
->TextOutModeMap
;
2486 StepSize
= Private
->TextOutListCount
;
2487 TextOutQueryData
= Private
->TextOutQueryData
;
2490 // Query all the mode that the newly added TextOut supports
2493 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
2494 while (Mode
< TextOut
->Mode
->MaxMode
) {
2495 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
2497 if (EFI_ERROR(Status
)) {
2500 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2503 MapTable
[StepSize
] = Mode
;
2504 TextOutQueryData
[Mode
].Columns
= 0;
2505 TextOutQueryData
[Mode
].Rows
= 0;
2511 // Search the intersection map and QueryData database to see if they intersects
2514 while (Index
< CurrentMaxMode
) {
2515 QueryMode
= *(TextOutModeMap
+ Index
* StepSize
);
2516 if ((TextOutQueryData
[QueryMode
].Rows
== Rows
) && (TextOutQueryData
[QueryMode
].Columns
== Columns
)) {
2517 MapTable
[Index
* StepSize
] = Mode
;
2525 // Now search the TextOutModeMap table to find the intersection of supported
2526 // mode between ConSplitter and the newly added device.
2528 ConSplitterGetIntersection (
2533 &Private
->TextOutMode
.MaxMode
,
2534 &Private
->TextOutMode
.Mode
2542 Sync output device between ConOut and StdErr output.
2544 @retval EFI_SUCCESS Sync implemented successfully.
2545 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2549 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2553 UINTN ConOutNumOfConsoles
;
2554 UINTN StdErrNumOfConsoles
;
2555 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
2556 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
2560 UINTN ConOutColumns
;
2562 UINTN StdErrColumns
;
2563 INT32 ConOutMaxMode
;
2564 INT32 StdErrMaxMode
;
2569 INT32
*ConOutModeMap
;
2570 INT32
*StdErrModeMap
;
2571 INT32
*ConOutMapTable
;
2572 INT32
*StdErrMapTable
;
2573 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
2574 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
2575 UINTN ConOutStepSize
;
2576 UINTN StdErrStepSize
;
2577 BOOLEAN FoundTheSameTextOut
;
2578 UINTN ConOutMapTableSize
;
2579 UINTN StdErrMapTableSize
;
2581 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
2582 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
2583 ConOutTextOutList
= mConOut
.TextOutList
;
2584 StdErrTextOutList
= mStdErr
.TextOutList
;
2587 FoundTheSameTextOut
= FALSE
;
2588 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
2590 while (Indexj
< StdErrNumOfConsoles
) {
2591 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
2592 FoundTheSameTextOut
= TRUE
;
2597 StdErrTextOutList
++;
2601 ConOutTextOutList
++;
2604 if (!FoundTheSameTextOut
) {
2608 // Must make sure that current mode won't change even if mode number changes
2610 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
2611 ConOutModeMap
= mConOut
.TextOutModeMap
;
2612 ConOutStepSize
= mConOut
.TextOutListCount
;
2613 ConOutQueryData
= mConOut
.TextOutQueryData
;
2615 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
2616 StdErrModeMap
= mStdErr
.TextOutModeMap
;
2617 StdErrStepSize
= mStdErr
.TextOutListCount
;
2618 StdErrQueryData
= mStdErr
.TextOutQueryData
;
2621 // Allocate the map table and set the map table's index to -1.
2623 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
2624 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
2625 if (ConOutMapTable
== NULL
) {
2626 return EFI_OUT_OF_RESOURCES
;
2629 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
2631 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
2632 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
2633 if (StdErrMapTable
== NULL
) {
2634 return EFI_OUT_OF_RESOURCES
;
2637 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
2640 // Find the intersection of the two set of modes. If they actually intersect, the
2641 // corresponding entry in the map table is set to 1.
2644 while (Mode
< ConOutMaxMode
) {
2646 // Search the intersection map and QueryData database to see if they intersect
2649 ConOutMode
= *(ConOutModeMap
+ Mode
* ConOutStepSize
);
2650 ConOutRows
= ConOutQueryData
[ConOutMode
].Rows
;
2651 ConOutColumns
= ConOutQueryData
[ConOutMode
].Columns
;
2652 while (Index
< StdErrMaxMode
) {
2653 StdErrMode
= *(StdErrModeMap
+ Index
* StdErrStepSize
);
2654 StdErrRows
= StdErrQueryData
[StdErrMode
].Rows
;
2655 StdErrColumns
= StdErrQueryData
[StdErrMode
].Columns
;
2656 if ((StdErrRows
== ConOutRows
) && (StdErrColumns
== ConOutColumns
)) {
2657 ConOutMapTable
[Mode
] = 1;
2658 StdErrMapTable
[Index
] = 1;
2668 // Now search the TextOutModeMap table to find the intersection of supported
2669 // mode between ConSplitter and the newly added device.
2671 ConSplitterGetIntersection (
2674 mConOut
.TextOutListCount
,
2676 &(mConOut
.TextOutMode
.MaxMode
),
2677 &(mConOut
.TextOutMode
.Mode
)
2680 if (mConOut
.TextOutMode
.Mode
< 0) {
2681 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2684 ConSplitterGetIntersection (
2687 mStdErr
.TextOutListCount
,
2689 &(mStdErr
.TextOutMode
.MaxMode
),
2690 &(mStdErr
.TextOutMode
.Mode
)
2693 if (mStdErr
.TextOutMode
.Mode
< 0) {
2694 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2697 FreePool (ConOutMapTable
);
2698 FreePool (StdErrMapTable
);
2705 Add Grahpics Output modes into Consplitter Text Out list.
2707 @param Private Text Out Splitter pointer.
2708 @param GraphicsOutput Graphics Output protocol pointer.
2709 @param UgaDraw UGA Draw protocol pointer.
2711 @retval EFI_SUCCESS Output mode added successfully.
2712 @retval other Failed to add output mode.
2716 ConSplitterAddGraphicsOutputMode (
2717 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2718 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2719 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2725 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
2727 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2728 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2729 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*ModeBuffer
;
2730 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*MatchedMode
;
2733 BOOLEAN AlreadyExist
;
2734 UINT32 UgaHorizontalResolution
;
2735 UINT32 UgaVerticalResolution
;
2736 UINT32 UgaColorDepth
;
2737 UINT32 UgaRefreshRate
;
2739 ASSERT (GraphicsOutput
!= NULL
|| UgaDraw
!= NULL
);
2741 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2745 Status
= EFI_SUCCESS
;
2747 if (Private
->CurrentNumberOfUgaDraw
!= 0) {
2749 // If any UGA device has already been added, then there is no need to
2750 // calculate intersection of display mode of different GOP/UGA device,
2751 // since only one display mode will be exported (i.e. user-defined mode)
2756 if (GraphicsOutput
!= NULL
) {
2757 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2759 // This is the first Graphics Output device added
2761 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2762 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2763 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2764 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2765 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2766 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2769 // Allocate resource for the private mode buffer
2771 ModeBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
) * GraphicsOutput
->Mode
->MaxMode
);
2772 if (ModeBuffer
== NULL
) {
2773 return EFI_OUT_OF_RESOURCES
;
2775 FreePool (Private
->GraphicsOutputModeBuffer
);
2776 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2779 // Store all supported display modes to the private mode buffer
2782 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2784 // The Info buffer would be allocated by callee
2786 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2787 if (EFI_ERROR (Status
)) {
2790 ASSERT ( SizeOfInfo
<= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2791 CopyMem (Mode
, Info
, SizeOfInfo
);
2797 // Check intersection of display mode
2799 ModeBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
) * CurrentGraphicsOutputMode
->MaxMode
);
2800 if (ModeBuffer
== NULL
) {
2801 return EFI_OUT_OF_RESOURCES
;
2804 MatchedMode
= ModeBuffer
;
2805 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2806 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2809 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2811 // The Info buffer would be allocated by callee
2813 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2814 if (EFI_ERROR (Status
)) {
2817 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2818 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2820 // If GOP device supports one mode in current mode buffer,
2821 // it will be added into matched mode buffer
2831 AlreadyExist
= FALSE
;
2834 // Check if GOP mode has been in the mode buffer, ModeBuffer = MatchedMode at begin.
2836 for (Info
= ModeBuffer
; Info
< MatchedMode
; Info
++) {
2837 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2838 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2839 AlreadyExist
= TRUE
;
2844 if (!AlreadyExist
) {
2845 CopyMem (MatchedMode
, Mode
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2848 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly
2850 MatchedMode
->Version
= 0;
2851 MatchedMode
->PixelFormat
= PixelBltOnly
;
2852 ZeroMem (&MatchedMode
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2862 // Drop the old mode buffer, assign it to a new one
2864 FreePool (Private
->GraphicsOutputModeBuffer
);
2865 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2868 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2870 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2871 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2872 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2873 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2874 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
2875 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2879 // Graphics console driver can ensure the same mode for all GOP devices
2881 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2882 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2883 if ((Mode
->HorizontalResolution
== GraphicsOutput
->Mode
->Info
->HorizontalResolution
) &&
2884 (Mode
->VerticalResolution
== GraphicsOutput
->Mode
->Info
->VerticalResolution
)) {
2885 CurrentIndex
= Index
;
2889 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2891 // if user defined mode is not found, set to default mode 800x600
2893 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2894 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2895 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2896 CurrentIndex
= Index
;
2901 } else if (UgaDraw
!= NULL
) {
2903 // Graphics console driver can ensure the same mode for all GOP devices
2904 // so we can get the current mode from this video device
2908 &UgaHorizontalResolution
,
2909 &UgaVerticalResolution
,
2914 CurrentGraphicsOutputMode
->MaxMode
= 1;
2915 Info
= CurrentGraphicsOutputMode
->Info
;
2917 Info
->HorizontalResolution
= UgaHorizontalResolution
;
2918 Info
->VerticalResolution
= UgaVerticalResolution
;
2919 Info
->PixelFormat
= PixelBltOnly
;
2920 Info
->PixelsPerScanLine
= UgaHorizontalResolution
;
2921 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2922 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
2923 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2926 // Update the private mode buffer
2928 CopyMem (&Private
->GraphicsOutputModeBuffer
[0], Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2931 // Only mode 0 is available to be set
2938 if (GraphicsOutput
!= NULL
) {
2939 Private
->CurrentNumberOfGraphicsOutput
++;
2941 if (UgaDraw
!= NULL
) {
2942 Private
->CurrentNumberOfUgaDraw
++;
2946 // Force GraphicsOutput mode to be set,
2949 Mode
= &Private
->GraphicsOutputModeBuffer
[CurrentIndex
];
2950 if ((GraphicsOutput
!= NULL
) &&
2951 (Mode
->HorizontalResolution
== CurrentGraphicsOutputMode
->Info
->HorizontalResolution
) &&
2952 (Mode
->VerticalResolution
== CurrentGraphicsOutputMode
->Info
->VerticalResolution
)) {
2953 CurrentGraphicsOutputMode
->Mode
= (UINT32
) CurrentIndex
;
2954 if ((Mode
->HorizontalResolution
!= GraphicsOutput
->Mode
->Info
->HorizontalResolution
) ||
2955 (Mode
->VerticalResolution
!= GraphicsOutput
->Mode
->Info
->VerticalResolution
)) {
2957 // If all existing video device has been set to common mode, only set new GOP device to
2960 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2961 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2962 if (EFI_ERROR (Status
)) {
2965 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2971 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
2975 // Current mode number may need update now, so set it to an invalid mode number
2977 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2979 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.
2981 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) CurrentIndex
);
2982 if (EFI_ERROR(Status
)) {
2984 // If user defined mode is not valid for display device, set to the default mode 800x600.
2986 (Private
->GraphicsOutputModeBuffer
[0]).HorizontalResolution
= 800;
2987 (Private
->GraphicsOutputModeBuffer
[0]).VerticalResolution
= 600;
2988 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, 0);
2996 Set the current console out mode.
2998 This routine will get the current console mode information (column, row)
2999 from ConsoleOutMode variable and set it; if the variable does not exist,
3000 set to user defined console mode.
3002 @param Private Consplitter Text Out pointer.
3006 ConsplitterSetConsoleOutMode (
3007 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
3017 CONSOLE_OUT_MODE ModeInfo
;
3018 CONSOLE_OUT_MODE MaxModeInfo
;
3019 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
3023 TextOut
= &Private
->TextOut
;
3024 MaxMode
= (UINTN
) (TextOut
->Mode
->MaxMode
);
3026 MaxModeInfo
.Column
= 0;
3027 MaxModeInfo
.Row
= 0;
3028 ModeInfo
.Column
= PcdGet32 (PcdConOutColumn
);
3029 ModeInfo
.Row
= PcdGet32 (PcdConOutRow
);
3032 // To find the prefer mode and basic mode from Text Out mode list
3034 for (Mode
= 0; Mode
< MaxMode
; Mode
++) {
3035 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Col
, &Row
);
3036 if (!EFI_ERROR(Status
)) {
3037 if ((ModeInfo
.Column
!= 0) && (ModeInfo
.Row
!= 0)) {
3039 // Use user defined column and row
3041 if (Col
== ModeInfo
.Column
&& Row
== ModeInfo
.Row
) {
3046 // If user sets PcdConOutColumn or PcdConOutRow to 0,
3047 // find and set the highest text mode.
3049 if ((Col
>= MaxModeInfo
.Column
) && (Row
>= MaxModeInfo
.Row
)) {
3050 MaxModeInfo
.Column
= Col
;
3051 MaxModeInfo
.Row
= Row
;
3055 if (Col
== 80 && Row
== 25) {
3062 // Set prefer mode to Text Out devices.
3064 Status
= TextOut
->SetMode (TextOut
, PreferMode
);
3065 if (EFI_ERROR(Status
)) {
3067 // if current mode setting is failed, default 80x25 mode will be set.
3069 Status
= TextOut
->SetMode (TextOut
, BaseMode
);
3070 ASSERT(!EFI_ERROR(Status
));
3072 Status
= PcdSet32S (PcdConOutColumn
, 80);
3073 ASSERT(!EFI_ERROR(Status
));
3074 Status
= PcdSet32S (PcdConOutRow
, 25);
3075 ASSERT(!EFI_ERROR(Status
));
3083 Add Text Output Device in Consplitter Text Output list.
3085 @param Private Text Out Splitter pointer.
3086 @param TextOut Simple Text Output protocol pointer.
3087 @param GraphicsOutput Graphics Output protocol pointer.
3088 @param UgaDraw UGA Draw protocol pointer.
3090 @retval EFI_SUCCESS Text Output Device added successfully.
3091 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
3095 ConSplitterTextOutAddDevice (
3096 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
3097 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
3098 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
3099 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
3103 UINTN CurrentNumOfConsoles
;
3105 UINT32 UgaHorizontalResolution
;
3106 UINT32 UgaVerticalResolution
;
3107 UINT32 UgaColorDepth
;
3108 UINT32 UgaRefreshRate
;
3109 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
3111 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
3112 EFI_STATUS DeviceStatus
;
3114 Status
= EFI_SUCCESS
;
3115 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
3118 // If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer().
3120 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
3121 Status
= ConSplitterGrowBuffer (
3122 sizeof (TEXT_OUT_AND_GOP_DATA
),
3123 &Private
->TextOutListCount
,
3124 (VOID
**) &Private
->TextOutList
3126 if (EFI_ERROR (Status
)) {
3127 return EFI_OUT_OF_RESOURCES
;
3130 // Also need to reallocate the TextOutModeMap table
3132 Status
= ConSplitterGrowMapTable (Private
);
3133 if (EFI_ERROR (Status
)) {
3134 return EFI_OUT_OF_RESOURCES
;
3138 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
3140 TextAndGop
->TextOut
= TextOut
;
3141 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
3142 TextAndGop
->UgaDraw
= UgaDraw
;
3144 if (CurrentNumOfConsoles
== 0) {
3146 // Add the first device's output mode to console splitter's mode list
3148 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
3150 ConSplitterSyncOutputMode (Private
, TextOut
);
3153 Private
->CurrentNumberOfConsoles
++;
3156 // Scan both TextOutList, for the intersection TextOut device
3157 // maybe both ConOut and StdErr incorporate the same Text Out
3158 // device in them, thus the output of both should be synced.
3160 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3162 MaxMode
= Private
->TextOutMode
.MaxMode
;
3163 ASSERT (MaxMode
>= 1);
3165 DeviceStatus
= EFI_DEVICE_ERROR
;
3166 Status
= EFI_DEVICE_ERROR
;
3169 // This device display mode will be added into Graphics Ouput modes.
3171 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
3172 DeviceStatus
= ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
3175 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
3177 // If UGA is produced by Consplitter
3179 if (GraphicsOutput
!= NULL
) {
3180 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, GraphicsOutput
->Mode
->Mode
, &SizeOfInfo
, &Info
);
3181 if (EFI_ERROR (Status
)) {
3184 ASSERT ( SizeOfInfo
<= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
3186 UgaHorizontalResolution
= Info
->HorizontalResolution
;
3187 UgaVerticalResolution
= Info
->VerticalResolution
;
3191 } else if (UgaDraw
!= NULL
) {
3192 Status
= UgaDraw
->GetMode (
3194 &UgaHorizontalResolution
,
3195 &UgaVerticalResolution
,
3199 if (!EFI_ERROR (Status
) && EFI_ERROR (DeviceStatus
)) {
3201 // if GetMode is successfully and UGA device hasn't been set, set it
3203 Status
= ConSplitterUgaDrawSetMode (
3205 UgaHorizontalResolution
,
3206 UgaVerticalResolution
,
3212 // If GetMode/SetMode is failed, set to 800x600 mode
3214 if(EFI_ERROR (Status
)) {
3215 Status
= ConSplitterUgaDrawSetMode (
3226 if (((!EFI_ERROR (DeviceStatus
)) || (!EFI_ERROR (Status
))) &&
3227 ((Private
->CurrentNumberOfGraphicsOutput
+ Private
->CurrentNumberOfUgaDraw
) == 1)) {
3228 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
3230 // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed
3231 // on the virtual handle.
3233 Status
= gBS
->InstallMultipleProtocolInterfaces (
3234 &mConOut
.VirtualHandle
,
3235 &gEfiUgaDrawProtocolGuid
,
3239 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
3241 // If UGA Draw protocol not supported, Graphics Output Protocol is installed
3242 // on virtual handle.
3244 Status
= gBS
->InstallMultipleProtocolInterfaces (
3245 &mConOut
.VirtualHandle
,
3246 &gEfiGraphicsOutputProtocolGuid
,
3247 &mConOut
.GraphicsOutput
,
3252 // Boot Graphics Output protocol and UGA Draw protocol are supported,
3253 // both they will be installed on virtual handle.
3255 Status
= gBS
->InstallMultipleProtocolInterfaces (
3256 &mConOut
.VirtualHandle
,
3257 &gEfiGraphicsOutputProtocolGuid
,
3258 &mConOut
.GraphicsOutput
,
3259 &gEfiUgaDrawProtocolGuid
,
3267 // After adding new console device, all existing console devices should be
3268 // synced to the current shared mode.
3270 ConsplitterSetConsoleOutMode (Private
);
3277 Remove Text Out Device in Consplitter Text Out list.
3279 @param Private Text Out Splitter pointer.
3280 @param TextOut Simple Text Output Pointer protocol pointer.
3282 @retval EFI_SUCCESS Text Out Device removed successfully.
3283 @retval EFI_NOT_FOUND No Text Out Device found.
3287 ConSplitterTextOutDeleteDevice (
3288 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
3289 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
3293 UINTN CurrentNumOfConsoles
;
3294 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
3298 // Remove the specified text-out device data structure from the Text out List,
3299 // and rearrange the remaining data structures in the Text out List.
3301 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
3302 Index
= (INT32
) CurrentNumOfConsoles
- 1;
3303 TextOutList
= Private
->TextOutList
;
3304 while (Index
>= 0) {
3305 if (TextOutList
->TextOut
== TextOut
) {
3306 if (TextOutList
->UgaDraw
!= NULL
) {
3307 Private
->CurrentNumberOfUgaDraw
--;
3309 if (TextOutList
->GraphicsOutput
!= NULL
) {
3310 Private
->CurrentNumberOfGraphicsOutput
--;
3312 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
3313 CurrentNumOfConsoles
--;
3321 // The specified TextOut is not managed by the ConSplitter driver
3324 return EFI_NOT_FOUND
;
3327 if ((Private
->CurrentNumberOfGraphicsOutput
== 0) && (Private
->CurrentNumberOfUgaDraw
== 0)) {
3329 // If there is not any physical GOP and UGA device in system,
3330 // Consplitter GOP or UGA protocol will be uninstalled
3332 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
3333 Status
= gBS
->UninstallProtocolInterface (
3334 Private
->VirtualHandle
,
3335 &gEfiUgaDrawProtocolGuid
,
3338 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
3339 Status
= gBS
->UninstallProtocolInterface (
3340 Private
->VirtualHandle
,
3341 &gEfiGraphicsOutputProtocolGuid
,
3342 &Private
->GraphicsOutput
3345 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3346 Private
->VirtualHandle
,
3347 &gEfiUgaDrawProtocolGuid
,
3349 &gEfiGraphicsOutputProtocolGuid
,
3350 &Private
->GraphicsOutput
,
3356 if (CurrentNumOfConsoles
== 0) {
3358 // If the number of consoles is zero, reset all parameters
3360 Private
->CurrentNumberOfConsoles
= 0;
3361 Private
->TextOutMode
.MaxMode
= 1;
3362 Private
->TextOutQueryData
[0].Columns
= 80;
3363 Private
->TextOutQueryData
[0].Rows
= 25;
3364 TextOutSetMode (Private
, 0);
3369 // Max Mode is realy an intersection of the QueryMode command to all
3370 // devices. So we must copy the QueryMode of the first device to
3374 Private
->TextOutQueryData
,
3375 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
3378 FreePool (Private
->TextOutModeMap
);
3379 Private
->TextOutModeMap
= NULL
;
3380 TextOutList
= Private
->TextOutList
;
3383 // Add the first TextOut to the QueryData array and ModeMap table
3385 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
3388 // Now add one by one
3391 Private
->CurrentNumberOfConsoles
= 1;
3393 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
3394 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
3396 Private
->CurrentNumberOfConsoles
++;
3400 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3407 Reset the input device and optionaly run diagnostics
3409 @param This Protocol instance pointer.
3410 @param ExtendedVerification Driver may perform diagnostics on reset.
3412 @retval EFI_SUCCESS The device was reset.
3413 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3419 ConSplitterTextInReset (
3420 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3421 IN BOOLEAN ExtendedVerification
3425 EFI_STATUS ReturnStatus
;
3426 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3429 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3431 Private
->KeyEventSignalState
= FALSE
;
3434 // return the worst status met
3436 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3437 Status
= Private
->TextInList
[Index
]->Reset (
3438 Private
->TextInList
[Index
],
3439 ExtendedVerification
3441 if (EFI_ERROR (Status
)) {
3442 ReturnStatus
= Status
;
3446 if (!EFI_ERROR (ReturnStatus
)) {
3447 ToggleStateSyncReInitialization (Private
);
3450 return ReturnStatus
;
3455 Reads the next keystroke from the input device. The WaitForKey Event can
3456 be used to test for existance of a keystroke via WaitForEvent () call.
3458 @param Private Protocol instance pointer.
3459 @param Key Driver may perform diagnostics on reset.
3461 @retval EFI_SUCCESS The keystroke information was returned.
3462 @retval EFI_NOT_READY There was no keystroke data availiable.
3463 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3469 ConSplitterTextInPrivateReadKeyStroke (
3470 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3471 OUT EFI_INPUT_KEY
*Key
3476 EFI_INPUT_KEY CurrentKey
;
3478 Key
->UnicodeChar
= 0;
3479 Key
->ScanCode
= SCAN_NULL
;
3482 // if no physical console input device exists, return EFI_NOT_READY;
3483 // if any physical console input device has key input,
3484 // return the key and EFI_SUCCESS.
3486 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
;) {
3487 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
3488 Private
->TextInList
[Index
],
3491 if (!EFI_ERROR (Status
)) {
3493 // If it is not partial keystorke, return the key. Otherwise, continue
3494 // to read key from THIS physical console input device.
3496 if ((CurrentKey
.ScanCode
!= CHAR_NULL
) || (CurrentKey
.UnicodeChar
!= SCAN_NULL
)) {
3502 // Continue to read key from NEXT physical console input device.
3508 return EFI_NOT_READY
;
3514 Reads the next keystroke from the input device. The WaitForKey Event can
3515 be used to test for existance of a keystroke via WaitForEvent () call.
3517 @param This Protocol instance pointer.
3518 @param Key Driver may perform diagnostics on reset.
3520 @retval EFI_SUCCESS The keystroke information was returned.
3521 @retval EFI_NOT_READY There was no keystroke data availiable.
3522 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3528 ConSplitterTextInReadKeyStroke (
3529 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3530 OUT EFI_INPUT_KEY
*Key
3533 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3535 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3537 Private
->KeyEventSignalState
= FALSE
;
3540 // Signal ConnectConIn event on first call in Lazy ConIn mode
3542 if (!mConInIsConnect
&& PcdGetBool (PcdConInConnectOnDemand
)) {
3543 DEBUG ((EFI_D_INFO
, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));
3544 gBS
->SignalEvent (Private
->ConnectConInEvent
);
3545 mConInIsConnect
= TRUE
;
3548 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
3553 This event aggregates all the events of the ConIn devices in the spliter.
3555 If any events of physical ConIn devices are signaled, signal the ConIn
3556 spliter event. This will cause the calling code to call
3557 ConSplitterTextInReadKeyStroke ().
3559 @param Event The Event assoicated with callback.
3560 @param Context Context registered when Event was created.
3565 ConSplitterTextInWaitForKey (
3571 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3574 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3576 if (Private
->KeyEventSignalState
) {
3578 // If KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3580 gBS
->SignalEvent (Event
);
3585 // If any physical console input device has key input, signal the event.
3587 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3588 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
3589 if (!EFI_ERROR (Status
)) {
3590 gBS
->SignalEvent (Event
);
3591 Private
->KeyEventSignalState
= TRUE
;
3599 Test if the key has been registered on input device.
3601 @param RegsiteredData A pointer to a buffer that is filled in with the
3602 keystroke state data for the key that was
3604 @param InputData A pointer to a buffer that is filled in with the
3605 keystroke state data for the key that was
3608 @retval TRUE Key be pressed matches a registered key.
3609 @retval FLASE Match failed.
3614 IN EFI_KEY_DATA
*RegsiteredData
,
3615 IN EFI_KEY_DATA
*InputData
3618 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
3620 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
3621 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
3626 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3628 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
3629 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
3632 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
3633 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
3643 Reset the input device and optionaly run diagnostics
3645 @param This Protocol instance pointer.
3646 @param ExtendedVerification Driver may perform diagnostics on reset.
3648 @retval EFI_SUCCESS The device was reset.
3649 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3655 ConSplitterTextInResetEx (
3656 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3657 IN BOOLEAN ExtendedVerification
3661 EFI_STATUS ReturnStatus
;
3662 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3665 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3667 Private
->KeyEventSignalState
= FALSE
;
3670 // return the worst status met
3672 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3673 Status
= Private
->TextInExList
[Index
]->Reset (
3674 Private
->TextInExList
[Index
],
3675 ExtendedVerification
3677 if (EFI_ERROR (Status
)) {
3678 ReturnStatus
= Status
;
3682 if (!EFI_ERROR (ReturnStatus
)) {
3683 ToggleStateSyncReInitialization (Private
);
3686 return ReturnStatus
;
3692 Reads the next keystroke from the input device. The WaitForKey Event can
3693 be used to test for existance of a keystroke via WaitForEvent () call.
3695 @param This Protocol instance pointer.
3696 @param KeyData A pointer to a buffer that is filled in with the
3697 keystroke state data for the key that was
3700 @retval EFI_SUCCESS The keystroke information was returned.
3701 @retval EFI_NOT_READY There was no keystroke data availiable.
3702 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
3704 @retval EFI_INVALID_PARAMETER KeyData is NULL.
3709 ConSplitterTextInReadKeyStrokeEx (
3710 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3711 OUT EFI_KEY_DATA
*KeyData
3714 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3717 EFI_KEY_DATA CurrentKeyData
;
3720 if (KeyData
== NULL
) {
3721 return EFI_INVALID_PARAMETER
;
3724 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3726 Private
->KeyEventSignalState
= FALSE
;
3728 KeyData
->Key
.UnicodeChar
= 0;
3729 KeyData
->Key
.ScanCode
= SCAN_NULL
;
3732 // Signal ConnectConIn event on first call in Lazy ConIn mode
3734 if (!mConInIsConnect
&& PcdGetBool (PcdConInConnectOnDemand
)) {
3735 DEBUG ((EFI_D_INFO
, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));
3736 gBS
->SignalEvent (Private
->ConnectConInEvent
);
3737 mConInIsConnect
= TRUE
;
3741 // if no physical console input device exists, return EFI_NOT_READY;
3742 // if any physical console input device has key input,
3743 // return the key and EFI_SUCCESS.
3745 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
;) {
3746 Status
= Private
->TextInExList
[Index
]->ReadKeyStrokeEx (
3747 Private
->TextInExList
[Index
],
3750 if (!EFI_ERROR (Status
)) {
3752 // If virtual KeyState has been required to be exposed, or it is not
3753 // partial keystorke, return the key. Otherwise, continue to read key
3754 // from THIS physical console input device.
3756 if ((Private
->VirtualKeyStateExported
) ||
3757 (CurrentKeyData
.Key
.ScanCode
!= CHAR_NULL
) ||
3758 (CurrentKeyData
.Key
.UnicodeChar
!= SCAN_NULL
)) {
3759 CopyMem (KeyData
, &CurrentKeyData
, sizeof (CurrentKeyData
));
3764 // Continue to read key from NEXT physical console input device.
3770 return EFI_NOT_READY
;
3775 Set certain state for the input device.
3777 @param This Protocol instance pointer.
3778 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
3779 state for the input device.
3781 @retval EFI_SUCCESS The device state was set successfully.
3782 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3783 could not have the setting adjusted.
3784 @retval EFI_UNSUPPORTED The device does not have the ability to set its
3786 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
3791 ConSplitterTextInSetState (
3792 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3793 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
3796 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3799 EFI_KEY_TOGGLE_STATE PhysicalKeyToggleState
;
3801 if (KeyToggleState
== NULL
) {
3802 return EFI_INVALID_PARAMETER
;
3805 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3808 // Always turn on physical TextInEx partial key report for
3809 // toggle state sync.
3811 PhysicalKeyToggleState
= *KeyToggleState
| EFI_KEY_STATE_EXPOSED
;
3814 // if no physical console input device exists, return EFI_SUCCESS;
3815 // otherwise return the status of setting state of physical console input device
3817 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3818 Status
= Private
->TextInExList
[Index
]->SetState (
3819 Private
->TextInExList
[Index
],
3820 &PhysicalKeyToggleState
3822 if (EFI_ERROR (Status
)) {
3828 // Record the physical KeyToggleState.
3830 Private
->PhysicalKeyToggleState
= PhysicalKeyToggleState
;
3832 // Get if virtual KeyState has been required to be exposed.
3834 Private
->VirtualKeyStateExported
= (((*KeyToggleState
) & EFI_KEY_STATE_EXPOSED
) != 0);
3842 Register a notification function for a particular keystroke for the input device.
3844 @param This Protocol instance pointer.
3845 @param KeyData A pointer to a buffer that is filled in with
3846 the keystroke information for the key that was
3847 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
3848 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
3849 keystroke will trigger a notification of the KeyNotificationFunction.
3850 @param KeyNotificationFunction Points to the function to be called when the key
3851 sequence is typed specified by KeyData. This notification function
3852 should be called at <=TPL_CALLBACK.
3853 @param NotifyHandle Points to the unique handle assigned to the
3854 registered notification.
3856 @retval EFI_SUCCESS The notification function was registered
3858 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
3860 @retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL.
3865 ConSplitterTextInRegisterKeyNotify (
3866 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3867 IN EFI_KEY_DATA
*KeyData
,
3868 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
3869 OUT VOID
**NotifyHandle
3872 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3875 TEXT_IN_EX_SPLITTER_NOTIFY
*NewNotify
;
3877 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3880 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
3881 return EFI_INVALID_PARAMETER
;
3884 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3887 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3889 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3890 CurrentNotify
= TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link
);
3891 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
3892 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
3893 *NotifyHandle
= CurrentNotify
;
3900 // Allocate resource to save the notification function
3902 NewNotify
= (TEXT_IN_EX_SPLITTER_NOTIFY
*) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY
));
3903 if (NewNotify
== NULL
) {
3904 return EFI_OUT_OF_RESOURCES
;
3906 NewNotify
->NotifyHandleList
= (EFI_HANDLE
*) AllocateZeroPool (sizeof (EFI_HANDLE
) * Private
->TextInExListCount
);
3907 if (NewNotify
->NotifyHandleList
== NULL
) {
3908 gBS
->FreePool (NewNotify
);
3909 return EFI_OUT_OF_RESOURCES
;
3911 NewNotify
->Signature
= TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
;
3912 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
3913 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
3916 // Return the wrong status of registering key notify of
3917 // physical console input device if meet problems
3919 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3920 Status
= Private
->TextInExList
[Index
]->RegisterKeyNotify (
3921 Private
->TextInExList
[Index
],
3923 KeyNotificationFunction
,
3924 &NewNotify
->NotifyHandleList
[Index
]
3926 if (EFI_ERROR (Status
)) {
3928 // Un-register the key notify on all physical console input devices
3930 while (Index
-- != 0) {
3931 Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3932 Private
->TextInExList
[Index
],
3933 NewNotify
->NotifyHandleList
[Index
]
3936 gBS
->FreePool (NewNotify
->NotifyHandleList
);
3937 gBS
->FreePool (NewNotify
);
3942 InsertTailList (&Private
->NotifyList
, &NewNotify
->NotifyEntry
);
3944 *NotifyHandle
= NewNotify
;
3952 Remove a registered notification function from a particular keystroke.
3954 @param This Protocol instance pointer.
3955 @param NotificationHandle The handle of the notification function being
3958 @retval EFI_SUCCESS The notification function was unregistered
3960 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
3965 ConSplitterTextInUnregisterKeyNotify (
3966 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3967 IN VOID
*NotificationHandle
3970 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3972 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3975 if (NotificationHandle
== NULL
) {
3976 return EFI_INVALID_PARAMETER
;
3979 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3981 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3982 CurrentNotify
= TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link
);
3983 if (CurrentNotify
== NotificationHandle
) {
3984 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3985 Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3986 Private
->TextInExList
[Index
],
3987 CurrentNotify
->NotifyHandleList
[Index
]
3990 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
3992 gBS
->FreePool (CurrentNotify
->NotifyHandleList
);
3993 gBS
->FreePool (CurrentNotify
);
3999 // NotificationHandle is not found in database
4001 return EFI_INVALID_PARAMETER
;
4006 Reset the input device and optionaly run diagnostics
4008 @param This Protocol instance pointer.
4009 @param ExtendedVerification Driver may perform diagnostics on reset.
4011 @retval EFI_SUCCESS The device was reset.
4012 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
4018 ConSplitterSimplePointerReset (
4019 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
4020 IN BOOLEAN ExtendedVerification
4024 EFI_STATUS ReturnStatus
;
4025 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4028 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
4030 Private
->InputEventSignalState
= FALSE
;
4032 if (Private
->CurrentNumberOfPointers
== 0) {
4036 // return the worst status met
4038 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
4039 Status
= Private
->PointerList
[Index
]->Reset (
4040 Private
->PointerList
[Index
],
4041 ExtendedVerification
4043 if (EFI_ERROR (Status
)) {
4044 ReturnStatus
= Status
;
4048 return ReturnStatus
;
4053 Reads the next keystroke from the input device. The WaitForKey Event can
4054 be used to test for existance of a keystroke via WaitForEvent () call.
4056 @param Private Protocol instance pointer.
4057 @param State The state information of simple pointer device.
4059 @retval EFI_SUCCESS The keystroke information was returned.
4060 @retval EFI_NOT_READY There was no keystroke data availiable.
4061 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
4067 ConSplitterSimplePointerPrivateGetState (
4068 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
4069 IN OUT EFI_SIMPLE_POINTER_STATE
*State
4073 EFI_STATUS ReturnStatus
;
4075 EFI_SIMPLE_POINTER_STATE CurrentState
;
4077 State
->RelativeMovementX
= 0;
4078 State
->RelativeMovementY
= 0;
4079 State
->RelativeMovementZ
= 0;
4080 State
->LeftButton
= FALSE
;
4081 State
->RightButton
= FALSE
;
4084 // if no physical console input device exists, return EFI_NOT_READY;
4085 // if any physical console input device has key input,
4086 // return the key and EFI_SUCCESS.
4088 ReturnStatus
= EFI_NOT_READY
;
4089 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
4091 Status
= Private
->PointerList
[Index
]->GetState (
4092 Private
->PointerList
[Index
],
4095 if (!EFI_ERROR (Status
)) {
4096 if (ReturnStatus
== EFI_NOT_READY
) {
4097 ReturnStatus
= EFI_SUCCESS
;
4100 if (CurrentState
.LeftButton
) {
4101 State
->LeftButton
= TRUE
;
4104 if (CurrentState
.RightButton
) {
4105 State
->RightButton
= TRUE
;
4108 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
4109 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
4112 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
4113 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
4116 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
4117 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
4119 } else if (Status
== EFI_DEVICE_ERROR
) {
4120 ReturnStatus
= EFI_DEVICE_ERROR
;
4124 return ReturnStatus
;
4129 Reads the next keystroke from the input device. The WaitForKey Event can
4130 be used to test for existance of a keystroke via WaitForEvent () call.
4132 @param This A pointer to protocol instance.
4133 @param State A pointer to state information on the pointer device
4135 @retval EFI_SUCCESS The keystroke information was returned in State.
4136 @retval EFI_NOT_READY There was no keystroke data availiable.
4137 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
4143 ConSplitterSimplePointerGetState (
4144 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
4145 IN OUT EFI_SIMPLE_POINTER_STATE
*State
4148 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4150 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
4152 Private
->InputEventSignalState
= FALSE
;
4154 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
4159 This event agregates all the events of the ConIn devices in the spliter.
4160 If any events of physical ConIn devices are signaled, signal the ConIn
4161 spliter event. This will cause the calling code to call
4162 ConSplitterTextInReadKeyStroke ().
4164 @param Event The Event assoicated with callback.
4165 @param Context Context registered when Event was created.
4170 ConSplitterSimplePointerWaitForInput (
4176 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4179 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
4182 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
4184 if (Private
->InputEventSignalState
) {
4185 gBS
->SignalEvent (Event
);
4189 // if any physical console input device has key input, signal the event.
4191 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
4192 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
4193 if (!EFI_ERROR (Status
)) {
4194 gBS
->SignalEvent (Event
);
4195 Private
->InputEventSignalState
= TRUE
;
4201 Resets the pointer device hardware.
4203 @param This Protocol instance pointer.
4204 @param ExtendedVerification Driver may perform diagnostics on reset.
4206 @retval EFI_SUCCESS The device was reset.
4207 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
4213 ConSplitterAbsolutePointerReset (
4214 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4215 IN BOOLEAN ExtendedVerification
4219 EFI_STATUS ReturnStatus
;
4220 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4223 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4225 Private
->AbsoluteInputEventSignalState
= FALSE
;
4227 if (Private
->CurrentNumberOfAbsolutePointers
== 0) {
4231 // return the worst status met
4233 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4234 Status
= Private
->AbsolutePointerList
[Index
]->Reset (
4235 Private
->AbsolutePointerList
[Index
],
4236 ExtendedVerification
4238 if (EFI_ERROR (Status
)) {
4239 ReturnStatus
= Status
;
4243 return ReturnStatus
;
4248 Retrieves the current state of a pointer device.
4250 @param This Protocol instance pointer.
4251 @param State A pointer to the state information on the
4254 @retval EFI_SUCCESS The state of the pointer device was returned in
4256 @retval EFI_NOT_READY The state of the pointer device has not changed
4257 since the last call to GetState().
4258 @retval EFI_DEVICE_ERROR A device error occurred while attempting to
4259 retrieve the pointer device's current state.
4264 ConSplitterAbsolutePointerGetState (
4265 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4266 IN OUT EFI_ABSOLUTE_POINTER_STATE
*State
4269 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4271 EFI_STATUS ReturnStatus
;
4273 EFI_ABSOLUTE_POINTER_STATE CurrentState
;
4287 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4289 Private
->AbsoluteInputEventSignalState
= FALSE
;
4291 State
->CurrentX
= 0;
4292 State
->CurrentY
= 0;
4293 State
->CurrentZ
= 0;
4294 State
->ActiveButtons
= 0;
4296 VirtualMinX
= Private
->AbsolutePointerMode
.AbsoluteMinX
;
4297 VirtualMinY
= Private
->AbsolutePointerMode
.AbsoluteMinY
;
4298 VirtualMinZ
= Private
->AbsolutePointerMode
.AbsoluteMinZ
;
4299 VirtualMaxX
= Private
->AbsolutePointerMode
.AbsoluteMaxX
;
4300 VirtualMaxY
= Private
->AbsolutePointerMode
.AbsoluteMaxY
;
4301 VirtualMaxZ
= Private
->AbsolutePointerMode
.AbsoluteMaxZ
;
4304 // if no physical pointer device exists, return EFI_NOT_READY;
4305 // if any physical pointer device has changed state,
4306 // return the state and EFI_SUCCESS.
4308 ReturnStatus
= EFI_NOT_READY
;
4309 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4311 Status
= Private
->AbsolutePointerList
[Index
]->GetState (
4312 Private
->AbsolutePointerList
[Index
],
4315 if (!EFI_ERROR (Status
)) {
4316 if (ReturnStatus
== EFI_NOT_READY
) {
4317 ReturnStatus
= EFI_SUCCESS
;
4320 MinX
= Private
->AbsolutePointerList
[Index
]->Mode
->AbsoluteMinX
;
4321 MinY
= Private
->AbsolutePointerList
[Index
]->Mode
->AbsoluteMinY
;
4322 MinZ
= Private
->AbsolutePointerList
[Index
]->Mode
->AbsoluteMinZ
;
4323 MaxX
= Private
->AbsolutePointerList
[Index
]->Mode
->AbsoluteMaxX
;
4324 MaxY
= Private
->AbsolutePointerList
[Index
]->Mode
->AbsoluteMaxY
;
4325 MaxZ
= Private
->AbsolutePointerList
[Index
]->Mode
->AbsoluteMaxZ
;
4327 State
->ActiveButtons
= CurrentState
.ActiveButtons
;
4330 // Rescale to Con Splitter virtual Absolute Pointer's resolution.
4332 if (!(MinX
== 0 && MaxX
== 0)) {
4333 State
->CurrentX
= VirtualMinX
+ DivU64x64Remainder (
4335 CurrentState
.CurrentX
,
4336 VirtualMaxX
- VirtualMinX
4342 if (!(MinY
== 0 && MaxY
== 0)) {
4343 State
->CurrentY
= VirtualMinY
+ DivU64x64Remainder (
4345 CurrentState
.CurrentY
,
4346 VirtualMaxY
- VirtualMinY
4352 if (!(MinZ
== 0 && MaxZ
== 0)) {
4353 State
->CurrentZ
= VirtualMinZ
+ DivU64x64Remainder (
4355 CurrentState
.CurrentZ
,
4356 VirtualMaxZ
- VirtualMinZ
4363 } else if (Status
== EFI_DEVICE_ERROR
) {
4364 ReturnStatus
= EFI_DEVICE_ERROR
;
4368 return ReturnStatus
;
4373 This event agregates all the events of the pointer devices in the splitter.
4374 If any events of physical pointer devices are signaled, signal the pointer
4375 splitter event. This will cause the calling code to call
4376 ConSplitterAbsolutePointerGetState ().
4378 @param Event The Event assoicated with callback.
4379 @param Context Context registered when Event was created.
4384 ConSplitterAbsolutePointerWaitForInput (
4390 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4393 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
4396 // if AbsoluteInputEventSignalState is flagged before,
4397 // and not cleared by Reset() or GetState(), signal it
4399 if (Private
->AbsoluteInputEventSignalState
) {
4400 gBS
->SignalEvent (Event
);
4404 // if any physical console input device has key input, signal the event.
4406 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4407 Status
= gBS
->CheckEvent (Private
->AbsolutePointerList
[Index
]->WaitForInput
);
4408 if (!EFI_ERROR (Status
)) {
4409 gBS
->SignalEvent (Event
);
4410 Private
->AbsoluteInputEventSignalState
= TRUE
;
4417 Reset the text output device hardware and optionaly run diagnostics
4419 @param This Protocol instance pointer.
4420 @param ExtendedVerification Driver may perform more exhaustive verfication
4421 operation of the device during reset.
4423 @retval EFI_SUCCESS The text output device was reset.
4424 @retval EFI_DEVICE_ERROR The text output device is not functioning
4425 correctly and could not be reset.
4430 ConSplitterTextOutReset (
4431 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4432 IN BOOLEAN ExtendedVerification
4436 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4438 EFI_STATUS ReturnStatus
;
4440 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4443 // return the worst status met
4445 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4446 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
4447 Private
->TextOutList
[Index
].TextOut
,
4448 ExtendedVerification
4450 if (EFI_ERROR (Status
)) {
4451 ReturnStatus
= Status
;
4455 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BLACK
));
4458 // reset all mode parameters
4460 TextOutSetMode (Private
, 0);
4462 return ReturnStatus
;
4467 Write a Unicode string to the output device.
4469 @param This Protocol instance pointer.
4470 @param WString The NULL-terminated Unicode string to be
4471 displayed on the output device(s). All output
4472 devices must also support the Unicode drawing
4473 defined in this file.
4475 @retval EFI_SUCCESS The string was output to the device.
4476 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
4478 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
4480 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
4481 characters in the Unicode string could not be
4482 rendered and were skipped.
4487 ConSplitterTextOutOutputString (
4488 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4493 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4495 EFI_STATUS ReturnStatus
;
4499 This
->SetAttribute (This
, This
->Mode
->Attribute
);
4501 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4504 // return the worst status met
4506 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4507 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
4508 Private
->TextOutList
[Index
].TextOut
,
4511 if (EFI_ERROR (Status
)) {
4512 ReturnStatus
= Status
;
4516 if (Private
->CurrentNumberOfConsoles
> 0) {
4517 Private
->TextOutMode
.CursorColumn
= Private
->TextOutList
[0].TextOut
->Mode
->CursorColumn
;
4518 Private
->TextOutMode
.CursorRow
= Private
->TextOutList
[0].TextOut
->Mode
->CursorRow
;
4521 // When there is no real console devices in system,
4522 // update cursor position for the virtual device in consplitter.
4524 Private
->TextOut
.QueryMode (
4526 Private
->TextOutMode
.Mode
,
4530 for (; *WString
!= CHAR_NULL
; WString
++) {
4532 case CHAR_BACKSPACE
:
4533 if (Private
->TextOutMode
.CursorColumn
== 0 && Private
->TextOutMode
.CursorRow
> 0) {
4534 Private
->TextOutMode
.CursorRow
--;
4535 Private
->TextOutMode
.CursorColumn
= (INT32
) (MaxColumn
- 1);
4536 } else if (Private
->TextOutMode
.CursorColumn
> 0) {
4537 Private
->TextOutMode
.CursorColumn
--;
4542 if (Private
->TextOutMode
.CursorRow
< (INT32
) (MaxRow
- 1)) {
4543 Private
->TextOutMode
.CursorRow
++;
4547 case CHAR_CARRIAGE_RETURN
:
4548 Private
->TextOutMode
.CursorColumn
= 0;
4552 if (Private
->TextOutMode
.CursorColumn
< (INT32
) (MaxColumn
- 1)) {
4553 Private
->TextOutMode
.CursorColumn
++;
4555 Private
->TextOutMode
.CursorColumn
= 0;
4556 if (Private
->TextOutMode
.CursorRow
< (INT32
) (MaxRow
- 1)) {
4557 Private
->TextOutMode
.CursorRow
++;
4565 return ReturnStatus
;
4570 Verifies that all characters in a Unicode string can be output to the
4573 @param This Protocol instance pointer.
4574 @param WString The NULL-terminated Unicode string to be
4575 examined for the output device(s).
4577 @retval EFI_SUCCESS The device(s) are capable of rendering the
4579 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string
4580 cannot be rendered by one or more of the output
4581 devices mapped by the EFI handle.
4586 ConSplitterTextOutTestString (
4587 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4592 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4594 EFI_STATUS ReturnStatus
;
4596 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4599 // return the worst status met
4601 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4602 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
4603 Private
->TextOutList
[Index
].TextOut
,
4606 if (EFI_ERROR (Status
)) {
4607 ReturnStatus
= Status
;
4611 // There is no DevNullTextOutTestString () since a Unicode buffer would
4612 // always return EFI_SUCCESS.
4613 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4615 return ReturnStatus
;
4620 Returns information for an available text mode that the output device(s)
4623 @param This Protocol instance pointer.
4624 @param ModeNumber The mode number to return information on.
4625 @param Columns Returns the columns of the text output device
4626 for the requested ModeNumber.
4627 @param Rows Returns the rows of the text output device
4628 for the requested ModeNumber.
4630 @retval EFI_SUCCESS The requested mode information was returned.
4631 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4633 @retval EFI_UNSUPPORTED The mode number was not valid.
4638 ConSplitterTextOutQueryMode (
4639 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4640 IN UINTN ModeNumber
,
4645 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4647 INT32
*TextOutModeMap
;
4649 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4652 // Check whether param ModeNumber is valid.
4653 // ModeNumber should be within range 0 ~ MaxMode - 1.
4655 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4656 return EFI_UNSUPPORTED
;
4659 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4660 return EFI_UNSUPPORTED
;
4664 // We get the available mode from mode intersection map if it's available
4666 if (Private
->TextOutModeMap
!= NULL
) {
4667 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4668 CurrentMode
= (UINTN
)(*TextOutModeMap
);
4669 *Columns
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4670 *Rows
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4672 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
4673 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
4676 if (*Columns
<= 0 && *Rows
<= 0) {
4677 return EFI_UNSUPPORTED
;
4686 Sets the output device(s) to a specified mode.
4688 @param This Protocol instance pointer.
4689 @param ModeNumber The mode number to set.
4691 @retval EFI_SUCCESS The requested text mode was set.
4692 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4694 @retval EFI_UNSUPPORTED The mode number was not valid.
4699 ConSplitterTextOutSetMode (
4700 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4705 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4707 INT32
*TextOutModeMap
;
4708 EFI_STATUS ReturnStatus
;
4710 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4713 // Check whether param ModeNumber is valid.
4714 // ModeNumber should be within range 0 ~ MaxMode - 1.
4716 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4717 return EFI_UNSUPPORTED
;
4720 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4721 return EFI_UNSUPPORTED
;
4724 // If the mode is being set to the curent mode, then just clear the screen and return.
4726 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
4727 return ConSplitterTextOutClearScreen (This
);
4730 // return the worst status met
4732 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4733 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4734 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
4735 Private
->TextOutList
[Index
].TextOut
,
4736 TextOutModeMap
[Index
]
4738 if (EFI_ERROR (Status
)) {
4739 ReturnStatus
= Status
;
4744 // Set mode parameter to specified mode number
4746 TextOutSetMode (Private
, ModeNumber
);
4748 return ReturnStatus
;
4753 Sets the background and foreground colors for the OutputString () and
4754 ClearScreen () functions.
4756 @param This Protocol instance pointer.
4757 @param Attribute The attribute to set. Bits 0..3 are the
4758 foreground color, and bits 4..6 are the
4759 background color. All other bits are undefined
4760 and must be zero. The valid Attributes are
4761 defined in this file.
4763 @retval EFI_SUCCESS The attribute was set.
4764 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4766 @retval EFI_UNSUPPORTED The attribute requested is not defined.
4771 ConSplitterTextOutSetAttribute (
4772 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4777 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4779 EFI_STATUS ReturnStatus
;
4781 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4784 // Check whether param Attribute is valid.
4786 if ((Attribute
| 0x7F) != 0x7F) {
4787 return EFI_UNSUPPORTED
;
4791 // return the worst status met
4793 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4794 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
4795 Private
->TextOutList
[Index
].TextOut
,
4798 if (EFI_ERROR (Status
)) {
4799 ReturnStatus
= Status
;
4803 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
4805 return ReturnStatus
;
4810 Clears the output device(s) display to the currently selected background
4813 @param This Protocol instance pointer.
4815 @retval EFI_SUCCESS The operation completed successfully.
4816 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4818 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4823 ConSplitterTextOutClearScreen (
4824 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
4828 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4830 EFI_STATUS ReturnStatus
;
4832 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4835 // return the worst status met
4837 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4838 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4839 if (EFI_ERROR (Status
)) {
4840 ReturnStatus
= Status
;
4845 // No need to do extra check here as whether (Column, Row) is valid has
4846 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4847 // always be supported.
4849 Private
->TextOutMode
.CursorColumn
= 0;
4850 Private
->TextOutMode
.CursorRow
= 0;
4851 Private
->TextOutMode
.CursorVisible
= TRUE
;
4853 return ReturnStatus
;
4858 Sets the current coordinates of the cursor position
4860 @param This Protocol instance pointer.
4861 @param Column The column position to set the cursor to. Must be
4862 greater than or equal to zero and less than the
4863 number of columns by QueryMode ().
4864 @param Row The row position to set the cursor to. Must be
4865 greater than or equal to zero and less than the
4866 number of rows by QueryMode ().
4868 @retval EFI_SUCCESS The operation completed successfully.
4869 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4871 @retval EFI_UNSUPPORTED The output device is not in a valid text mode,
4872 or the cursor position is invalid for the
4878 ConSplitterTextOutSetCursorPosition (
4879 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4885 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4887 EFI_STATUS ReturnStatus
;
4890 INT32
*TextOutModeMap
;
4894 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4895 TextOutModeMap
= NULL
;
4896 ModeNumber
= Private
->TextOutMode
.Mode
;
4899 // Get current MaxColumn and MaxRow from intersection map
4901 if (Private
->TextOutModeMap
!= NULL
) {
4902 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4903 CurrentMode
= *TextOutModeMap
;
4905 CurrentMode
= ModeNumber
;
4908 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4909 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4911 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
4912 return EFI_UNSUPPORTED
;
4915 // return the worst status met
4917 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4918 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
4919 Private
->TextOutList
[Index
].TextOut
,
4923 if (EFI_ERROR (Status
)) {
4924 ReturnStatus
= Status
;
4929 // No need to do extra check here as whether (Column, Row) is valid has
4930 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4931 // always be supported.
4933 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
4934 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
4936 return ReturnStatus
;
4941 Makes the cursor visible or invisible
4943 @param This Protocol instance pointer.
4944 @param Visible If TRUE, the cursor is set to be visible. If
4945 FALSE, the cursor is set to be invisible.
4947 @retval EFI_SUCCESS The operation completed successfully.
4948 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4949 the request, or the device does not support
4950 changing the cursor mode.
4951 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4956 ConSplitterTextOutEnableCursor (
4957 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4962 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4964 EFI_STATUS ReturnStatus
;
4966 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4969 // return the worst status met
4971 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4972 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
4973 Private
->TextOutList
[Index
].TextOut
,
4976 if (EFI_ERROR (Status
)) {
4977 ReturnStatus
= Status
;
4981 Private
->TextOutMode
.CursorVisible
= Visible
;
4983 return ReturnStatus
;