2 Console Splitter Driver. Any Handle that attatched
3 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
5 So far it works like any other driver by opening a SimpleTextIn and/or
6 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
7 difference is this driver does not layer a protocol on the passed in
8 handle, or construct a child handle like a standard device or bus driver.
9 This driver produces three virtual handles as children, one for console input
10 splitter, one for console output splitter and one for error output splitter.
11 EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
12 identify the splitter type.
14 Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
15 and Console I/O protocol, will be produced in the driver entry point.
16 The virtual handle are added on driver entry and never removed.
17 Such design ensures sytem function well during none console device situation.
19 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
20 All rights reserved. This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 #include "ConSplitter.h"
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
36 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
39 ConSplitterTextInReset
,
40 ConSplitterTextInReadKeyStroke
,
44 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
**) NULL
,
48 ConSplitterSimplePointerReset
,
49 ConSplitterSimplePointerGetState
,
51 (EFI_SIMPLE_POINTER_MODE
*) NULL
61 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
84 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
85 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
88 ConSplitterTextOutReset
,
89 ConSplitterTextOutOutputString
,
90 ConSplitterTextOutTestString
,
91 ConSplitterTextOutQueryMode
,
92 ConSplitterTextOutSetMode
,
93 ConSplitterTextOutSetAttribute
,
94 ConSplitterTextOutClearScreen
,
95 ConSplitterTextOutSetCursorPosition
,
96 ConSplitterTextOutEnableCursor
,
97 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
108 ConSpliterUgaDrawGetMode
,
109 ConSpliterUgaDrawSetMode
,
116 (EFI_UGA_PIXEL
*) NULL
,
118 ConSpliterGraphicsOutputQueryMode
,
119 ConSpliterGraphicsOutputSetMode
,
120 ConSpliterGraphicsOutputBlt
,
123 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
124 (TEXT_OUT_GOP_MODE
*) NULL
,
128 ConSpliterConsoleControlGetMode
,
129 ConSpliterConsoleControlSetMode
,
130 ConSpliterConsoleControlLockStdIn
134 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
136 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
140 EfiConsoleControlScreenText
,
147 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
148 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
151 ConSplitterTextOutReset
,
152 ConSplitterTextOutOutputString
,
153 ConSplitterTextOutTestString
,
154 ConSplitterTextOutQueryMode
,
155 ConSplitterTextOutSetMode
,
156 ConSplitterTextOutSetAttribute
,
157 ConSplitterTextOutClearScreen
,
158 ConSplitterTextOutSetCursorPosition
,
159 ConSplitterTextOutEnableCursor
,
160 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
171 ConSpliterUgaDrawGetMode
,
172 ConSpliterUgaDrawSetMode
,
179 (EFI_UGA_PIXEL
*) NULL
,
181 ConSpliterGraphicsOutputQueryMode
,
182 ConSpliterGraphicsOutputSetMode
,
183 ConSpliterGraphicsOutputBlt
,
186 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
187 (TEXT_OUT_GOP_MODE
*) NULL
,
191 ConSpliterConsoleControlGetMode
,
192 ConSpliterConsoleControlSetMode
,
193 ConSpliterConsoleControlLockStdIn
197 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
199 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
203 EfiConsoleControlScreenText
,
210 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
211 ConSplitterConInDriverBindingSupported
,
212 ConSplitterConInDriverBindingStart
,
213 ConSplitterConInDriverBindingStop
,
219 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
220 ConSplitterSimplePointerDriverBindingSupported
,
221 ConSplitterSimplePointerDriverBindingStart
,
222 ConSplitterSimplePointerDriverBindingStop
,
228 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
229 ConSplitterConOutDriverBindingSupported
,
230 ConSplitterConOutDriverBindingStart
,
231 ConSplitterConOutDriverBindingStop
,
237 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
238 ConSplitterStdErrDriverBindingSupported
,
239 ConSplitterStdErrDriverBindingStart
,
240 ConSplitterStdErrDriverBindingStop
,
247 The user Entry Point for module ConSplitter. The user code starts with this function.
249 @param[in] ImageHandle The firmware allocated handle for the EFI image.
250 @param[in] SystemTable A pointer to the EFI System Table.
252 @retval EFI_SUCCESS The entry point is executed successfully.
253 @retval other Some error occurs when executing this entry point.
258 InitializeConSplitter(
259 IN EFI_HANDLE ImageHandle
,
260 IN EFI_SYSTEM_TABLE
*SystemTable
266 // Install driver model protocol(s).
268 Status
= EfiLibInstallDriverBindingComponentName2 (
271 &gConSplitterConInDriverBinding
,
273 &gConSplitterConInComponentName
,
274 &gConSplitterConInComponentName2
276 ASSERT_EFI_ERROR (Status
);
278 Status
= EfiLibInstallDriverBindingComponentName2 (
281 &gConSplitterSimplePointerDriverBinding
,
283 &gConSplitterSimplePointerComponentName
,
284 &gConSplitterSimplePointerComponentName2
286 ASSERT_EFI_ERROR (Status
);
288 Status
= EfiLibInstallDriverBindingComponentName2 (
291 &gConSplitterConOutDriverBinding
,
293 &gConSplitterConOutComponentName
,
294 &gConSplitterConOutComponentName2
296 ASSERT_EFI_ERROR (Status
);
298 Status
= EfiLibInstallDriverBindingComponentName2 (
301 &gConSplitterStdErrDriverBinding
,
303 &gConSplitterStdErrComponentName
,
304 &gConSplitterStdErrComponentName2
306 ASSERT_EFI_ERROR (Status
);
310 // Call the original Entry Point
312 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
320 ConSplitterDriverEntry (
321 IN EFI_HANDLE ImageHandle
,
322 IN EFI_SYSTEM_TABLE
*SystemTable
327 Intialize a virtual console device to act as an agrigator of physical console
331 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
332 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
340 ASSERT (FeaturePcdGet (PcdConOutGopSupport
) ||
341 FeaturePcdGet (PcdConOutUgaSupport
));
343 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
344 // The virtual handles will always exist even if no console exist in the
345 // system. This is need to support hotplug devices like USB.
348 // Create virtual device handle for StdErr Splitter
350 Status
= ConSplitterTextOutConstructor (&mStdErr
);
351 if (!EFI_ERROR (Status
)) {
352 Status
= gBS
->InstallMultipleProtocolInterfaces (
353 &mStdErr
.VirtualHandle
,
354 &gEfiSimpleTextOutProtocolGuid
,
356 &gEfiPrimaryStandardErrorDeviceGuid
,
362 // Create virtual device handle for ConIn Splitter
364 Status
= ConSplitterTextInConstructor (&mConIn
);
365 if (!EFI_ERROR (Status
)) {
366 Status
= gBS
->InstallMultipleProtocolInterfaces (
367 &mConIn
.VirtualHandle
,
368 &gEfiSimpleTextInProtocolGuid
,
370 &gEfiSimplePointerProtocolGuid
,
371 &mConIn
.SimplePointer
,
372 &gEfiPrimaryConsoleInDeviceGuid
,
376 if (!EFI_ERROR (Status
)) {
378 // Update the EFI System Table with new virtual console
380 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
381 gST
->ConIn
= &mConIn
.TextIn
;
385 // Create virtual device handle for ConOut Splitter
387 Status
= ConSplitterTextOutConstructor (&mConOut
);
388 if (!EFI_ERROR (Status
)) {
389 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
391 // In EFI mode, UGA Draw protocol is installed
393 Status
= gBS
->InstallMultipleProtocolInterfaces (
394 &mConOut
.VirtualHandle
,
395 &gEfiSimpleTextOutProtocolGuid
,
397 &gEfiUgaDrawProtocolGuid
,
399 &gEfiConsoleControlProtocolGuid
,
400 &mConOut
.ConsoleControl
,
401 &gEfiPrimaryConsoleOutDeviceGuid
,
405 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
407 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
409 Status
= gBS
->InstallMultipleProtocolInterfaces (
410 &mConOut
.VirtualHandle
,
411 &gEfiSimpleTextOutProtocolGuid
,
413 &gEfiGraphicsOutputProtocolGuid
,
414 &mConOut
.GraphicsOutput
,
415 &gEfiConsoleControlProtocolGuid
,
416 &mConOut
.ConsoleControl
,
417 &gEfiPrimaryConsoleOutDeviceGuid
,
423 // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are
424 // installed on virtual handle.
426 Status
= gBS
->InstallMultipleProtocolInterfaces (
427 &mConOut
.VirtualHandle
,
428 &gEfiSimpleTextOutProtocolGuid
,
430 &gEfiGraphicsOutputProtocolGuid
,
431 &mConOut
.GraphicsOutput
,
432 &gEfiUgaDrawProtocolGuid
,
434 &gEfiConsoleControlProtocolGuid
,
435 &mConOut
.ConsoleControl
,
436 &gEfiPrimaryConsoleOutDeviceGuid
,
442 if (!EFI_ERROR (Status
)) {
444 // Update the EFI System Table with new virtual console
446 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
447 gST
->ConOut
= &mConOut
.TextOut
;
452 // Update the CRC32 in the EFI System Table header
455 gBS
->CalculateCrc32 (
465 ConSplitterTextInConstructor (
466 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
472 Construct the ConSplitter.
476 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
479 EFI_OUT_OF_RESOURCES - Out of resources.
486 // Initilize console input splitter's private data.
488 Status
= ConSplitterGrowBuffer (
489 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
490 &ConInPrivate
->TextInListCount
,
491 (VOID
**) &ConInPrivate
->TextInList
493 if (EFI_ERROR (Status
)) {
494 return EFI_OUT_OF_RESOURCES
;
497 // Create Event to support locking StdIn Device
499 Status
= gBS
->CreateEvent (
500 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
502 ConSpliterConsoleControlLockStdInEvent
,
504 &ConInPrivate
->LockEvent
506 ASSERT_EFI_ERROR (Status
);
508 Status
= gBS
->CreateEvent (
511 ConSplitterTextInWaitForKey
,
513 &ConInPrivate
->TextIn
.WaitForKey
515 ASSERT_EFI_ERROR (Status
);
517 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
519 Status
= ConSplitterGrowBuffer (
520 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
521 &ConInPrivate
->PointerListCount
,
522 (VOID
**) &ConInPrivate
->PointerList
524 if (EFI_ERROR (Status
)) {
525 return EFI_OUT_OF_RESOURCES
;
528 Status
= gBS
->CreateEvent (
531 ConSplitterSimplePointerWaitForInput
,
533 &ConInPrivate
->SimplePointer
.WaitForInput
540 ConSplitterTextOutConstructor (
541 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
547 // Initilize console output splitter's private data.
549 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
551 Status
= ConSplitterGrowBuffer (
552 sizeof (TEXT_OUT_AND_GOP_DATA
),
553 &ConOutPrivate
->TextOutListCount
,
554 (VOID
**) &ConOutPrivate
->TextOutList
556 if (EFI_ERROR (Status
)) {
557 return EFI_OUT_OF_RESOURCES
;
560 Status
= ConSplitterGrowBuffer (
561 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
562 &ConOutPrivate
->TextOutQueryDataCount
,
563 (VOID
**) &ConOutPrivate
->TextOutQueryData
565 if (EFI_ERROR (Status
)) {
566 return EFI_OUT_OF_RESOURCES
;
569 // Setup the DevNullTextOut console to 80 x 25
571 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
572 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
573 DevNullTextOutSetMode (ConOutPrivate
, 0);
575 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
577 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
579 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
581 if (FeaturePcdGet (PcdConOutGopSupport
)) {
583 // Setup resource for mode information in Graphics Output Protocol interface
585 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
586 return EFI_OUT_OF_RESOURCES
;
588 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
589 return EFI_OUT_OF_RESOURCES
;
592 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
594 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
595 return EFI_OUT_OF_RESOURCES
;
597 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
598 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
601 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
602 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
603 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
605 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
606 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
607 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
608 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
609 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
611 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
613 // Initial current mode to unknow state, and then set to mode 0
615 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
616 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
624 ConSplitterSupported (
625 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
626 IN EFI_HANDLE ControllerHandle
,
632 Generic Supported Check
635 This - Pointer to protocol.
636 ControllerHandle - Controller Handle.
641 EFI_UNSUPPORTED - unsupported.
642 EFI_SUCCESS - operation is OK.
650 // Make sure the Console Splitter does not attempt to attach to itself
652 if (ControllerHandle
== mConIn
.VirtualHandle
) {
653 return EFI_UNSUPPORTED
;
656 if (ControllerHandle
== mConOut
.VirtualHandle
) {
657 return EFI_UNSUPPORTED
;
660 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
661 return EFI_UNSUPPORTED
;
664 // Check to see whether the handle has the ConsoleInDevice GUID on it
666 Status
= gBS
->OpenProtocol (
670 This
->DriverBindingHandle
,
672 EFI_OPEN_PROTOCOL_BY_DRIVER
675 if (EFI_ERROR (Status
)) {
682 This
->DriverBindingHandle
,
691 ConSplitterConInDriverBindingSupported (
692 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
693 IN EFI_HANDLE ControllerHandle
,
694 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
699 Console In Supported Check
702 This - Pointer to protocol.
703 ControllerHandle - Controller handle.
704 RemainingDevicePath - Remaining device path.
712 return ConSplitterSupported (
715 &gEfiConsoleInDeviceGuid
721 ConSplitterSimplePointerDriverBindingSupported (
722 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
723 IN EFI_HANDLE ControllerHandle
,
724 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
729 Standard Error Supported Check
732 This - Pointer to protocol.
733 ControllerHandle - Controller handle.
734 RemainingDevicePath - Remaining device path.
742 return ConSplitterSupported (
745 &gEfiSimplePointerProtocolGuid
751 ConSplitterConOutDriverBindingSupported (
752 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
753 IN EFI_HANDLE ControllerHandle
,
754 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
759 Console Out Supported Check
762 This - Pointer to protocol.
763 ControllerHandle - Controller handle.
764 RemainingDevicePath - Remaining device path.
772 return ConSplitterSupported (
775 &gEfiConsoleOutDeviceGuid
781 ConSplitterStdErrDriverBindingSupported (
782 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
783 IN EFI_HANDLE ControllerHandle
,
784 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
789 Standard Error Supported Check
792 This - Pointer to protocol.
793 ControllerHandle - Controller handle.
794 RemainingDevicePath - Remaining device path.
802 return ConSplitterSupported (
805 &gEfiStandardErrorDeviceGuid
813 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
814 IN EFI_HANDLE ControllerHandle
,
815 IN EFI_HANDLE ConSplitterVirtualHandle
,
816 IN EFI_GUID
*DeviceGuid
,
817 IN EFI_GUID
*InterfaceGuid
,
823 Start ConSplitter on ControllerHandle, and create the virtual
824 agrogated console device on first call Start for a SimpleTextIn handle.
827 (Standard DriverBinding Protocol Start() function)
830 EFI_ERROR if a SimpleTextIn protocol is not started.
838 // Check to see whether the handle has the ConsoleInDevice GUID on it
840 Status
= gBS
->OpenProtocol (
844 This
->DriverBindingHandle
,
846 EFI_OPEN_PROTOCOL_BY_DRIVER
848 if (EFI_ERROR (Status
)) {
852 Status
= gBS
->OpenProtocol (
856 This
->DriverBindingHandle
,
857 ConSplitterVirtualHandle
,
858 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
860 if (EFI_ERROR (Status
)) {
864 return gBS
->OpenProtocol (
868 This
->DriverBindingHandle
,
869 ConSplitterVirtualHandle
,
870 EFI_OPEN_PROTOCOL_GET_PROTOCOL
876 ConSplitterConInDriverBindingStart (
877 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
878 IN EFI_HANDLE ControllerHandle
,
879 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
884 Start ConSplitter on ControllerHandle, and create the virtual
885 agrogated console device on first call Start for a SimpleTextIn handle.
888 This - Pointer to protocol.
889 ControllerHandle - Controller handle.
890 RemainingDevicePath - Remaining device path.
895 EFI_ERROR if a SimpleTextIn protocol is not started.
900 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
903 // Start ConSplitter on ControllerHandle, and create the virtual
904 // agrogated console device on first call Start for a SimpleTextIn handle.
906 Status
= ConSplitterStart (
909 mConIn
.VirtualHandle
,
910 &gEfiConsoleInDeviceGuid
,
911 &gEfiSimpleTextInProtocolGuid
,
914 if (EFI_ERROR (Status
)) {
918 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
923 ConSplitterSimplePointerDriverBindingStart (
924 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
925 IN EFI_HANDLE ControllerHandle
,
926 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
931 Start ConSplitter on ControllerHandle, and create the virtual
932 agrogated console device on first call Start for a SimpleTextIn handle.
935 This - Pointer to protocol.
936 ControllerHandle - Controller handle.
937 RemainingDevicePath - Remaining device path.
941 EFI_ERROR if a SimpleTextIn protocol is not started.
946 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
948 Status
= ConSplitterStart (
951 mConIn
.VirtualHandle
,
952 &gEfiSimplePointerProtocolGuid
,
953 &gEfiSimplePointerProtocolGuid
,
954 (VOID
**) &SimplePointer
956 if (EFI_ERROR (Status
)) {
960 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
965 ConSplitterConOutDriverBindingStart (
966 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
967 IN EFI_HANDLE ControllerHandle
,
968 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
973 Start ConSplitter on ControllerHandle, and create the virtual
974 agrogated console device on first call Start for a SimpleTextIn handle.
977 This - Pointer to protocol.
978 ControllerHandle - Controller handle.
979 RemainingDevicePath - Remaining device path.
982 EFI_ERROR if a SimpleTextIn protocol is not started.
987 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
988 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
989 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
991 Status
= ConSplitterStart (
994 mConOut
.VirtualHandle
,
995 &gEfiConsoleOutDeviceGuid
,
996 &gEfiSimpleTextOutProtocolGuid
,
999 if (EFI_ERROR (Status
)) {
1003 // Try to Open Graphics Output protocol
1005 Status
= gBS
->OpenProtocol (
1007 &gEfiGraphicsOutputProtocolGuid
,
1008 (VOID
**) &GraphicsOutput
,
1009 This
->DriverBindingHandle
,
1010 mConOut
.VirtualHandle
,
1011 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1013 if (EFI_ERROR (Status
)) {
1014 GraphicsOutput
= NULL
;
1017 // Open UGA_DRAW protocol
1019 Status
= gBS
->OpenProtocol (
1021 &gEfiUgaDrawProtocolGuid
,
1023 This
->DriverBindingHandle
,
1024 mConOut
.VirtualHandle
,
1025 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1027 if (EFI_ERROR (Status
)) {
1031 // If both ConOut and StdErr incorporate the same Text Out device,
1032 // their MaxMode and QueryData should be the intersection of both.
1034 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1035 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1037 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
1039 // Match the UGA mode data of ConOut with the current mode
1041 if (UgaDraw
!= NULL
) {
1044 &mConOut
.UgaHorizontalResolution
,
1045 &mConOut
.UgaVerticalResolution
,
1046 &mConOut
.UgaColorDepth
,
1047 &mConOut
.UgaRefreshRate
1056 ConSplitterStdErrDriverBindingStart (
1057 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1058 IN EFI_HANDLE ControllerHandle
,
1059 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1063 Routine Description:
1064 Start ConSplitter on ControllerHandle, and create the virtual
1065 agrogated console device on first call Start for a SimpleTextIn handle.
1068 This - Pointer to protocol.
1069 ControllerHandle - Controller handle.
1070 RemainingDevicePath - Remaining device path.
1073 EFI_ERROR if a SimpleTextIn protocol is not started.
1078 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1080 Status
= ConSplitterStart (
1083 mStdErr
.VirtualHandle
,
1084 &gEfiStandardErrorDeviceGuid
,
1085 &gEfiSimpleTextOutProtocolGuid
,
1088 if (EFI_ERROR (Status
)) {
1092 // If both ConOut and StdErr incorporate the same Text Out device,
1093 // their MaxMode and QueryData should be the intersection of both.
1095 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1096 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1097 if (EFI_ERROR (Status
)) {
1101 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1102 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1103 gST
->StdErr
= &mStdErr
.TextOut
;
1105 // Update the CRC32 in the EFI System Table header
1108 gBS
->CalculateCrc32 (
1109 (UINT8
*) &gST
->Hdr
,
1110 gST
->Hdr
.HeaderSize
,
1122 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1123 IN EFI_HANDLE ControllerHandle
,
1124 IN EFI_HANDLE ConSplitterVirtualHandle
,
1125 IN EFI_GUID
*DeviceGuid
,
1126 IN EFI_GUID
*InterfaceGuid
,
1131 Routine Description:
1134 (Standard DriverBinding Protocol Stop() function)
1144 Status
= gBS
->OpenProtocol (
1148 This
->DriverBindingHandle
,
1150 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1152 if (EFI_ERROR (Status
)) {
1156 // close the protocol refered.
1158 gBS
->CloseProtocol (
1161 This
->DriverBindingHandle
,
1162 ConSplitterVirtualHandle
1164 gBS
->CloseProtocol (
1167 This
->DriverBindingHandle
,
1176 ConSplitterConInDriverBindingStop (
1177 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1178 IN EFI_HANDLE ControllerHandle
,
1179 IN UINTN NumberOfChildren
,
1180 IN EFI_HANDLE
*ChildHandleBuffer
1184 Routine Description:
1187 (Standard DriverBinding Protocol Stop() function)
1196 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1198 if (NumberOfChildren
== 0) {
1202 Status
= ConSplitterStop (
1205 mConIn
.VirtualHandle
,
1206 &gEfiConsoleInDeviceGuid
,
1207 &gEfiSimpleTextInProtocolGuid
,
1210 if (EFI_ERROR (Status
)) {
1214 // Delete this console input device's data structures.
1216 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1221 ConSplitterSimplePointerDriverBindingStop (
1222 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1223 IN EFI_HANDLE ControllerHandle
,
1224 IN UINTN NumberOfChildren
,
1225 IN EFI_HANDLE
*ChildHandleBuffer
1229 Routine Description:
1232 (Standard DriverBinding Protocol Stop() function)
1241 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1243 if (NumberOfChildren
== 0) {
1247 Status
= ConSplitterStop (
1250 mConIn
.VirtualHandle
,
1251 &gEfiSimplePointerProtocolGuid
,
1252 &gEfiSimplePointerProtocolGuid
,
1253 (VOID
**) &SimplePointer
1255 if (EFI_ERROR (Status
)) {
1259 // Delete this console input device's data structures.
1261 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1266 ConSplitterConOutDriverBindingStop (
1267 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1268 IN EFI_HANDLE ControllerHandle
,
1269 IN UINTN NumberOfChildren
,
1270 IN EFI_HANDLE
*ChildHandleBuffer
1274 Routine Description:
1277 (Standard DriverBinding Protocol Stop() function)
1286 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1288 if (NumberOfChildren
== 0) {
1292 Status
= ConSplitterStop (
1295 mConOut
.VirtualHandle
,
1296 &gEfiConsoleOutDeviceGuid
,
1297 &gEfiSimpleTextOutProtocolGuid
,
1300 if (EFI_ERROR (Status
)) {
1305 // Delete this console output device's data structures.
1307 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1312 ConSplitterStdErrDriverBindingStop (
1313 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1314 IN EFI_HANDLE ControllerHandle
,
1315 IN UINTN NumberOfChildren
,
1316 IN EFI_HANDLE
*ChildHandleBuffer
1320 Routine Description:
1323 (Standard DriverBinding Protocol Stop() function)
1327 EFI_SUCCESS - Complete successfully.
1332 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1334 if (NumberOfChildren
== 0) {
1338 Status
= ConSplitterStop (
1341 mStdErr
.VirtualHandle
,
1342 &gEfiStandardErrorDeviceGuid
,
1343 &gEfiSimpleTextOutProtocolGuid
,
1346 if (EFI_ERROR (Status
)) {
1350 // Delete this console error out device's data structures.
1352 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1353 if (EFI_ERROR (Status
)) {
1357 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1358 gST
->StandardErrorHandle
= NULL
;
1361 // Update the CRC32 in the EFI System Table header
1364 gBS
->CalculateCrc32 (
1365 (UINT8
*) &gST
->Hdr
,
1366 gST
->Hdr
.HeaderSize
,
1375 ConSplitterGrowBuffer (
1376 IN UINTN SizeOfCount
,
1378 IN OUT VOID
**Buffer
1382 Routine Description:
1383 Take the passed in Buffer of size SizeOfCount and grow the buffer
1384 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1385 bytes. Copy the current data in Buffer to the new version of Buffer
1386 and free the old version of buffer.
1390 SizeOfCount - Size of element in array
1391 Count - Current number of elements in array
1392 Buffer - Bigger version of passed in Buffer with all the data
1395 EFI_SUCCESS - Buffer size has grown
1396 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1407 // grow the buffer to new buffer size,
1408 // copy the old buffer's content to the new-size buffer,
1409 // then free the old buffer.
1411 OldSize
= *Count
* SizeOfCount
;
1412 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1413 NewSize
= *Count
* SizeOfCount
;
1415 Ptr
= AllocateZeroPool (NewSize
);
1417 return EFI_OUT_OF_RESOURCES
;
1420 CopyMem (Ptr
, *Buffer
, OldSize
);
1422 if (*Buffer
!= NULL
) {
1432 ConSplitterTextInAddDevice (
1433 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1434 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1438 Routine Description:
1445 EFI_OUT_OF_RESOURCES
1452 // If the Text In List is full, enlarge it by calling growbuffer().
1454 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1455 Status
= ConSplitterGrowBuffer (
1456 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1457 &Private
->TextInListCount
,
1458 (VOID
**) &Private
->TextInList
1460 if (EFI_ERROR (Status
)) {
1461 return EFI_OUT_OF_RESOURCES
;
1465 // Add the new text-in device data structure into the Text In List.
1467 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1468 Private
->CurrentNumberOfConsoles
++;
1471 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1473 gBS
->CheckEvent (TextIn
->WaitForKey
);
1479 ConSplitterTextInDeleteDevice (
1480 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1481 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1485 Routine Description:
1498 // Remove the specified text-in device data structure from the Text In List,
1499 // and rearrange the remaining data structures in the Text In List.
1501 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1502 if (Private
->TextInList
[Index
] == TextIn
) {
1503 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1504 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1507 Private
->CurrentNumberOfConsoles
--;
1512 return EFI_NOT_FOUND
;
1516 ConSplitterSimplePointerAddDevice (
1517 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1518 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1522 Routine Description:
1528 EFI_OUT_OF_RESOURCES
1536 // If the Text In List is full, enlarge it by calling growbuffer().
1538 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1539 Status
= ConSplitterGrowBuffer (
1540 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1541 &Private
->PointerListCount
,
1542 (VOID
**) &Private
->PointerList
1544 if (EFI_ERROR (Status
)) {
1545 return EFI_OUT_OF_RESOURCES
;
1549 // Add the new text-in device data structure into the Text In List.
1551 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1552 Private
->CurrentNumberOfPointers
++;
1557 ConSplitterSimplePointerDeleteDevice (
1558 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1559 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1563 Routine Description:
1575 // Remove the specified text-in device data structure from the Text In List,
1576 // and rearrange the remaining data structures in the Text In List.
1578 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1579 if (Private
->PointerList
[Index
] == SimplePointer
) {
1580 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1581 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1584 Private
->CurrentNumberOfPointers
--;
1589 return EFI_NOT_FOUND
;
1594 ConSplitterGrowMapTable (
1595 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1599 Routine Description:
1612 INT32
*TextOutModeMap
;
1613 INT32
*OldTextOutModeMap
;
1617 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1618 OldTextOutModeMap
= Private
->TextOutModeMap
;
1619 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1621 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1622 if (TextOutModeMap
== NULL
) {
1623 return EFI_OUT_OF_RESOURCES
;
1626 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1627 Private
->TextOutModeMap
= TextOutModeMap
;
1630 // If TextOutList has been enlarged, need to realloc the mode map table
1631 // The mode map table is regarded as a two dimension array.
1634 // 0 ---------> TextOutListCount ----> TextOutListCount
1635 // | -------------------------------------------
1642 // -------------------------------------------
1645 if (OldTextOutModeMap
!= NULL
) {
1647 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1649 SrcAddress
= OldTextOutModeMap
;
1652 // Copy the old data to the new one
1654 while (Index
< Private
->TextOutMode
.MaxMode
) {
1655 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1656 TextOutModeMap
+= NewSize
;
1661 // Free the old buffer
1663 FreePool (OldTextOutModeMap
);
1671 ConSplitterAddOutputMode (
1672 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1673 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1677 Routine Description:
1692 MaxMode
= TextOut
->Mode
->MaxMode
;
1693 Private
->TextOutMode
.MaxMode
= MaxMode
;
1696 // Grow the buffer if query data buffer is not large enough to
1697 // hold all the mode supported by the first console.
1699 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1700 Status
= ConSplitterGrowBuffer (
1701 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1702 &Private
->TextOutQueryDataCount
,
1703 (VOID
**) &Private
->TextOutQueryData
1705 if (EFI_ERROR (Status
)) {
1706 return EFI_OUT_OF_RESOURCES
;
1710 // Allocate buffer for the output mode map
1712 Status
= ConSplitterGrowMapTable (Private
);
1713 if (EFI_ERROR (Status
)) {
1714 return EFI_OUT_OF_RESOURCES
;
1717 // As the first textout device, directly add the mode in to QueryData
1718 // and at the same time record the mapping between QueryData and TextOut.
1722 while (Mode
< MaxMode
) {
1723 TextOut
->QueryMode (
1726 &Private
->TextOutQueryData
[Mode
].Columns
,
1727 &Private
->TextOutQueryData
[Mode
].Rows
1729 Private
->TextOutModeMap
[Index
] = Mode
;
1731 Index
+= Private
->TextOutListCount
;
1739 ConSplitterGetIntersection (
1740 IN INT32
*TextOutModeMap
,
1741 IN INT32
*NewlyAddedMap
,
1742 IN UINTN MapStepSize
,
1743 IN UINTN NewMapStepSize
,
1745 OUT INT32
*CurrentMode
1749 INT32
*CurrentMapEntry
;
1750 INT32
*NextMapEntry
;
1751 INT32 CurrentMaxMode
;
1755 CurrentMapEntry
= TextOutModeMap
;
1756 NextMapEntry
= TextOutModeMap
;
1757 CurrentMaxMode
= *MaxMode
;
1758 Mode
= *CurrentMode
;
1760 while (Index
< CurrentMaxMode
) {
1761 if (*NewlyAddedMap
== -1) {
1763 // This mode is not supported any more. Remove it. Special care
1764 // must be taken as this remove will also affect current mode;
1766 if (Index
== *CurrentMode
) {
1768 } else if (Index
< *CurrentMode
) {
1773 if (CurrentMapEntry
!= NextMapEntry
) {
1774 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1777 NextMapEntry
+= MapStepSize
;
1780 CurrentMapEntry
+= MapStepSize
;
1781 NewlyAddedMap
+= NewMapStepSize
;
1785 *CurrentMode
= Mode
;
1792 ConSplitterSyncOutputMode (
1793 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1794 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1798 Routine Description:
1801 Private - Private data structure.
1802 TextOut - Text Out Protocol.
1809 INT32 CurrentMaxMode
;
1812 INT32
*TextOutModeMap
;
1814 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1820 // Must make sure that current mode won't change even if mode number changes
1822 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1823 TextOutModeMap
= Private
->TextOutModeMap
;
1824 StepSize
= Private
->TextOutListCount
;
1825 TextOutQueryData
= Private
->TextOutQueryData
;
1828 // Query all the mode that the newly added TextOut supports
1831 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1832 while (Mode
< TextOut
->Mode
->MaxMode
) {
1833 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1836 // Search the QueryData database to see if they intersects
1839 while (Index
< CurrentMaxMode
) {
1840 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1841 MapTable
[Index
* StepSize
] = Mode
;
1851 // Now search the TextOutModeMap table to find the intersection of supported
1852 // mode between ConSplitter and the newly added device.
1854 ConSplitterGetIntersection (
1859 &Private
->TextOutMode
.MaxMode
,
1860 &Private
->TextOutMode
.Mode
1868 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1873 Routine Description:
1880 EFI_OUT_OF_RESOURCES
1884 UINTN ConOutNumOfConsoles
;
1885 UINTN StdErrNumOfConsoles
;
1886 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
1887 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
1892 INT32 ConOutMaxMode
;
1893 INT32 StdErrMaxMode
;
1896 INT32
*ConOutModeMap
;
1897 INT32
*StdErrModeMap
;
1898 INT32
*ConOutMapTable
;
1899 INT32
*StdErrMapTable
;
1900 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
1901 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
1902 BOOLEAN FoundTheSameTextOut
;
1903 UINTN ConOutMapTableSize
;
1904 UINTN StdErrMapTableSize
;
1906 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1907 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1908 ConOutTextOutList
= mConOut
.TextOutList
;
1909 StdErrTextOutList
= mStdErr
.TextOutList
;
1912 FoundTheSameTextOut
= FALSE
;
1913 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1915 while (Indexj
< StdErrNumOfConsoles
) {
1916 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1917 FoundTheSameTextOut
= TRUE
;
1922 StdErrTextOutList
++;
1926 ConOutTextOutList
++;
1929 if (!FoundTheSameTextOut
) {
1933 // Must make sure that current mode won't change even if mode number changes
1935 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1936 ConOutModeMap
= mConOut
.TextOutModeMap
;
1937 ConOutQueryData
= mConOut
.TextOutQueryData
;
1939 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1940 StdErrModeMap
= mStdErr
.TextOutModeMap
;
1941 StdErrQueryData
= mStdErr
.TextOutQueryData
;
1944 // Allocate the map table and set the map table's index to -1.
1946 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
1947 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
1948 if (ConOutMapTable
== NULL
) {
1949 return EFI_OUT_OF_RESOURCES
;
1952 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
1954 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
1955 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
1956 if (StdErrMapTable
== NULL
) {
1957 return EFI_OUT_OF_RESOURCES
;
1960 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
1963 // Find the intersection of the two set of modes. If they actually intersect, the
1964 // correponding entry in the map table is set to 1.
1967 while (Mode
< ConOutMaxMode
) {
1969 // Search the other's QueryData database to see if they intersect
1972 Rows
= ConOutQueryData
[Mode
].Rows
;
1973 Columns
= ConOutQueryData
[Mode
].Columns
;
1974 while (Index
< StdErrMaxMode
) {
1975 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
1976 ConOutMapTable
[Mode
] = 1;
1977 StdErrMapTable
[Index
] = 1;
1987 // Now search the TextOutModeMap table to find the intersection of supported
1988 // mode between ConSplitter and the newly added device.
1990 ConSplitterGetIntersection (
1993 mConOut
.TextOutListCount
,
1995 &(mConOut
.TextOutMode
.MaxMode
),
1996 &(mConOut
.TextOutMode
.Mode
)
1998 if (mConOut
.TextOutMode
.Mode
< 0) {
1999 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2002 ConSplitterGetIntersection (
2005 mStdErr
.TextOutListCount
,
2007 &(mStdErr
.TextOutMode
.MaxMode
),
2008 &(mStdErr
.TextOutMode
.Mode
)
2010 if (mStdErr
.TextOutMode
.Mode
< 0) {
2011 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2014 FreePool (ConOutMapTable
);
2015 FreePool (StdErrMapTable
);
2022 ConSplitterAddGraphicsOutputMode (
2023 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2024 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2025 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2029 Routine Description:
2041 TEXT_OUT_GOP_MODE
*Mode
;
2043 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2044 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2045 TEXT_OUT_GOP_MODE
*ModeBuffer
;
2046 TEXT_OUT_GOP_MODE
*MatchedMode
;
2050 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2051 return EFI_UNSUPPORTED
;
2054 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2056 if (GraphicsOutput
!= NULL
) {
2057 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2059 // This is the first Graphics Output device added
2061 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2062 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2063 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2064 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2065 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2066 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2069 // Allocate resource for the private mode buffer
2071 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
2072 if (ModeBuffer
== NULL
) {
2073 return EFI_OUT_OF_RESOURCES
;
2075 FreePool (Private
->GraphicsOutputModeBuffer
);
2076 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2079 // Store all supported display modes to the private mode buffer
2082 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2083 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2084 if (EFI_ERROR (Status
)) {
2087 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2088 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2094 // Check intersection of display mode
2096 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2097 if (ModeBuffer
== NULL
) {
2098 return EFI_OUT_OF_RESOURCES
;
2101 MatchedMode
= ModeBuffer
;
2102 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2103 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2106 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2107 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2108 if (EFI_ERROR (Status
)) {
2111 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2112 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2121 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2129 // Drop the old mode buffer, assign it to a new one
2131 FreePool (Private
->GraphicsOutputModeBuffer
);
2132 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2135 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2137 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2138 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2139 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2140 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2141 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2142 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2146 // Select a prefered Display mode 800x600
2148 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2149 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2150 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2155 // Prefered mode is not found, set to mode 0
2157 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2162 // Current mode number may need update now, so set it to an invalide mode number
2164 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2167 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2168 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2170 CurrentGraphicsOutputMode
->MaxMode
= 1;
2171 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2172 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2173 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2174 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2175 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2176 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2177 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2178 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2181 // Update the private mode buffer
2183 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2184 ModeBuffer
->HorizontalResolution
= 800;
2185 ModeBuffer
->VerticalResolution
= 600;
2188 // Current mode is unknow now, set it to an invalid mode number 0xffff
2190 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2195 // Force GraphicsOutput mode to be set,
2196 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2198 Private
->HardwareNeedsStarting
= TRUE
;
2199 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2201 Private
->CurrentNumberOfGraphicsOutput
++;
2207 ConSplitterTextOutAddDevice (
2208 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2209 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2210 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2211 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2215 Routine Description:
2226 UINTN CurrentNumOfConsoles
;
2229 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2231 Status
= EFI_SUCCESS
;
2232 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2235 // If the Text Out List is full, enlarge it by calling growbuffer().
2237 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2238 Status
= ConSplitterGrowBuffer (
2239 sizeof (TEXT_OUT_AND_GOP_DATA
),
2240 &Private
->TextOutListCount
,
2241 (VOID
**) &Private
->TextOutList
2243 if (EFI_ERROR (Status
)) {
2244 return EFI_OUT_OF_RESOURCES
;
2247 // Also need to reallocate the TextOutModeMap table
2249 Status
= ConSplitterGrowMapTable (Private
);
2250 if (EFI_ERROR (Status
)) {
2251 return EFI_OUT_OF_RESOURCES
;
2255 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2257 TextAndGop
->TextOut
= TextOut
;
2258 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2259 TextAndGop
->UgaDraw
= UgaDraw
;
2261 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2263 // If No UGA device then use the ConOut device
2265 TextAndGop
->TextOutEnabled
= TRUE
;
2268 // If UGA device use ConOut device only used if UGA screen is in Text mode
2270 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2273 if (CurrentNumOfConsoles
== 0) {
2275 // Add the first device's output mode to console splitter's mode list
2277 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2279 ConSplitterSyncOutputMode (Private
, TextOut
);
2282 Private
->CurrentNumberOfConsoles
++;
2285 // Scan both TextOutList, for the intersection TextOut device
2286 // maybe both ConOut and StdErr incorporate the same Text Out
2287 // device in them, thus the output of both should be synced.
2289 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2291 CurrentMode
= Private
->TextOutMode
.Mode
;
2292 MaxMode
= Private
->TextOutMode
.MaxMode
;
2293 ASSERT (MaxMode
>= 1);
2295 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2296 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2297 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2301 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2303 // We just added a new UGA device in graphics mode
2305 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2306 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2307 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2308 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2310 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2312 // The new console supports the same mode of the current console so sync up
2314 DevNullSyncGopStdOut (Private
);
2317 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2319 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2326 ConSplitterTextOutDeleteDevice (
2327 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2328 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2332 Routine Description:
2343 UINTN CurrentNumOfConsoles
;
2344 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2348 // Remove the specified text-out device data structure from the Text out List,
2349 // and rearrange the remaining data structures in the Text out List.
2351 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2352 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2353 TextOutList
= Private
->TextOutList
;
2354 while (Index
>= 0) {
2355 if (TextOutList
->TextOut
== TextOut
) {
2356 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2357 CurrentNumOfConsoles
--;
2365 // The specified TextOut is not managed by the ConSplitter driver
2368 return EFI_NOT_FOUND
;
2371 if (CurrentNumOfConsoles
== 0) {
2373 // If the number of consoles is zero clear the Dev NULL device
2375 Private
->CurrentNumberOfConsoles
= 0;
2376 Private
->TextOutMode
.MaxMode
= 1;
2377 Private
->TextOutQueryData
[0].Columns
= 80;
2378 Private
->TextOutQueryData
[0].Rows
= 25;
2379 DevNullTextOutSetMode (Private
, 0);
2384 // Max Mode is realy an intersection of the QueryMode command to all
2385 // devices. So we must copy the QueryMode of the first device to
2389 Private
->TextOutQueryData
,
2390 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2393 FreePool (Private
->TextOutModeMap
);
2394 Private
->TextOutModeMap
= NULL
;
2395 TextOutList
= Private
->TextOutList
;
2398 // Add the first TextOut to the QueryData array and ModeMap table
2400 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2403 // Now add one by one
2406 Private
->CurrentNumberOfConsoles
= 1;
2408 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2409 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2411 Private
->CurrentNumberOfConsoles
++;
2415 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2420 // ConSplitter TextIn member functions
2424 ConSplitterTextInReset (
2425 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2426 IN BOOLEAN ExtendedVerification
2430 Routine Description:
2431 Reset the input device and optionaly run diagnostics
2434 This - Protocol instance pointer.
2435 ExtendedVerification - Driver may perform diagnostics on reset.
2438 EFI_SUCCESS - The device was reset.
2439 EFI_DEVICE_ERROR - The device is not functioning properly and could
2445 EFI_STATUS ReturnStatus
;
2446 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2449 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2451 Private
->KeyEventSignalState
= FALSE
;
2454 // return the worst status met
2456 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2457 Status
= Private
->TextInList
[Index
]->Reset (
2458 Private
->TextInList
[Index
],
2459 ExtendedVerification
2461 if (EFI_ERROR (Status
)) {
2462 ReturnStatus
= Status
;
2466 return ReturnStatus
;
2471 ConSplitterTextInPrivateReadKeyStroke (
2472 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2473 OUT EFI_INPUT_KEY
*Key
2477 Routine Description:
2478 Reads the next keystroke from the input device. The WaitForKey Event can
2479 be used to test for existance of a keystroke via WaitForEvent () call.
2482 This - Protocol instance pointer.
2483 Key - Driver may perform diagnostics on reset.
2486 EFI_SUCCESS - The keystroke information was returned.
2487 EFI_NOT_READY - There was no keystroke data availiable.
2488 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2495 EFI_INPUT_KEY CurrentKey
;
2497 Key
->UnicodeChar
= 0;
2498 Key
->ScanCode
= SCAN_NULL
;
2501 // if no physical console input device exists, return EFI_NOT_READY;
2502 // if any physical console input device has key input,
2503 // return the key and EFI_SUCCESS.
2505 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2506 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2507 Private
->TextInList
[Index
],
2510 if (!EFI_ERROR (Status
)) {
2516 return EFI_NOT_READY
;
2520 ConSpliterConssoleControlStdInLocked (
2525 Routine Description:
2526 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2527 the only device locked.
2534 FALSE - StdIn working normally
2538 return mConIn
.PasswordEnabled
;
2543 ConSpliterConsoleControlLockStdInEvent (
2549 Routine Description:
2550 This timer event will fire when StdIn is locked. It will check the key
2551 sequence on StdIn to see if it matches the password. Any error in the
2552 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2553 TRUE the StdIn splitter will not report any input.
2556 (Standard EFI_EVENT_NOTIFY)
2565 CHAR16 BackSpaceString
[2];
2566 CHAR16 SpaceString
[2];
2569 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2570 if (!EFI_ERROR (Status
)) {
2572 // if it's an ENTER, match password
2574 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2575 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2576 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2578 // Password not match
2580 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2581 mConIn
.PwdIndex
= 0;
2584 // Key matches password sequence
2586 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2587 mConIn
.PasswordEnabled
= FALSE
;
2588 Status
= EFI_NOT_READY
;
2590 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2594 if (mConIn
.PwdIndex
> 0) {
2595 BackSpaceString
[0] = CHAR_BACKSPACE
;
2596 BackSpaceString
[1] = 0;
2598 SpaceString
[0] = ' ';
2601 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2602 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2603 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2607 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2609 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2611 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2612 if (mConIn
.PwdIndex
== 0) {
2613 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2616 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2617 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2622 } while (!EFI_ERROR (Status
));
2627 ConSpliterConsoleControlLockStdIn (
2628 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2633 Routine Description:
2634 If Password is NULL unlock the password state variable and set the event
2635 timer. If the Password is too big return an error. If the Password is valid
2636 Copy the Password and enable state variable and then arm the periodic timer
2641 EFI_SUCCESS - Lock the StdIn device
2642 EFI_INVALID_PARAMETER - Password is NULL
2643 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2647 if (Password
== NULL
) {
2648 return EFI_INVALID_PARAMETER
;
2651 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2653 // Currently have a max password size
2655 return EFI_OUT_OF_RESOURCES
;
2658 // Save the password, initialize state variables and arm event timer
2660 StrCpy (mConIn
.Password
, Password
);
2661 mConIn
.PasswordEnabled
= TRUE
;
2662 mConIn
.PwdIndex
= 0;
2663 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2670 ConSplitterTextInReadKeyStroke (
2671 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2672 OUT EFI_INPUT_KEY
*Key
2676 Routine Description:
2677 Reads the next keystroke from the input device. The WaitForKey Event can
2678 be used to test for existance of a keystroke via WaitForEvent () call.
2679 If the ConIn is password locked make it look like no keystroke is availible
2682 This - Protocol instance pointer.
2683 Key - Driver may perform diagnostics on reset.
2686 EFI_SUCCESS - The keystroke information was returned.
2687 EFI_NOT_READY - There was no keystroke data availiable.
2688 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2693 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2695 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2696 if (Private
->PasswordEnabled
) {
2698 // If StdIn Locked return not ready
2700 return EFI_NOT_READY
;
2703 Private
->KeyEventSignalState
= FALSE
;
2705 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2710 ConSplitterTextInWaitForKey (
2716 Routine Description:
2717 This event agregates all the events of the ConIn devices in the spliter.
2718 If the ConIn is password locked then return.
2719 If any events of physical ConIn devices are signaled, signal the ConIn
2720 spliter event. This will cause the calling code to call
2721 ConSplitterTextInReadKeyStroke ().
2724 Event - The Event assoicated with callback.
2725 Context - Context registered when Event was created.
2733 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2736 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2737 if (Private
->PasswordEnabled
) {
2739 // If StdIn Locked return not ready
2745 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2747 if (Private
->KeyEventSignalState
) {
2748 gBS
->SignalEvent (Event
);
2752 // if any physical console input device has key input, signal the event.
2754 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2755 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2756 if (!EFI_ERROR (Status
)) {
2757 gBS
->SignalEvent (Event
);
2758 Private
->KeyEventSignalState
= TRUE
;
2765 ConSplitterSimplePointerReset (
2766 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2767 IN BOOLEAN ExtendedVerification
2771 Routine Description:
2772 Reset the input device and optionaly run diagnostics
2775 This - Protocol instance pointer.
2776 ExtendedVerification - Driver may perform diagnostics on reset.
2779 EFI_SUCCESS - The device was reset.
2780 EFI_DEVICE_ERROR - The device is not functioning properly and could
2786 EFI_STATUS ReturnStatus
;
2787 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2790 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2792 Private
->InputEventSignalState
= FALSE
;
2794 if (Private
->CurrentNumberOfPointers
== 0) {
2798 // return the worst status met
2800 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2801 Status
= Private
->PointerList
[Index
]->Reset (
2802 Private
->PointerList
[Index
],
2803 ExtendedVerification
2805 if (EFI_ERROR (Status
)) {
2806 ReturnStatus
= Status
;
2810 return ReturnStatus
;
2816 ConSplitterSimplePointerPrivateGetState (
2817 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2818 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2822 Routine Description:
2823 Reads the next keystroke from the input device. The WaitForKey Event can
2824 be used to test for existance of a keystroke via WaitForEvent () call.
2827 This - Protocol instance pointer.
2831 EFI_SUCCESS - The keystroke information was returned.
2832 EFI_NOT_READY - There was no keystroke data availiable.
2833 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2839 EFI_STATUS ReturnStatus
;
2841 EFI_SIMPLE_POINTER_STATE CurrentState
;
2843 State
->RelativeMovementX
= 0;
2844 State
->RelativeMovementY
= 0;
2845 State
->RelativeMovementZ
= 0;
2846 State
->LeftButton
= FALSE
;
2847 State
->RightButton
= FALSE
;
2850 // if no physical console input device exists, return EFI_NOT_READY;
2851 // if any physical console input device has key input,
2852 // return the key and EFI_SUCCESS.
2854 ReturnStatus
= EFI_NOT_READY
;
2855 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2857 Status
= Private
->PointerList
[Index
]->GetState (
2858 Private
->PointerList
[Index
],
2861 if (!EFI_ERROR (Status
)) {
2862 if (ReturnStatus
== EFI_NOT_READY
) {
2863 ReturnStatus
= EFI_SUCCESS
;
2866 if (CurrentState
.LeftButton
) {
2867 State
->LeftButton
= TRUE
;
2870 if (CurrentState
.RightButton
) {
2871 State
->RightButton
= TRUE
;
2874 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
2875 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
2878 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
2879 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
2882 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
2883 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
2885 } else if (Status
== EFI_DEVICE_ERROR
) {
2886 ReturnStatus
= EFI_DEVICE_ERROR
;
2890 return ReturnStatus
;
2895 ConSplitterSimplePointerGetState (
2896 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2897 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2901 Routine Description:
2902 Reads the next keystroke from the input device. The WaitForKey Event can
2903 be used to test for existance of a keystroke via WaitForEvent () call.
2904 If the ConIn is password locked make it look like no keystroke is availible
2907 This - Protocol instance pointer.
2911 EFI_SUCCESS - The keystroke information was returned.
2912 EFI_NOT_READY - There was no keystroke data availiable.
2913 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2918 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2920 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2921 if (Private
->PasswordEnabled
) {
2923 // If StdIn Locked return not ready
2925 return EFI_NOT_READY
;
2928 Private
->InputEventSignalState
= FALSE
;
2930 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2935 ConSplitterSimplePointerWaitForInput (
2941 Routine Description:
2942 This event agregates all the events of the ConIn devices in the spliter.
2943 If the ConIn is password locked then return.
2944 If any events of physical ConIn devices are signaled, signal the ConIn
2945 spliter event. This will cause the calling code to call
2946 ConSplitterTextInReadKeyStroke ().
2949 Event - The Event assoicated with callback.
2950 Context - Context registered when Event was created.
2958 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2961 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2962 if (Private
->PasswordEnabled
) {
2964 // If StdIn Locked return not ready
2970 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2972 if (Private
->InputEventSignalState
) {
2973 gBS
->SignalEvent (Event
);
2977 // if any physical console input device has key input, signal the event.
2979 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2980 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
2981 if (!EFI_ERROR (Status
)) {
2982 gBS
->SignalEvent (Event
);
2983 Private
->InputEventSignalState
= TRUE
;
2990 ConSplitterTextOutReset (
2991 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2992 IN BOOLEAN ExtendedVerification
2996 Routine Description:
2997 Reset the text output device hardware and optionaly run diagnostics
3000 This - Protocol instance pointer.
3001 ExtendedVerification - Driver may perform more exhaustive verfication
3002 operation of the device during reset.
3005 EFI_SUCCESS - The text output device was reset.
3006 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
3012 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3014 EFI_STATUS ReturnStatus
;
3016 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3019 // return the worst status met
3021 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3023 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3025 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
3026 Private
->TextOutList
[Index
].TextOut
,
3027 ExtendedVerification
3029 if (EFI_ERROR (Status
)) {
3030 ReturnStatus
= Status
;
3035 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
3037 Status
= DevNullTextOutSetMode (Private
, 0);
3038 if (EFI_ERROR (Status
)) {
3039 ReturnStatus
= Status
;
3042 return ReturnStatus
;
3047 ConSplitterTextOutOutputString (
3048 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3053 Routine Description:
3054 Write a Unicode string to the output device.
3057 This - Protocol instance pointer.
3058 String - The NULL-terminated Unicode string to be displayed on the output
3059 device(s). All output devices must also support the Unicode
3060 drawing defined in this file.
3063 EFI_SUCCESS - The string was output to the device.
3064 EFI_DEVICE_ERROR - The device reported an error while attempting to output
3066 EFI_UNSUPPORTED - The output device's mode is not currently in a
3068 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
3069 characters in the Unicode string could not be
3070 rendered and were skipped.
3075 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3077 UINTN BackSpaceCount
;
3078 EFI_STATUS ReturnStatus
;
3079 CHAR16
*TargetString
;
3081 This
->SetAttribute (This
, This
->Mode
->Attribute
);
3083 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3086 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3087 if (*TargetString
== CHAR_BACKSPACE
) {
3093 if (BackSpaceCount
== 0) {
3094 TargetString
= WString
;
3096 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3097 StrCpy (TargetString
, WString
);
3100 // return the worst status met
3102 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3103 if (EFI_ERROR (Status
)) {
3104 ReturnStatus
= Status
;
3107 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3109 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3110 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3111 Private
->TextOutList
[Index
].TextOut
,
3114 if (EFI_ERROR (Status
)) {
3115 ReturnStatus
= Status
;
3120 if (BackSpaceCount
) {
3121 FreePool (TargetString
);
3124 return ReturnStatus
;
3129 ConSplitterTextOutTestString (
3130 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3135 Routine Description:
3136 Verifies that all characters in a Unicode string can be output to the
3140 This - Protocol instance pointer.
3141 String - The NULL-terminated Unicode string to be examined for the output
3145 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3146 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3147 rendered by one or more of the output devices mapped
3153 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3155 EFI_STATUS ReturnStatus
;
3157 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3160 // return the worst status met
3162 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3163 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3164 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3165 Private
->TextOutList
[Index
].TextOut
,
3168 if (EFI_ERROR (Status
)) {
3169 ReturnStatus
= Status
;
3174 // There is no DevNullTextOutTestString () since a Unicode buffer would
3175 // always return EFI_SUCCESS.
3176 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3178 return ReturnStatus
;
3183 ConSplitterTextOutQueryMode (
3184 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3185 IN UINTN ModeNumber
,
3191 Routine Description:
3192 Returns information for an available text mode that the output device(s)
3196 This - Protocol instance pointer.
3197 ModeNumber - The mode number to return information on.
3198 Columns, Rows - Returns the geometry of the text output device for the
3199 requested ModeNumber.
3202 EFI_SUCCESS - The requested mode information was returned.
3203 EFI_DEVICE_ERROR - The device had an error and could not
3204 complete the request.
3205 EFI_UNSUPPORTED - The mode number was not valid.
3209 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3211 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3214 // Check whether param ModeNumber is valid.
3215 // ModeNumber should be within range 0 ~ MaxMode - 1.
3217 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3218 return EFI_UNSUPPORTED
;
3221 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3222 return EFI_UNSUPPORTED
;
3225 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3226 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3228 if (*Columns
<= 0 && *Rows
<= 0) {
3229 return EFI_UNSUPPORTED
;
3238 ConSplitterTextOutSetMode (
3239 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3244 Routine Description:
3245 Sets the output device(s) to a specified mode.
3248 This - Protocol instance pointer.
3249 ModeNumber - The mode number to set.
3252 EFI_SUCCESS - The requested text mode was set.
3253 EFI_DEVICE_ERROR - The device had an error and
3254 could not complete the request.
3255 EFI_UNSUPPORTED - The mode number was not valid.
3260 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3262 INT32
*TextOutModeMap
;
3263 EFI_STATUS ReturnStatus
;
3265 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3268 // Check whether param ModeNumber is valid.
3269 // ModeNumber should be within range 0 ~ MaxMode - 1.
3271 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3272 return EFI_UNSUPPORTED
;
3275 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3276 return EFI_UNSUPPORTED
;
3279 // If the mode is being set to the curent mode, then just clear the screen and return.
3281 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3282 return ConSplitterTextOutClearScreen (This
);
3285 // return the worst status met
3287 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3288 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3290 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3291 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3292 Private
->TextOutList
[Index
].TextOut
,
3293 TextOutModeMap
[Index
]
3296 // If this console device is based on a UGA device, then sync up the bitmap from
3297 // the UGA splitter and reclear the text portion of the display in the new mode.
3299 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3300 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3303 if (EFI_ERROR (Status
)) {
3304 ReturnStatus
= Status
;
3309 // The DevNull Console will support any possible mode as it allocates memory
3311 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3312 if (EFI_ERROR (Status
)) {
3313 ReturnStatus
= Status
;
3316 return ReturnStatus
;
3321 ConSplitterTextOutSetAttribute (
3322 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3327 Routine Description:
3328 Sets the background and foreground colors for the OutputString () and
3329 ClearScreen () functions.
3332 This - Protocol instance pointer.
3333 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3334 bits 4..6 are the background color. All other bits are undefined
3335 and must be zero. The valid Attributes are defined in this file.
3338 EFI_SUCCESS - The attribute was set.
3339 EFI_DEVICE_ERROR - The device had an error and
3340 could not complete the request.
3341 EFI_UNSUPPORTED - The attribute requested is not defined.
3346 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3348 EFI_STATUS ReturnStatus
;
3350 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3353 // Check whether param Attribute is valid.
3355 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3356 return EFI_UNSUPPORTED
;
3360 // return the worst status met
3362 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3364 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3365 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3366 Private
->TextOutList
[Index
].TextOut
,
3369 if (EFI_ERROR (Status
)) {
3370 ReturnStatus
= Status
;
3375 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3377 return ReturnStatus
;
3382 ConSplitterTextOutClearScreen (
3383 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
3387 Routine Description:
3388 Clears the output device(s) display to the currently selected background
3392 This - Protocol instance pointer.
3395 EFI_SUCCESS - The operation completed successfully.
3396 EFI_DEVICE_ERROR - The device had an error and
3397 could not complete the request.
3398 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3403 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3405 EFI_STATUS ReturnStatus
;
3407 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3410 // return the worst status met
3412 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3414 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3415 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3416 if (EFI_ERROR (Status
)) {
3417 ReturnStatus
= Status
;
3422 Status
= DevNullTextOutClearScreen (Private
);
3423 if (EFI_ERROR (Status
)) {
3424 ReturnStatus
= Status
;
3427 return ReturnStatus
;
3432 ConSplitterTextOutSetCursorPosition (
3433 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3439 Routine Description:
3440 Sets the current coordinates of the cursor position
3443 This - Protocol instance pointer.
3444 Column, Row - the position to set the cursor to. Must be greater than or
3445 equal to zero and less than the number of columns and rows
3449 EFI_SUCCESS - The operation completed successfully.
3450 EFI_DEVICE_ERROR - The device had an error and
3451 could not complete the request.
3452 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
3453 cursor position is invalid for the current mode.
3458 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3460 EFI_STATUS ReturnStatus
;
3463 INT32
*TextOutModeMap
;
3467 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3468 TextOutModeMap
= NULL
;
3469 ModeNumber
= Private
->TextOutMode
.Mode
;
3472 // Get current MaxColumn and MaxRow from intersection map
3474 if (Private
->TextOutModeMap
!= NULL
) {
3475 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3476 CurrentMode
= *TextOutModeMap
;
3478 CurrentMode
= ModeNumber
;
3481 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
3482 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
3484 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3485 return EFI_UNSUPPORTED
;
3488 // return the worst status met
3490 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3492 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3493 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3494 Private
->TextOutList
[Index
].TextOut
,
3498 if (EFI_ERROR (Status
)) {
3499 ReturnStatus
= Status
;
3504 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3506 return ReturnStatus
;
3511 ConSplitterTextOutEnableCursor (
3512 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3517 Routine Description:
3518 Makes the cursor visible or invisible
3521 This - Protocol instance pointer.
3522 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
3523 set to be invisible.
3526 EFI_SUCCESS - The operation completed successfully.
3527 EFI_DEVICE_ERROR - The device had an error and could not complete the
3528 request, or the device does not support changing
3530 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3535 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3537 EFI_STATUS ReturnStatus
;
3539 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3542 // return the worst status met
3544 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3546 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3547 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3548 Private
->TextOutList
[Index
].TextOut
,
3551 if (EFI_ERROR (Status
)) {
3552 ReturnStatus
= Status
;
3557 DevNullTextOutEnableCursor (Private
, Visible
);
3559 return ReturnStatus
;