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
,
47 ConSplitterTextInResetEx
,
48 ConSplitterTextInReadKeyStrokeEx
,
50 ConSplitterTextInSetState
,
51 ConSplitterTextInRegisterKeyNotify
,
52 ConSplitterTextInUnregisterKeyNotify
55 (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
**) NULL
,
58 (struct _LIST_ENTRY
*) NULL
,
59 (struct _LIST_ENTRY
*) NULL
63 ConSplitterSimplePointerReset
,
64 ConSplitterSimplePointerGetState
,
66 (EFI_SIMPLE_POINTER_MODE
*) NULL
76 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
99 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
100 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
103 ConSplitterTextOutReset
,
104 ConSplitterTextOutOutputString
,
105 ConSplitterTextOutTestString
,
106 ConSplitterTextOutQueryMode
,
107 ConSplitterTextOutSetMode
,
108 ConSplitterTextOutSetAttribute
,
109 ConSplitterTextOutClearScreen
,
110 ConSplitterTextOutSetCursorPosition
,
111 ConSplitterTextOutEnableCursor
,
112 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
123 ConSpliterUgaDrawGetMode
,
124 ConSpliterUgaDrawSetMode
,
131 (EFI_UGA_PIXEL
*) NULL
,
133 ConSpliterGraphicsOutputQueryMode
,
134 ConSpliterGraphicsOutputSetMode
,
135 ConSpliterGraphicsOutputBlt
,
138 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
139 (TEXT_OUT_GOP_MODE
*) NULL
,
143 ConSpliterConsoleControlGetMode
,
144 ConSpliterConsoleControlSetMode
,
145 ConSpliterConsoleControlLockStdIn
149 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
151 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
155 EfiConsoleControlScreenText
,
162 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
163 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
166 ConSplitterTextOutReset
,
167 ConSplitterTextOutOutputString
,
168 ConSplitterTextOutTestString
,
169 ConSplitterTextOutQueryMode
,
170 ConSplitterTextOutSetMode
,
171 ConSplitterTextOutSetAttribute
,
172 ConSplitterTextOutClearScreen
,
173 ConSplitterTextOutSetCursorPosition
,
174 ConSplitterTextOutEnableCursor
,
175 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
186 ConSpliterUgaDrawGetMode
,
187 ConSpliterUgaDrawSetMode
,
194 (EFI_UGA_PIXEL
*) NULL
,
196 ConSpliterGraphicsOutputQueryMode
,
197 ConSpliterGraphicsOutputSetMode
,
198 ConSpliterGraphicsOutputBlt
,
201 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
202 (TEXT_OUT_GOP_MODE
*) NULL
,
206 ConSpliterConsoleControlGetMode
,
207 ConSpliterConsoleControlSetMode
,
208 ConSpliterConsoleControlLockStdIn
212 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
214 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
218 EfiConsoleControlScreenText
,
225 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
226 ConSplitterConInDriverBindingSupported
,
227 ConSplitterConInDriverBindingStart
,
228 ConSplitterConInDriverBindingStop
,
234 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
235 ConSplitterSimplePointerDriverBindingSupported
,
236 ConSplitterSimplePointerDriverBindingStart
,
237 ConSplitterSimplePointerDriverBindingStop
,
243 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
244 ConSplitterConOutDriverBindingSupported
,
245 ConSplitterConOutDriverBindingStart
,
246 ConSplitterConOutDriverBindingStop
,
252 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
253 ConSplitterStdErrDriverBindingSupported
,
254 ConSplitterStdErrDriverBindingStart
,
255 ConSplitterStdErrDriverBindingStop
,
262 The user Entry Point for module ConSplitter. The user code starts with this function.
264 @param[in] ImageHandle The firmware allocated handle for the EFI image.
265 @param[in] SystemTable A pointer to the EFI System Table.
267 @retval EFI_SUCCESS The entry point is executed successfully.
268 @retval other Some error occurs when executing this entry point.
273 InitializeConSplitter(
274 IN EFI_HANDLE ImageHandle
,
275 IN EFI_SYSTEM_TABLE
*SystemTable
281 // Install driver model protocol(s).
283 Status
= EfiLibInstallDriverBindingComponentName2 (
286 &gConSplitterConInDriverBinding
,
288 &gConSplitterConInComponentName
,
289 &gConSplitterConInComponentName2
291 ASSERT_EFI_ERROR (Status
);
293 Status
= EfiLibInstallDriverBindingComponentName2 (
296 &gConSplitterSimplePointerDriverBinding
,
298 &gConSplitterSimplePointerComponentName
,
299 &gConSplitterSimplePointerComponentName2
301 ASSERT_EFI_ERROR (Status
);
303 Status
= EfiLibInstallDriverBindingComponentName2 (
306 &gConSplitterConOutDriverBinding
,
308 &gConSplitterConOutComponentName
,
309 &gConSplitterConOutComponentName2
311 ASSERT_EFI_ERROR (Status
);
313 Status
= EfiLibInstallDriverBindingComponentName2 (
316 &gConSplitterStdErrDriverBinding
,
318 &gConSplitterStdErrComponentName
,
319 &gConSplitterStdErrComponentName2
321 ASSERT_EFI_ERROR (Status
);
325 // Call the original Entry Point
327 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
335 ConSplitterDriverEntry (
336 IN EFI_HANDLE ImageHandle
,
337 IN EFI_SYSTEM_TABLE
*SystemTable
342 Intialize a virtual console device to act as an agrigator of physical console
346 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
347 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
355 ASSERT (FeaturePcdGet (PcdConOutGopSupport
) ||
356 FeaturePcdGet (PcdConOutUgaSupport
));
358 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
359 // The virtual handles will always exist even if no console exist in the
360 // system. This is need to support hotplug devices like USB.
363 // Create virtual device handle for StdErr Splitter
365 Status
= ConSplitterTextOutConstructor (&mStdErr
);
366 if (!EFI_ERROR (Status
)) {
367 Status
= gBS
->InstallMultipleProtocolInterfaces (
368 &mStdErr
.VirtualHandle
,
369 &gEfiSimpleTextOutProtocolGuid
,
371 &gEfiPrimaryStandardErrorDeviceGuid
,
377 // Create virtual device handle for ConIn Splitter
379 Status
= ConSplitterTextInConstructor (&mConIn
);
380 if (!EFI_ERROR (Status
)) {
381 Status
= gBS
->InstallMultipleProtocolInterfaces (
382 &mConIn
.VirtualHandle
,
383 &gEfiSimpleTextInProtocolGuid
,
385 &gEfiSimpleTextInputExProtocolGuid
,
387 &gEfiSimplePointerProtocolGuid
,
388 &mConIn
.SimplePointer
,
389 &gEfiPrimaryConsoleInDeviceGuid
,
393 if (!EFI_ERROR (Status
)) {
395 // Update the EFI System Table with new virtual console
397 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
398 gST
->ConIn
= &mConIn
.TextIn
;
402 // Create virtual device handle for ConOut Splitter
404 Status
= ConSplitterTextOutConstructor (&mConOut
);
405 if (!EFI_ERROR (Status
)) {
406 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
408 // In EFI mode, UGA Draw protocol is installed
410 Status
= gBS
->InstallMultipleProtocolInterfaces (
411 &mConOut
.VirtualHandle
,
412 &gEfiSimpleTextOutProtocolGuid
,
414 &gEfiUgaDrawProtocolGuid
,
416 &gEfiConsoleControlProtocolGuid
,
417 &mConOut
.ConsoleControl
,
418 &gEfiPrimaryConsoleOutDeviceGuid
,
422 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
424 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
426 Status
= gBS
->InstallMultipleProtocolInterfaces (
427 &mConOut
.VirtualHandle
,
428 &gEfiSimpleTextOutProtocolGuid
,
430 &gEfiGraphicsOutputProtocolGuid
,
431 &mConOut
.GraphicsOutput
,
432 &gEfiConsoleControlProtocolGuid
,
433 &mConOut
.ConsoleControl
,
434 &gEfiPrimaryConsoleOutDeviceGuid
,
440 // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are
441 // installed on virtual handle.
443 Status
= gBS
->InstallMultipleProtocolInterfaces (
444 &mConOut
.VirtualHandle
,
445 &gEfiSimpleTextOutProtocolGuid
,
447 &gEfiGraphicsOutputProtocolGuid
,
448 &mConOut
.GraphicsOutput
,
449 &gEfiUgaDrawProtocolGuid
,
451 &gEfiConsoleControlProtocolGuid
,
452 &mConOut
.ConsoleControl
,
453 &gEfiPrimaryConsoleOutDeviceGuid
,
459 if (!EFI_ERROR (Status
)) {
461 // Update the EFI System Table with new virtual console
463 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
464 gST
->ConOut
= &mConOut
.TextOut
;
469 // Update the CRC32 in the EFI System Table header
472 gBS
->CalculateCrc32 (
482 ConSplitterTextInConstructor (
483 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
489 Construct the ConSplitter.
493 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
496 EFI_OUT_OF_RESOURCES - Out of resources.
503 // Initilize console input splitter's private data.
505 Status
= ConSplitterGrowBuffer (
506 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
507 &ConInPrivate
->TextInListCount
,
508 (VOID
**) &ConInPrivate
->TextInList
510 if (EFI_ERROR (Status
)) {
511 return EFI_OUT_OF_RESOURCES
;
514 // Create Event to support locking StdIn Device
516 Status
= gBS
->CreateEvent (
517 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
519 ConSpliterConsoleControlLockStdInEvent
,
521 &ConInPrivate
->LockEvent
523 ASSERT_EFI_ERROR (Status
);
525 Status
= gBS
->CreateEvent (
528 ConSplitterTextInWaitForKey
,
530 &ConInPrivate
->TextIn
.WaitForKey
532 ASSERT_EFI_ERROR (Status
);
535 // Buffer for Simple Text Input Ex Protocol
537 Status
= ConSplitterGrowBuffer (
538 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
539 &ConInPrivate
->TextInExListCount
,
540 (VOID
**) &ConInPrivate
->TextInExList
542 if (EFI_ERROR (Status
)) {
543 return EFI_OUT_OF_RESOURCES
;
546 Status
= gBS
->CreateEvent (
549 ConSplitterTextInWaitForKey
,
551 &ConInPrivate
->TextInEx
.WaitForKeyEx
553 ASSERT_EFI_ERROR (Status
);
555 InitializeListHead (&ConInPrivate
->NotifyList
);
558 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
560 Status
= ConSplitterGrowBuffer (
561 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
562 &ConInPrivate
->PointerListCount
,
563 (VOID
**) &ConInPrivate
->PointerList
565 if (EFI_ERROR (Status
)) {
566 return EFI_OUT_OF_RESOURCES
;
569 Status
= gBS
->CreateEvent (
572 ConSplitterSimplePointerWaitForInput
,
574 &ConInPrivate
->SimplePointer
.WaitForInput
581 ConSplitterTextOutConstructor (
582 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
588 // Initilize console output splitter's private data.
590 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
592 Status
= ConSplitterGrowBuffer (
593 sizeof (TEXT_OUT_AND_GOP_DATA
),
594 &ConOutPrivate
->TextOutListCount
,
595 (VOID
**) &ConOutPrivate
->TextOutList
597 if (EFI_ERROR (Status
)) {
598 return EFI_OUT_OF_RESOURCES
;
601 Status
= ConSplitterGrowBuffer (
602 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
603 &ConOutPrivate
->TextOutQueryDataCount
,
604 (VOID
**) &ConOutPrivate
->TextOutQueryData
606 if (EFI_ERROR (Status
)) {
607 return EFI_OUT_OF_RESOURCES
;
610 // Setup the DevNullTextOut console to 80 x 25
612 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
613 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
614 DevNullTextOutSetMode (ConOutPrivate
, 0);
616 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
618 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
620 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
622 if (FeaturePcdGet (PcdConOutGopSupport
)) {
624 // Setup resource for mode information in Graphics Output Protocol interface
626 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
627 return EFI_OUT_OF_RESOURCES
;
629 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
630 return EFI_OUT_OF_RESOURCES
;
633 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
635 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
636 return EFI_OUT_OF_RESOURCES
;
638 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
639 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
642 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
643 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
644 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
646 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
647 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
648 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
649 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
650 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
652 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
654 // Initial current mode to unknow state, and then set to mode 0
656 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
657 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
665 ConSplitterSupported (
666 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
667 IN EFI_HANDLE ControllerHandle
,
673 Generic Supported Check
676 This - Pointer to protocol.
677 ControllerHandle - Controller Handle.
682 EFI_UNSUPPORTED - unsupported.
683 EFI_SUCCESS - operation is OK.
691 // Make sure the Console Splitter does not attempt to attach to itself
693 if (ControllerHandle
== mConIn
.VirtualHandle
) {
694 return EFI_UNSUPPORTED
;
697 if (ControllerHandle
== mConOut
.VirtualHandle
) {
698 return EFI_UNSUPPORTED
;
701 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
702 return EFI_UNSUPPORTED
;
705 // Check to see whether the handle has the ConsoleInDevice GUID on it
707 Status
= gBS
->OpenProtocol (
711 This
->DriverBindingHandle
,
713 EFI_OPEN_PROTOCOL_BY_DRIVER
716 if (EFI_ERROR (Status
)) {
723 This
->DriverBindingHandle
,
732 ConSplitterConInDriverBindingSupported (
733 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
734 IN EFI_HANDLE ControllerHandle
,
735 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
740 Console In Supported Check
743 This - Pointer to protocol.
744 ControllerHandle - Controller handle.
745 RemainingDevicePath - Remaining device path.
753 return ConSplitterSupported (
756 &gEfiConsoleInDeviceGuid
762 ConSplitterSimplePointerDriverBindingSupported (
763 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
764 IN EFI_HANDLE ControllerHandle
,
765 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
770 Standard Error Supported Check
773 This - Pointer to protocol.
774 ControllerHandle - Controller handle.
775 RemainingDevicePath - Remaining device path.
783 return ConSplitterSupported (
786 &gEfiSimplePointerProtocolGuid
792 ConSplitterConOutDriverBindingSupported (
793 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
794 IN EFI_HANDLE ControllerHandle
,
795 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
800 Console Out Supported Check
803 This - Pointer to protocol.
804 ControllerHandle - Controller handle.
805 RemainingDevicePath - Remaining device path.
813 return ConSplitterSupported (
816 &gEfiConsoleOutDeviceGuid
822 ConSplitterStdErrDriverBindingSupported (
823 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
824 IN EFI_HANDLE ControllerHandle
,
825 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
830 Standard Error Supported Check
833 This - Pointer to protocol.
834 ControllerHandle - Controller handle.
835 RemainingDevicePath - Remaining device path.
843 return ConSplitterSupported (
846 &gEfiStandardErrorDeviceGuid
854 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
855 IN EFI_HANDLE ControllerHandle
,
856 IN EFI_HANDLE ConSplitterVirtualHandle
,
857 IN EFI_GUID
*DeviceGuid
,
858 IN EFI_GUID
*InterfaceGuid
,
864 Start ConSplitter on ControllerHandle, and create the virtual
865 agrogated console device on first call Start for a SimpleTextIn handle.
868 (Standard DriverBinding Protocol Start() function)
871 EFI_ERROR if a SimpleTextIn protocol is not started.
879 // Check to see whether the handle has the ConsoleInDevice GUID on it
881 Status
= gBS
->OpenProtocol (
885 This
->DriverBindingHandle
,
887 EFI_OPEN_PROTOCOL_BY_DRIVER
889 if (EFI_ERROR (Status
)) {
893 Status
= gBS
->OpenProtocol (
897 This
->DriverBindingHandle
,
898 ConSplitterVirtualHandle
,
899 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
901 if (EFI_ERROR (Status
)) {
905 return gBS
->OpenProtocol (
909 This
->DriverBindingHandle
,
910 ConSplitterVirtualHandle
,
911 EFI_OPEN_PROTOCOL_GET_PROTOCOL
917 ConSplitterConInDriverBindingStart (
918 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
919 IN EFI_HANDLE ControllerHandle
,
920 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
925 Start ConSplitter on ControllerHandle, and create the virtual
926 agrogated console device on first call Start for a SimpleTextIn handle.
929 This - Pointer to protocol.
930 ControllerHandle - Controller handle.
931 RemainingDevicePath - Remaining device path.
936 EFI_ERROR if a SimpleTextIn protocol is not started.
941 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
942 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
945 // Start ConSplitter on ControllerHandle, and create the virtual
946 // agrogated console device on first call Start for a SimpleTextIn handle.
948 Status
= ConSplitterStart (
951 mConIn
.VirtualHandle
,
952 &gEfiConsoleInDeviceGuid
,
953 &gEfiSimpleTextInProtocolGuid
,
956 if (EFI_ERROR (Status
)) {
960 Status
= gBS
->OpenProtocol (
962 &gEfiSimpleTextInputExProtocolGuid
,
964 This
->DriverBindingHandle
,
965 mConIn
.VirtualHandle
,
966 EFI_OPEN_PROTOCOL_GET_PROTOCOL
968 if (EFI_ERROR (Status
)) {
972 Status
= ConSplitterTextInExAddDevice (&mConIn
, TextInEx
);
973 if (EFI_ERROR (Status
)) {
977 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
982 ConSplitterSimplePointerDriverBindingStart (
983 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
984 IN EFI_HANDLE ControllerHandle
,
985 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
990 Start ConSplitter on ControllerHandle, and create the virtual
991 agrogated console device on first call Start for a SimpleTextIn handle.
994 This - Pointer to protocol.
995 ControllerHandle - Controller handle.
996 RemainingDevicePath - Remaining device path.
1000 EFI_ERROR if a SimpleTextIn protocol is not started.
1005 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1007 Status
= ConSplitterStart (
1010 mConIn
.VirtualHandle
,
1011 &gEfiSimplePointerProtocolGuid
,
1012 &gEfiSimplePointerProtocolGuid
,
1013 (VOID
**) &SimplePointer
1015 if (EFI_ERROR (Status
)) {
1019 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
1024 ConSplitterConOutDriverBindingStart (
1025 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1026 IN EFI_HANDLE ControllerHandle
,
1027 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1031 Routine Description:
1032 Start ConSplitter on ControllerHandle, and create the virtual
1033 agrogated console device on first call Start for a SimpleTextIn handle.
1036 This - Pointer to protocol.
1037 ControllerHandle - Controller handle.
1038 RemainingDevicePath - Remaining device path.
1041 EFI_ERROR if a SimpleTextIn protocol is not started.
1046 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1047 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1048 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1050 Status
= ConSplitterStart (
1053 mConOut
.VirtualHandle
,
1054 &gEfiConsoleOutDeviceGuid
,
1055 &gEfiSimpleTextOutProtocolGuid
,
1058 if (EFI_ERROR (Status
)) {
1062 // Try to Open Graphics Output protocol
1064 Status
= gBS
->OpenProtocol (
1066 &gEfiGraphicsOutputProtocolGuid
,
1067 (VOID
**) &GraphicsOutput
,
1068 This
->DriverBindingHandle
,
1069 mConOut
.VirtualHandle
,
1070 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1072 if (EFI_ERROR (Status
)) {
1073 GraphicsOutput
= NULL
;
1076 // Open UGA_DRAW protocol
1078 Status
= gBS
->OpenProtocol (
1080 &gEfiUgaDrawProtocolGuid
,
1082 This
->DriverBindingHandle
,
1083 mConOut
.VirtualHandle
,
1084 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1086 if (EFI_ERROR (Status
)) {
1090 // If both ConOut and StdErr incorporate the same Text Out device,
1091 // their MaxMode and QueryData should be the intersection of both.
1093 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1094 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1096 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
1098 // Match the UGA mode data of ConOut with the current mode
1100 if (UgaDraw
!= NULL
) {
1103 &mConOut
.UgaHorizontalResolution
,
1104 &mConOut
.UgaVerticalResolution
,
1105 &mConOut
.UgaColorDepth
,
1106 &mConOut
.UgaRefreshRate
1115 ConSplitterStdErrDriverBindingStart (
1116 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1117 IN EFI_HANDLE ControllerHandle
,
1118 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1122 Routine Description:
1123 Start ConSplitter on ControllerHandle, and create the virtual
1124 agrogated console device on first call Start for a SimpleTextIn handle.
1127 This - Pointer to protocol.
1128 ControllerHandle - Controller handle.
1129 RemainingDevicePath - Remaining device path.
1132 EFI_ERROR if a SimpleTextIn protocol is not started.
1137 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1139 Status
= ConSplitterStart (
1142 mStdErr
.VirtualHandle
,
1143 &gEfiStandardErrorDeviceGuid
,
1144 &gEfiSimpleTextOutProtocolGuid
,
1147 if (EFI_ERROR (Status
)) {
1151 // If both ConOut and StdErr incorporate the same Text Out device,
1152 // their MaxMode and QueryData should be the intersection of both.
1154 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1155 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1156 if (EFI_ERROR (Status
)) {
1160 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1161 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1162 gST
->StdErr
= &mStdErr
.TextOut
;
1164 // Update the CRC32 in the EFI System Table header
1167 gBS
->CalculateCrc32 (
1168 (UINT8
*) &gST
->Hdr
,
1169 gST
->Hdr
.HeaderSize
,
1181 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1182 IN EFI_HANDLE ControllerHandle
,
1183 IN EFI_HANDLE ConSplitterVirtualHandle
,
1184 IN EFI_GUID
*DeviceGuid
,
1185 IN EFI_GUID
*InterfaceGuid
,
1190 Routine Description:
1193 (Standard DriverBinding Protocol Stop() function)
1203 Status
= gBS
->OpenProtocol (
1207 This
->DriverBindingHandle
,
1209 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1211 if (EFI_ERROR (Status
)) {
1215 // close the protocol refered.
1217 gBS
->CloseProtocol (
1220 This
->DriverBindingHandle
,
1221 ConSplitterVirtualHandle
1223 gBS
->CloseProtocol (
1226 This
->DriverBindingHandle
,
1235 ConSplitterConInDriverBindingStop (
1236 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1237 IN EFI_HANDLE ControllerHandle
,
1238 IN UINTN NumberOfChildren
,
1239 IN EFI_HANDLE
*ChildHandleBuffer
1243 Routine Description:
1246 (Standard DriverBinding Protocol Stop() function)
1255 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1257 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1258 if (NumberOfChildren
== 0) {
1262 Status
= gBS
->OpenProtocol (
1264 &gEfiSimpleTextInputExProtocolGuid
,
1265 (VOID
**) &TextInEx
,
1266 This
->DriverBindingHandle
,
1268 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1270 if (EFI_ERROR (Status
)) {
1274 Status
= ConSplitterTextInExDeleteDevice (&mConIn
, TextInEx
);
1275 if (EFI_ERROR (Status
)) {
1280 Status
= ConSplitterStop (
1283 mConIn
.VirtualHandle
,
1284 &gEfiConsoleInDeviceGuid
,
1285 &gEfiSimpleTextInProtocolGuid
,
1288 if (EFI_ERROR (Status
)) {
1292 // Delete this console input device's data structures.
1294 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1299 ConSplitterSimplePointerDriverBindingStop (
1300 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1301 IN EFI_HANDLE ControllerHandle
,
1302 IN UINTN NumberOfChildren
,
1303 IN EFI_HANDLE
*ChildHandleBuffer
1307 Routine Description:
1310 (Standard DriverBinding Protocol Stop() function)
1319 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1321 if (NumberOfChildren
== 0) {
1325 Status
= ConSplitterStop (
1328 mConIn
.VirtualHandle
,
1329 &gEfiSimplePointerProtocolGuid
,
1330 &gEfiSimplePointerProtocolGuid
,
1331 (VOID
**) &SimplePointer
1333 if (EFI_ERROR (Status
)) {
1337 // Delete this console input device's data structures.
1339 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1344 ConSplitterConOutDriverBindingStop (
1345 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1346 IN EFI_HANDLE ControllerHandle
,
1347 IN UINTN NumberOfChildren
,
1348 IN EFI_HANDLE
*ChildHandleBuffer
1352 Routine Description:
1355 (Standard DriverBinding Protocol Stop() function)
1364 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1366 if (NumberOfChildren
== 0) {
1370 Status
= ConSplitterStop (
1373 mConOut
.VirtualHandle
,
1374 &gEfiConsoleOutDeviceGuid
,
1375 &gEfiSimpleTextOutProtocolGuid
,
1378 if (EFI_ERROR (Status
)) {
1383 // Delete this console output device's data structures.
1385 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1390 ConSplitterStdErrDriverBindingStop (
1391 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1392 IN EFI_HANDLE ControllerHandle
,
1393 IN UINTN NumberOfChildren
,
1394 IN EFI_HANDLE
*ChildHandleBuffer
1398 Routine Description:
1401 (Standard DriverBinding Protocol Stop() function)
1405 EFI_SUCCESS - Complete successfully.
1410 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1412 if (NumberOfChildren
== 0) {
1416 Status
= ConSplitterStop (
1419 mStdErr
.VirtualHandle
,
1420 &gEfiStandardErrorDeviceGuid
,
1421 &gEfiSimpleTextOutProtocolGuid
,
1424 if (EFI_ERROR (Status
)) {
1428 // Delete this console error out device's data structures.
1430 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1431 if (EFI_ERROR (Status
)) {
1435 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1436 gST
->StandardErrorHandle
= NULL
;
1439 // Update the CRC32 in the EFI System Table header
1442 gBS
->CalculateCrc32 (
1443 (UINT8
*) &gST
->Hdr
,
1444 gST
->Hdr
.HeaderSize
,
1453 ConSplitterGrowBuffer (
1454 IN UINTN SizeOfCount
,
1456 IN OUT VOID
**Buffer
1460 Routine Description:
1461 Take the passed in Buffer of size SizeOfCount and grow the buffer
1462 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1463 bytes. Copy the current data in Buffer to the new version of Buffer
1464 and free the old version of buffer.
1468 SizeOfCount - Size of element in array
1469 Count - Current number of elements in array
1470 Buffer - Bigger version of passed in Buffer with all the data
1473 EFI_SUCCESS - Buffer size has grown
1474 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1485 // grow the buffer to new buffer size,
1486 // copy the old buffer's content to the new-size buffer,
1487 // then free the old buffer.
1489 OldSize
= *Count
* SizeOfCount
;
1490 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1491 NewSize
= *Count
* SizeOfCount
;
1493 Ptr
= AllocateZeroPool (NewSize
);
1495 return EFI_OUT_OF_RESOURCES
;
1498 CopyMem (Ptr
, *Buffer
, OldSize
);
1500 if (*Buffer
!= NULL
) {
1510 ConSplitterTextInAddDevice (
1511 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1512 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1516 Routine Description:
1523 EFI_OUT_OF_RESOURCES
1530 // If the Text In List is full, enlarge it by calling growbuffer().
1532 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1533 Status
= ConSplitterGrowBuffer (
1534 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1535 &Private
->TextInListCount
,
1536 (VOID
**) &Private
->TextInList
1538 if (EFI_ERROR (Status
)) {
1539 return EFI_OUT_OF_RESOURCES
;
1543 // Add the new text-in device data structure into the Text In List.
1545 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1546 Private
->CurrentNumberOfConsoles
++;
1549 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1551 gBS
->CheckEvent (TextIn
->WaitForKey
);
1557 ConSplitterTextInDeleteDevice (
1558 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1559 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1563 Routine Description:
1576 // Remove the specified text-in device data structure from the Text In List,
1577 // and rearrange the remaining data structures in the Text In List.
1579 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1580 if (Private
->TextInList
[Index
] == TextIn
) {
1581 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1582 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1585 Private
->CurrentNumberOfConsoles
--;
1590 return EFI_NOT_FOUND
;
1594 ConSplitterTextInExAddDevice (
1595 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1596 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1602 // If the TextInEx List is full, enlarge it by calling growbuffer().
1604 if (Private
->CurrentNumberOfExConsoles
>= Private
->TextInExListCount
) {
1605 Status
= ConSplitterGrowBuffer (
1606 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
1607 &Private
->TextInExListCount
,
1608 (VOID
**) &Private
->TextInExList
1610 if (EFI_ERROR (Status
)) {
1611 return EFI_OUT_OF_RESOURCES
;
1615 // Add the new text-in device data structure into the Text In List.
1617 Private
->TextInExList
[Private
->CurrentNumberOfExConsoles
] = TextInEx
;
1618 Private
->CurrentNumberOfExConsoles
++;
1621 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1623 gBS
->CheckEvent (TextInEx
->WaitForKeyEx
);
1629 ConSplitterTextInExDeleteDevice (
1630 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1631 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1636 // Remove the specified text-in device data structure from the Text In List,
1637 // and rearrange the remaining data structures in the Text In List.
1639 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
1640 if (Private
->TextInExList
[Index
] == TextInEx
) {
1641 for (Index
= Index
; Index
< Private
->CurrentNumberOfExConsoles
- 1; Index
++) {
1642 Private
->TextInExList
[Index
] = Private
->TextInExList
[Index
+ 1];
1645 Private
->CurrentNumberOfExConsoles
--;
1650 return EFI_NOT_FOUND
;
1654 ConSplitterSimplePointerAddDevice (
1655 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1656 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1660 Routine Description:
1666 EFI_OUT_OF_RESOURCES
1674 // If the Text In List is full, enlarge it by calling growbuffer().
1676 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1677 Status
= ConSplitterGrowBuffer (
1678 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1679 &Private
->PointerListCount
,
1680 (VOID
**) &Private
->PointerList
1682 if (EFI_ERROR (Status
)) {
1683 return EFI_OUT_OF_RESOURCES
;
1687 // Add the new text-in device data structure into the Text In List.
1689 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1690 Private
->CurrentNumberOfPointers
++;
1695 ConSplitterSimplePointerDeleteDevice (
1696 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1697 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1701 Routine Description:
1713 // Remove the specified text-in device data structure from the Text In List,
1714 // and rearrange the remaining data structures in the Text In List.
1716 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1717 if (Private
->PointerList
[Index
] == SimplePointer
) {
1718 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1719 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1722 Private
->CurrentNumberOfPointers
--;
1727 return EFI_NOT_FOUND
;
1732 ConSplitterGrowMapTable (
1733 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1737 Routine Description:
1750 INT32
*TextOutModeMap
;
1751 INT32
*OldTextOutModeMap
;
1755 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1756 OldTextOutModeMap
= Private
->TextOutModeMap
;
1757 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1759 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1760 if (TextOutModeMap
== NULL
) {
1761 return EFI_OUT_OF_RESOURCES
;
1764 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1765 Private
->TextOutModeMap
= TextOutModeMap
;
1768 // If TextOutList has been enlarged, need to realloc the mode map table
1769 // The mode map table is regarded as a two dimension array.
1772 // 0 ---------> TextOutListCount ----> TextOutListCount
1773 // | -------------------------------------------
1780 // -------------------------------------------
1783 if (OldTextOutModeMap
!= NULL
) {
1785 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1787 SrcAddress
= OldTextOutModeMap
;
1790 // Copy the old data to the new one
1792 while (Index
< Private
->TextOutMode
.MaxMode
) {
1793 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1794 TextOutModeMap
+= NewSize
;
1799 // Free the old buffer
1801 FreePool (OldTextOutModeMap
);
1809 ConSplitterAddOutputMode (
1810 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1811 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1815 Routine Description:
1830 MaxMode
= TextOut
->Mode
->MaxMode
;
1831 Private
->TextOutMode
.MaxMode
= MaxMode
;
1834 // Grow the buffer if query data buffer is not large enough to
1835 // hold all the mode supported by the first console.
1837 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1838 Status
= ConSplitterGrowBuffer (
1839 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1840 &Private
->TextOutQueryDataCount
,
1841 (VOID
**) &Private
->TextOutQueryData
1843 if (EFI_ERROR (Status
)) {
1844 return EFI_OUT_OF_RESOURCES
;
1848 // Allocate buffer for the output mode map
1850 Status
= ConSplitterGrowMapTable (Private
);
1851 if (EFI_ERROR (Status
)) {
1852 return EFI_OUT_OF_RESOURCES
;
1855 // As the first textout device, directly add the mode in to QueryData
1856 // and at the same time record the mapping between QueryData and TextOut.
1860 while (Mode
< MaxMode
) {
1861 TextOut
->QueryMode (
1864 &Private
->TextOutQueryData
[Mode
].Columns
,
1865 &Private
->TextOutQueryData
[Mode
].Rows
1867 Private
->TextOutModeMap
[Index
] = Mode
;
1869 Index
+= Private
->TextOutListCount
;
1877 ConSplitterGetIntersection (
1878 IN INT32
*TextOutModeMap
,
1879 IN INT32
*NewlyAddedMap
,
1880 IN UINTN MapStepSize
,
1881 IN UINTN NewMapStepSize
,
1883 OUT INT32
*CurrentMode
1887 INT32
*CurrentMapEntry
;
1888 INT32
*NextMapEntry
;
1889 INT32 CurrentMaxMode
;
1893 CurrentMapEntry
= TextOutModeMap
;
1894 NextMapEntry
= TextOutModeMap
;
1895 CurrentMaxMode
= *MaxMode
;
1896 Mode
= *CurrentMode
;
1898 while (Index
< CurrentMaxMode
) {
1899 if (*NewlyAddedMap
== -1) {
1901 // This mode is not supported any more. Remove it. Special care
1902 // must be taken as this remove will also affect current mode;
1904 if (Index
== *CurrentMode
) {
1906 } else if (Index
< *CurrentMode
) {
1911 if (CurrentMapEntry
!= NextMapEntry
) {
1912 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1915 NextMapEntry
+= MapStepSize
;
1918 CurrentMapEntry
+= MapStepSize
;
1919 NewlyAddedMap
+= NewMapStepSize
;
1923 *CurrentMode
= Mode
;
1930 ConSplitterSyncOutputMode (
1931 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1932 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1936 Routine Description:
1939 Private - Private data structure.
1940 TextOut - Text Out Protocol.
1947 INT32 CurrentMaxMode
;
1950 INT32
*TextOutModeMap
;
1952 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1958 // Must make sure that current mode won't change even if mode number changes
1960 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1961 TextOutModeMap
= Private
->TextOutModeMap
;
1962 StepSize
= Private
->TextOutListCount
;
1963 TextOutQueryData
= Private
->TextOutQueryData
;
1966 // Query all the mode that the newly added TextOut supports
1969 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1970 while (Mode
< TextOut
->Mode
->MaxMode
) {
1971 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1974 // Search the QueryData database to see if they intersects
1977 while (Index
< CurrentMaxMode
) {
1978 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1979 MapTable
[Index
* StepSize
] = Mode
;
1989 // Now search the TextOutModeMap table to find the intersection of supported
1990 // mode between ConSplitter and the newly added device.
1992 ConSplitterGetIntersection (
1997 &Private
->TextOutMode
.MaxMode
,
1998 &Private
->TextOutMode
.Mode
2006 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2011 Routine Description:
2018 EFI_OUT_OF_RESOURCES
2022 UINTN ConOutNumOfConsoles
;
2023 UINTN StdErrNumOfConsoles
;
2024 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
2025 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
2030 INT32 ConOutMaxMode
;
2031 INT32 StdErrMaxMode
;
2034 INT32
*ConOutModeMap
;
2035 INT32
*StdErrModeMap
;
2036 INT32
*ConOutMapTable
;
2037 INT32
*StdErrMapTable
;
2038 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
2039 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
2040 BOOLEAN FoundTheSameTextOut
;
2041 UINTN ConOutMapTableSize
;
2042 UINTN StdErrMapTableSize
;
2044 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
2045 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
2046 ConOutTextOutList
= mConOut
.TextOutList
;
2047 StdErrTextOutList
= mStdErr
.TextOutList
;
2050 FoundTheSameTextOut
= FALSE
;
2051 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
2053 while (Indexj
< StdErrNumOfConsoles
) {
2054 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
2055 FoundTheSameTextOut
= TRUE
;
2060 StdErrTextOutList
++;
2064 ConOutTextOutList
++;
2067 if (!FoundTheSameTextOut
) {
2071 // Must make sure that current mode won't change even if mode number changes
2073 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
2074 ConOutModeMap
= mConOut
.TextOutModeMap
;
2075 ConOutQueryData
= mConOut
.TextOutQueryData
;
2077 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
2078 StdErrModeMap
= mStdErr
.TextOutModeMap
;
2079 StdErrQueryData
= mStdErr
.TextOutQueryData
;
2082 // Allocate the map table and set the map table's index to -1.
2084 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
2085 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
2086 if (ConOutMapTable
== NULL
) {
2087 return EFI_OUT_OF_RESOURCES
;
2090 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
2092 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
2093 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
2094 if (StdErrMapTable
== NULL
) {
2095 return EFI_OUT_OF_RESOURCES
;
2098 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
2101 // Find the intersection of the two set of modes. If they actually intersect, the
2102 // correponding entry in the map table is set to 1.
2105 while (Mode
< ConOutMaxMode
) {
2107 // Search the other's QueryData database to see if they intersect
2110 Rows
= ConOutQueryData
[Mode
].Rows
;
2111 Columns
= ConOutQueryData
[Mode
].Columns
;
2112 while (Index
< StdErrMaxMode
) {
2113 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
2114 ConOutMapTable
[Mode
] = 1;
2115 StdErrMapTable
[Index
] = 1;
2125 // Now search the TextOutModeMap table to find the intersection of supported
2126 // mode between ConSplitter and the newly added device.
2128 ConSplitterGetIntersection (
2131 mConOut
.TextOutListCount
,
2133 &(mConOut
.TextOutMode
.MaxMode
),
2134 &(mConOut
.TextOutMode
.Mode
)
2136 if (mConOut
.TextOutMode
.Mode
< 0) {
2137 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2140 ConSplitterGetIntersection (
2143 mStdErr
.TextOutListCount
,
2145 &(mStdErr
.TextOutMode
.MaxMode
),
2146 &(mStdErr
.TextOutMode
.Mode
)
2148 if (mStdErr
.TextOutMode
.Mode
< 0) {
2149 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2152 FreePool (ConOutMapTable
);
2153 FreePool (StdErrMapTable
);
2160 ConSplitterAddGraphicsOutputMode (
2161 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2162 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2163 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2167 Routine Description:
2179 TEXT_OUT_GOP_MODE
*Mode
;
2181 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2182 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2183 TEXT_OUT_GOP_MODE
*ModeBuffer
;
2184 TEXT_OUT_GOP_MODE
*MatchedMode
;
2188 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2189 return EFI_UNSUPPORTED
;
2192 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2194 if (GraphicsOutput
!= NULL
) {
2195 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2197 // This is the first Graphics Output device added
2199 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2200 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2201 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2202 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2203 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2204 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2207 // Allocate resource for the private mode buffer
2209 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
2210 if (ModeBuffer
== NULL
) {
2211 return EFI_OUT_OF_RESOURCES
;
2213 FreePool (Private
->GraphicsOutputModeBuffer
);
2214 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2217 // Store all supported display modes to the private mode buffer
2220 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2221 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2222 if (EFI_ERROR (Status
)) {
2225 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2226 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2232 // Check intersection of display mode
2234 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2235 if (ModeBuffer
== NULL
) {
2236 return EFI_OUT_OF_RESOURCES
;
2239 MatchedMode
= ModeBuffer
;
2240 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2241 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2244 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2245 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2246 if (EFI_ERROR (Status
)) {
2249 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2250 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2259 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2267 // Drop the old mode buffer, assign it to a new one
2269 FreePool (Private
->GraphicsOutputModeBuffer
);
2270 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2273 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2275 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2276 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2277 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2278 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2279 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2280 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2284 // Select a prefered Display mode 800x600
2286 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2287 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2288 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2293 // Prefered mode is not found, set to mode 0
2295 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2300 // Current mode number may need update now, so set it to an invalide mode number
2302 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2305 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2306 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2308 CurrentGraphicsOutputMode
->MaxMode
= 1;
2309 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2310 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2311 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2312 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2313 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2314 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2315 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2316 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2319 // Update the private mode buffer
2321 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2322 ModeBuffer
->HorizontalResolution
= 800;
2323 ModeBuffer
->VerticalResolution
= 600;
2326 // Current mode is unknow now, set it to an invalid mode number 0xffff
2328 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2333 // Force GraphicsOutput mode to be set,
2334 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2336 Private
->HardwareNeedsStarting
= TRUE
;
2337 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2339 Private
->CurrentNumberOfGraphicsOutput
++;
2345 ConSplitterTextOutAddDevice (
2346 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2347 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2348 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2349 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2353 Routine Description:
2364 UINTN CurrentNumOfConsoles
;
2367 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2369 Status
= EFI_SUCCESS
;
2370 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2373 // If the Text Out List is full, enlarge it by calling growbuffer().
2375 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2376 Status
= ConSplitterGrowBuffer (
2377 sizeof (TEXT_OUT_AND_GOP_DATA
),
2378 &Private
->TextOutListCount
,
2379 (VOID
**) &Private
->TextOutList
2381 if (EFI_ERROR (Status
)) {
2382 return EFI_OUT_OF_RESOURCES
;
2385 // Also need to reallocate the TextOutModeMap table
2387 Status
= ConSplitterGrowMapTable (Private
);
2388 if (EFI_ERROR (Status
)) {
2389 return EFI_OUT_OF_RESOURCES
;
2393 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2395 TextAndGop
->TextOut
= TextOut
;
2396 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2397 TextAndGop
->UgaDraw
= UgaDraw
;
2399 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2401 // If No UGA device then use the ConOut device
2403 TextAndGop
->TextOutEnabled
= TRUE
;
2406 // If UGA device use ConOut device only used if UGA screen is in Text mode
2408 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2411 if (CurrentNumOfConsoles
== 0) {
2413 // Add the first device's output mode to console splitter's mode list
2415 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2417 ConSplitterSyncOutputMode (Private
, TextOut
);
2420 Private
->CurrentNumberOfConsoles
++;
2423 // Scan both TextOutList, for the intersection TextOut device
2424 // maybe both ConOut and StdErr incorporate the same Text Out
2425 // device in them, thus the output of both should be synced.
2427 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2429 CurrentMode
= Private
->TextOutMode
.Mode
;
2430 MaxMode
= Private
->TextOutMode
.MaxMode
;
2431 ASSERT (MaxMode
>= 1);
2433 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2434 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2435 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2439 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2441 // We just added a new UGA device in graphics mode
2443 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2444 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2445 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2446 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2448 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2450 // The new console supports the same mode of the current console so sync up
2452 DevNullSyncGopStdOut (Private
);
2455 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2457 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2464 ConSplitterTextOutDeleteDevice (
2465 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2466 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2470 Routine Description:
2481 UINTN CurrentNumOfConsoles
;
2482 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2486 // Remove the specified text-out device data structure from the Text out List,
2487 // and rearrange the remaining data structures in the Text out List.
2489 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2490 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2491 TextOutList
= Private
->TextOutList
;
2492 while (Index
>= 0) {
2493 if (TextOutList
->TextOut
== TextOut
) {
2494 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2495 CurrentNumOfConsoles
--;
2503 // The specified TextOut is not managed by the ConSplitter driver
2506 return EFI_NOT_FOUND
;
2509 if (CurrentNumOfConsoles
== 0) {
2511 // If the number of consoles is zero clear the Dev NULL device
2513 Private
->CurrentNumberOfConsoles
= 0;
2514 Private
->TextOutMode
.MaxMode
= 1;
2515 Private
->TextOutQueryData
[0].Columns
= 80;
2516 Private
->TextOutQueryData
[0].Rows
= 25;
2517 DevNullTextOutSetMode (Private
, 0);
2522 // Max Mode is realy an intersection of the QueryMode command to all
2523 // devices. So we must copy the QueryMode of the first device to
2527 Private
->TextOutQueryData
,
2528 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2531 FreePool (Private
->TextOutModeMap
);
2532 Private
->TextOutModeMap
= NULL
;
2533 TextOutList
= Private
->TextOutList
;
2536 // Add the first TextOut to the QueryData array and ModeMap table
2538 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2541 // Now add one by one
2544 Private
->CurrentNumberOfConsoles
= 1;
2546 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2547 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2549 Private
->CurrentNumberOfConsoles
++;
2553 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2558 // ConSplitter TextIn member functions
2562 ConSplitterTextInReset (
2563 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2564 IN BOOLEAN ExtendedVerification
2568 Routine Description:
2569 Reset the input device and optionaly run diagnostics
2572 This - Protocol instance pointer.
2573 ExtendedVerification - Driver may perform diagnostics on reset.
2576 EFI_SUCCESS - The device was reset.
2577 EFI_DEVICE_ERROR - The device is not functioning properly and could
2583 EFI_STATUS ReturnStatus
;
2584 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2587 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2589 Private
->KeyEventSignalState
= FALSE
;
2592 // return the worst status met
2594 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2595 Status
= Private
->TextInList
[Index
]->Reset (
2596 Private
->TextInList
[Index
],
2597 ExtendedVerification
2599 if (EFI_ERROR (Status
)) {
2600 ReturnStatus
= Status
;
2604 return ReturnStatus
;
2609 ConSplitterTextInPrivateReadKeyStroke (
2610 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2611 OUT EFI_INPUT_KEY
*Key
2615 Routine Description:
2616 Reads the next keystroke from the input device. The WaitForKey Event can
2617 be used to test for existance of a keystroke via WaitForEvent () call.
2620 This - Protocol instance pointer.
2621 Key - Driver may perform diagnostics on reset.
2624 EFI_SUCCESS - The keystroke information was returned.
2625 EFI_NOT_READY - There was no keystroke data availiable.
2626 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2633 EFI_INPUT_KEY CurrentKey
;
2635 Key
->UnicodeChar
= 0;
2636 Key
->ScanCode
= SCAN_NULL
;
2639 // if no physical console input device exists, return EFI_NOT_READY;
2640 // if any physical console input device has key input,
2641 // return the key and EFI_SUCCESS.
2643 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2644 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2645 Private
->TextInList
[Index
],
2648 if (!EFI_ERROR (Status
)) {
2654 return EFI_NOT_READY
;
2658 ConSpliterConssoleControlStdInLocked (
2663 Routine Description:
2664 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2665 the only device locked.
2672 FALSE - StdIn working normally
2676 return mConIn
.PasswordEnabled
;
2681 ConSpliterConsoleControlLockStdInEvent (
2687 Routine Description:
2688 This timer event will fire when StdIn is locked. It will check the key
2689 sequence on StdIn to see if it matches the password. Any error in the
2690 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2691 TRUE the StdIn splitter will not report any input.
2694 (Standard EFI_EVENT_NOTIFY)
2703 CHAR16 BackSpaceString
[2];
2704 CHAR16 SpaceString
[2];
2707 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2708 if (!EFI_ERROR (Status
)) {
2710 // if it's an ENTER, match password
2712 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2713 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2714 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2716 // Password not match
2718 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2719 mConIn
.PwdIndex
= 0;
2722 // Key matches password sequence
2724 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2725 mConIn
.PasswordEnabled
= FALSE
;
2726 Status
= EFI_NOT_READY
;
2728 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2732 if (mConIn
.PwdIndex
> 0) {
2733 BackSpaceString
[0] = CHAR_BACKSPACE
;
2734 BackSpaceString
[1] = 0;
2736 SpaceString
[0] = ' ';
2739 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2740 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2741 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2745 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2747 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2749 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2750 if (mConIn
.PwdIndex
== 0) {
2751 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2754 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2755 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2760 } while (!EFI_ERROR (Status
));
2765 ConSpliterConsoleControlLockStdIn (
2766 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2771 Routine Description:
2772 If Password is NULL unlock the password state variable and set the event
2773 timer. If the Password is too big return an error. If the Password is valid
2774 Copy the Password and enable state variable and then arm the periodic timer
2779 EFI_SUCCESS - Lock the StdIn device
2780 EFI_INVALID_PARAMETER - Password is NULL
2781 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2785 if (Password
== NULL
) {
2786 return EFI_INVALID_PARAMETER
;
2789 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2791 // Currently have a max password size
2793 return EFI_OUT_OF_RESOURCES
;
2796 // Save the password, initialize state variables and arm event timer
2798 StrCpy (mConIn
.Password
, Password
);
2799 mConIn
.PasswordEnabled
= TRUE
;
2800 mConIn
.PwdIndex
= 0;
2801 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2808 ConSplitterTextInReadKeyStroke (
2809 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2810 OUT EFI_INPUT_KEY
*Key
2814 Routine Description:
2815 Reads the next keystroke from the input device. The WaitForKey Event can
2816 be used to test for existance of a keystroke via WaitForEvent () call.
2817 If the ConIn is password locked make it look like no keystroke is availible
2820 This - Protocol instance pointer.
2821 Key - Driver may perform diagnostics on reset.
2824 EFI_SUCCESS - The keystroke information was returned.
2825 EFI_NOT_READY - There was no keystroke data availiable.
2826 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2831 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2833 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2834 if (Private
->PasswordEnabled
) {
2836 // If StdIn Locked return not ready
2838 return EFI_NOT_READY
;
2841 Private
->KeyEventSignalState
= FALSE
;
2843 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2848 ConSplitterTextInWaitForKey (
2854 Routine Description:
2855 This event agregates all the events of the ConIn devices in the spliter.
2856 If the ConIn is password locked then return.
2857 If any events of physical ConIn devices are signaled, signal the ConIn
2858 spliter event. This will cause the calling code to call
2859 ConSplitterTextInReadKeyStroke ().
2862 Event - The Event assoicated with callback.
2863 Context - Context registered when Event was created.
2871 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2874 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2875 if (Private
->PasswordEnabled
) {
2877 // If StdIn Locked return not ready
2883 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2885 if (Private
->KeyEventSignalState
) {
2886 gBS
->SignalEvent (Event
);
2890 // if any physical console input device has key input, signal the event.
2892 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2893 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2894 if (!EFI_ERROR (Status
)) {
2895 gBS
->SignalEvent (Event
);
2896 Private
->KeyEventSignalState
= TRUE
;
2905 IN EFI_KEY_DATA
*RegsiteredData
,
2906 IN EFI_KEY_DATA
*InputData
2910 Routine Description:
2914 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
2915 state data for the key that was registered.
2916 InputData - A pointer to a buffer that is filled in with the keystroke
2917 state data for the key that was pressed.
2920 TRUE - Key be pressed matches a registered key.
2921 FLASE - Match failed.
2925 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
2927 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
2928 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
2933 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
2935 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
2936 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
2939 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
2940 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
2949 // Simple Text Input Ex protocol functions
2954 ConSplitterTextInResetEx (
2955 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2956 IN BOOLEAN ExtendedVerification
2960 Routine Description:
2961 Reset the input device and optionaly run diagnostics
2964 This - Protocol instance pointer.
2965 ExtendedVerification - Driver may perform diagnostics on reset.
2968 EFI_SUCCESS - The device was reset.
2969 EFI_DEVICE_ERROR - The device is not functioning properly and could
2975 EFI_STATUS ReturnStatus
;
2976 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2979 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2981 Private
->KeyEventSignalState
= FALSE
;
2984 // return the worst status met
2986 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
2987 Status
= Private
->TextInExList
[Index
]->Reset (
2988 Private
->TextInExList
[Index
],
2989 ExtendedVerification
2991 if (EFI_ERROR (Status
)) {
2992 ReturnStatus
= Status
;
2996 return ReturnStatus
;
3002 ConSplitterTextInReadKeyStrokeEx (
3003 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3004 OUT EFI_KEY_DATA
*KeyData
3008 Routine Description:
3009 Reads the next keystroke from the input device. The WaitForKey Event can
3010 be used to test for existance of a keystroke via WaitForEvent () call.
3013 This - Protocol instance pointer.
3014 KeyData - A pointer to a buffer that is filled in with the keystroke
3015 state data for the key that was pressed.
3018 EFI_SUCCESS - The keystroke information was returned.
3019 EFI_NOT_READY - There was no keystroke data availiable.
3020 EFI_DEVICE_ERROR - The keystroke information was not returned due to
3022 EFI_INVALID_PARAMETER - KeyData is NULL.
3026 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3029 EFI_KEY_DATA CurrentKeyData
;
3032 if (KeyData
== NULL
) {
3033 return EFI_INVALID_PARAMETER
;
3036 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3037 if (Private
->PasswordEnabled
) {
3039 // If StdIn Locked return not ready
3041 return EFI_NOT_READY
;
3044 Private
->KeyEventSignalState
= FALSE
;
3046 KeyData
->Key
.UnicodeChar
= 0;
3047 KeyData
->Key
.ScanCode
= SCAN_NULL
;
3050 // if no physical console input device exists, return EFI_NOT_READY;
3051 // if any physical console input device has key input,
3052 // return the key and EFI_SUCCESS.
3054 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3055 Status
= Private
->TextInExList
[Index
]->ReadKeyStrokeEx (
3056 Private
->TextInExList
[Index
],
3059 if (!EFI_ERROR (Status
)) {
3060 CopyMem (KeyData
, &CurrentKeyData
, sizeof (CurrentKeyData
));
3065 return EFI_NOT_READY
;
3070 ConSplitterTextInSetState (
3071 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3072 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
3076 Routine Description:
3077 Set certain state for the input device.
3080 This - Protocol instance pointer.
3081 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
3082 state for the input device.
3085 EFI_SUCCESS - The device state was set successfully.
3086 EFI_DEVICE_ERROR - The device is not functioning correctly and could
3087 not have the setting adjusted.
3088 EFI_UNSUPPORTED - The device does not have the ability to set its state.
3089 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
3093 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3097 if (KeyToggleState
== NULL
) {
3098 return EFI_INVALID_PARAMETER
;
3101 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3104 // if no physical console input device exists, return EFI_SUCCESS;
3105 // otherwise return the status of setting state of physical console input device
3107 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3108 Status
= Private
->TextInExList
[Index
]->SetState (
3109 Private
->TextInExList
[Index
],
3112 if (EFI_ERROR (Status
)) {
3123 ConSplitterTextInRegisterKeyNotify (
3124 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3125 IN EFI_KEY_DATA
*KeyData
,
3126 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
3127 OUT EFI_HANDLE
*NotifyHandle
3131 Routine Description:
3132 Register a notification function for a particular keystroke for the input device.
3135 This - Protocol instance pointer.
3136 KeyData - A pointer to a buffer that is filled in with the keystroke
3137 information data for the key that was pressed.
3138 KeyNotificationFunction - Points to the function to be called when the key
3139 sequence is typed specified by KeyData.
3140 NotifyHandle - Points to the unique handle assigned to the registered notification.
3143 EFI_SUCCESS - The notification function was registered successfully.
3144 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
3145 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
3149 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3152 TEXT_IN_EX_SPLITTER_NOTIFY
*NewNotify
;
3154 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3157 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
3158 return EFI_INVALID_PARAMETER
;
3161 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3164 // if no physical console input device exists,
3165 // return EFI_SUCCESS directly.
3167 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3172 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3174 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3175 CurrentNotify
= CR (
3177 TEXT_IN_EX_SPLITTER_NOTIFY
,
3179 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
3181 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
3182 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
3183 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
3190 // Allocate resource to save the notification function
3192 NewNotify
= (TEXT_IN_EX_SPLITTER_NOTIFY
*) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY
));
3193 if (NewNotify
== NULL
) {
3194 return EFI_OUT_OF_RESOURCES
;
3196 NewNotify
->NotifyHandleList
= (EFI_HANDLE
*) AllocateZeroPool (sizeof (EFI_HANDLE
) * Private
->CurrentNumberOfExConsoles
);
3197 if (NewNotify
->NotifyHandleList
== NULL
) {
3198 gBS
->FreePool (NewNotify
);
3199 return EFI_OUT_OF_RESOURCES
;
3201 NewNotify
->Signature
= TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
;
3202 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
3203 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
3206 // Return the wrong status of registering key notify of
3207 // physical console input device if meet problems
3209 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3210 Status
= Private
->TextInExList
[Index
]->RegisterKeyNotify (
3211 Private
->TextInExList
[Index
],
3213 KeyNotificationFunction
,
3214 &NewNotify
->NotifyHandleList
[Index
]
3216 if (EFI_ERROR (Status
)) {
3217 gBS
->FreePool (NewNotify
->NotifyHandleList
);
3218 gBS
->FreePool (NewNotify
);
3224 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
3226 Status
= gBS
->InstallMultipleProtocolInterfaces (
3227 &NewNotify
->NotifyHandle
,
3228 &gSimpleTextInExNotifyGuid
,
3232 ASSERT_EFI_ERROR (Status
);
3234 InsertTailList (&mConIn
.NotifyList
, &NewNotify
->NotifyEntry
);
3236 *NotifyHandle
= NewNotify
->NotifyHandle
;
3244 ConSplitterTextInUnregisterKeyNotify (
3245 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3246 IN EFI_HANDLE NotificationHandle
3250 Routine Description:
3251 Remove a registered notification function from a particular keystroke.
3254 This - Protocol instance pointer.
3255 NotificationHandle - The handle of the notification function being unregistered.
3258 EFI_SUCCESS - The notification function was unregistered successfully.
3259 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
3260 EFI_NOT_FOUND - Can not find the matching entry in database.
3264 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3267 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3270 if (NotificationHandle
== NULL
) {
3271 return EFI_INVALID_PARAMETER
;
3274 Status
= gBS
->OpenProtocol (
3276 &gSimpleTextInExNotifyGuid
,
3280 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
3282 if (EFI_ERROR (Status
)) {
3283 return EFI_INVALID_PARAMETER
;
3286 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3289 // if no physical console input device exists,
3290 // return EFI_SUCCESS directly.
3292 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3296 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3297 CurrentNotify
= CR (Link
, TEXT_IN_EX_SPLITTER_NOTIFY
, NotifyEntry
, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
);
3298 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
3299 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3300 Status
= Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3301 Private
->TextInExList
[Index
],
3302 CurrentNotify
->NotifyHandleList
[Index
]
3304 if (EFI_ERROR (Status
)) {
3308 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
3309 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3310 CurrentNotify
->NotifyHandle
,
3311 &gSimpleTextInExNotifyGuid
,
3315 ASSERT_EFI_ERROR (Status
);
3316 gBS
->FreePool (CurrentNotify
->NotifyHandleList
);
3317 gBS
->FreePool (CurrentNotify
);
3322 return EFI_NOT_FOUND
;
3330 ConSplitterSimplePointerReset (
3331 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3332 IN BOOLEAN ExtendedVerification
3336 Routine Description:
3337 Reset the input device and optionaly run diagnostics
3340 This - Protocol instance pointer.
3341 ExtendedVerification - Driver may perform diagnostics on reset.
3344 EFI_SUCCESS - The device was reset.
3345 EFI_DEVICE_ERROR - The device is not functioning properly and could
3351 EFI_STATUS ReturnStatus
;
3352 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3355 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3357 Private
->InputEventSignalState
= FALSE
;
3359 if (Private
->CurrentNumberOfPointers
== 0) {
3363 // return the worst status met
3365 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3366 Status
= Private
->PointerList
[Index
]->Reset (
3367 Private
->PointerList
[Index
],
3368 ExtendedVerification
3370 if (EFI_ERROR (Status
)) {
3371 ReturnStatus
= Status
;
3375 return ReturnStatus
;
3381 ConSplitterSimplePointerPrivateGetState (
3382 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3383 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3387 Routine Description:
3388 Reads the next keystroke from the input device. The WaitForKey Event can
3389 be used to test for existance of a keystroke via WaitForEvent () call.
3392 This - Protocol instance pointer.
3396 EFI_SUCCESS - The keystroke information was returned.
3397 EFI_NOT_READY - There was no keystroke data availiable.
3398 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3404 EFI_STATUS ReturnStatus
;
3406 EFI_SIMPLE_POINTER_STATE CurrentState
;
3408 State
->RelativeMovementX
= 0;
3409 State
->RelativeMovementY
= 0;
3410 State
->RelativeMovementZ
= 0;
3411 State
->LeftButton
= FALSE
;
3412 State
->RightButton
= FALSE
;
3415 // if no physical console input device exists, return EFI_NOT_READY;
3416 // if any physical console input device has key input,
3417 // return the key and EFI_SUCCESS.
3419 ReturnStatus
= EFI_NOT_READY
;
3420 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3422 Status
= Private
->PointerList
[Index
]->GetState (
3423 Private
->PointerList
[Index
],
3426 if (!EFI_ERROR (Status
)) {
3427 if (ReturnStatus
== EFI_NOT_READY
) {
3428 ReturnStatus
= EFI_SUCCESS
;
3431 if (CurrentState
.LeftButton
) {
3432 State
->LeftButton
= TRUE
;
3435 if (CurrentState
.RightButton
) {
3436 State
->RightButton
= TRUE
;
3439 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
3440 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
3443 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
3444 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
3447 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
3448 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
3450 } else if (Status
== EFI_DEVICE_ERROR
) {
3451 ReturnStatus
= EFI_DEVICE_ERROR
;
3455 return ReturnStatus
;
3460 ConSplitterSimplePointerGetState (
3461 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3462 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3466 Routine Description:
3467 Reads the next keystroke from the input device. The WaitForKey Event can
3468 be used to test for existance of a keystroke via WaitForEvent () call.
3469 If the ConIn is password locked make it look like no keystroke is availible
3472 This - Protocol instance pointer.
3476 EFI_SUCCESS - The keystroke information was returned.
3477 EFI_NOT_READY - There was no keystroke data availiable.
3478 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3483 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3485 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3486 if (Private
->PasswordEnabled
) {
3488 // If StdIn Locked return not ready
3490 return EFI_NOT_READY
;
3493 Private
->InputEventSignalState
= FALSE
;
3495 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
3500 ConSplitterSimplePointerWaitForInput (
3506 Routine Description:
3507 This event agregates all the events of the ConIn devices in the spliter.
3508 If the ConIn is password locked then return.
3509 If any events of physical ConIn devices are signaled, signal the ConIn
3510 spliter event. This will cause the calling code to call
3511 ConSplitterTextInReadKeyStroke ().
3514 Event - The Event assoicated with callback.
3515 Context - Context registered when Event was created.
3523 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3526 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3527 if (Private
->PasswordEnabled
) {
3529 // If StdIn Locked return not ready
3535 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3537 if (Private
->InputEventSignalState
) {
3538 gBS
->SignalEvent (Event
);
3542 // if any physical console input device has key input, signal the event.
3544 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3545 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
3546 if (!EFI_ERROR (Status
)) {
3547 gBS
->SignalEvent (Event
);
3548 Private
->InputEventSignalState
= TRUE
;
3555 ConSplitterTextOutReset (
3556 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3557 IN BOOLEAN ExtendedVerification
3561 Routine Description:
3562 Reset the text output device hardware and optionaly run diagnostics
3565 This - Protocol instance pointer.
3566 ExtendedVerification - Driver may perform more exhaustive verfication
3567 operation of the device during reset.
3570 EFI_SUCCESS - The text output device was reset.
3571 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
3577 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3579 EFI_STATUS ReturnStatus
;
3581 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3584 // return the worst status met
3586 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3588 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3590 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
3591 Private
->TextOutList
[Index
].TextOut
,
3592 ExtendedVerification
3594 if (EFI_ERROR (Status
)) {
3595 ReturnStatus
= Status
;
3600 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
3602 Status
= DevNullTextOutSetMode (Private
, 0);
3603 if (EFI_ERROR (Status
)) {
3604 ReturnStatus
= Status
;
3607 return ReturnStatus
;
3612 ConSplitterTextOutOutputString (
3613 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3618 Routine Description:
3619 Write a Unicode string to the output device.
3622 This - Protocol instance pointer.
3623 String - The NULL-terminated Unicode string to be displayed on the output
3624 device(s). All output devices must also support the Unicode
3625 drawing defined in this file.
3628 EFI_SUCCESS - The string was output to the device.
3629 EFI_DEVICE_ERROR - The device reported an error while attempting to output
3631 EFI_UNSUPPORTED - The output device's mode is not currently in a
3633 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
3634 characters in the Unicode string could not be
3635 rendered and were skipped.
3640 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3642 UINTN BackSpaceCount
;
3643 EFI_STATUS ReturnStatus
;
3644 CHAR16
*TargetString
;
3646 This
->SetAttribute (This
, This
->Mode
->Attribute
);
3648 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3651 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3652 if (*TargetString
== CHAR_BACKSPACE
) {
3658 if (BackSpaceCount
== 0) {
3659 TargetString
= WString
;
3661 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3662 StrCpy (TargetString
, WString
);
3665 // return the worst status met
3667 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3668 if (EFI_ERROR (Status
)) {
3669 ReturnStatus
= Status
;
3672 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3674 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3675 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3676 Private
->TextOutList
[Index
].TextOut
,
3679 if (EFI_ERROR (Status
)) {
3680 ReturnStatus
= Status
;
3685 if (BackSpaceCount
) {
3686 FreePool (TargetString
);
3689 return ReturnStatus
;
3694 ConSplitterTextOutTestString (
3695 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3700 Routine Description:
3701 Verifies that all characters in a Unicode string can be output to the
3705 This - Protocol instance pointer.
3706 String - The NULL-terminated Unicode string to be examined for the output
3710 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3711 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3712 rendered by one or more of the output devices mapped
3718 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3720 EFI_STATUS ReturnStatus
;
3722 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3725 // return the worst status met
3727 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3728 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3729 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3730 Private
->TextOutList
[Index
].TextOut
,
3733 if (EFI_ERROR (Status
)) {
3734 ReturnStatus
= Status
;
3739 // There is no DevNullTextOutTestString () since a Unicode buffer would
3740 // always return EFI_SUCCESS.
3741 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3743 return ReturnStatus
;
3748 ConSplitterTextOutQueryMode (
3749 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3750 IN UINTN ModeNumber
,
3756 Routine Description:
3757 Returns information for an available text mode that the output device(s)
3761 This - Protocol instance pointer.
3762 ModeNumber - The mode number to return information on.
3763 Columns, Rows - Returns the geometry of the text output device for the
3764 requested ModeNumber.
3767 EFI_SUCCESS - The requested mode information was returned.
3768 EFI_DEVICE_ERROR - The device had an error and could not
3769 complete the request.
3770 EFI_UNSUPPORTED - The mode number was not valid.
3774 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3776 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3779 // Check whether param ModeNumber is valid.
3780 // ModeNumber should be within range 0 ~ MaxMode - 1.
3782 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3783 return EFI_UNSUPPORTED
;
3786 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3787 return EFI_UNSUPPORTED
;
3790 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3791 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3793 if (*Columns
<= 0 && *Rows
<= 0) {
3794 return EFI_UNSUPPORTED
;
3803 ConSplitterTextOutSetMode (
3804 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3809 Routine Description:
3810 Sets the output device(s) to a specified mode.
3813 This - Protocol instance pointer.
3814 ModeNumber - The mode number to set.
3817 EFI_SUCCESS - The requested text mode was set.
3818 EFI_DEVICE_ERROR - The device had an error and
3819 could not complete the request.
3820 EFI_UNSUPPORTED - The mode number was not valid.
3825 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3827 INT32
*TextOutModeMap
;
3828 EFI_STATUS ReturnStatus
;
3830 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3833 // Check whether param ModeNumber is valid.
3834 // ModeNumber should be within range 0 ~ MaxMode - 1.
3836 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3837 return EFI_UNSUPPORTED
;
3840 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3841 return EFI_UNSUPPORTED
;
3844 // If the mode is being set to the curent mode, then just clear the screen and return.
3846 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3847 return ConSplitterTextOutClearScreen (This
);
3850 // return the worst status met
3852 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3853 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3855 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3856 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3857 Private
->TextOutList
[Index
].TextOut
,
3858 TextOutModeMap
[Index
]
3861 // If this console device is based on a UGA device, then sync up the bitmap from
3862 // the UGA splitter and reclear the text portion of the display in the new mode.
3864 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3865 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3868 if (EFI_ERROR (Status
)) {
3869 ReturnStatus
= Status
;
3874 // The DevNull Console will support any possible mode as it allocates memory
3876 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3877 if (EFI_ERROR (Status
)) {
3878 ReturnStatus
= Status
;
3881 return ReturnStatus
;
3886 ConSplitterTextOutSetAttribute (
3887 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3892 Routine Description:
3893 Sets the background and foreground colors for the OutputString () and
3894 ClearScreen () functions.
3897 This - Protocol instance pointer.
3898 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3899 bits 4..6 are the background color. All other bits are undefined
3900 and must be zero. The valid Attributes are defined in this file.
3903 EFI_SUCCESS - The attribute was set.
3904 EFI_DEVICE_ERROR - The device had an error and
3905 could not complete the request.
3906 EFI_UNSUPPORTED - The attribute requested is not defined.
3911 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3913 EFI_STATUS ReturnStatus
;
3915 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3918 // Check whether param Attribute is valid.
3920 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3921 return EFI_UNSUPPORTED
;
3925 // return the worst status met
3927 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3929 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3930 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3931 Private
->TextOutList
[Index
].TextOut
,
3934 if (EFI_ERROR (Status
)) {
3935 ReturnStatus
= Status
;
3940 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3942 return ReturnStatus
;
3947 ConSplitterTextOutClearScreen (
3948 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
3952 Routine Description:
3953 Clears the output device(s) display to the currently selected background
3957 This - Protocol instance pointer.
3960 EFI_SUCCESS - The operation completed successfully.
3961 EFI_DEVICE_ERROR - The device had an error and
3962 could not complete the request.
3963 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3968 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3970 EFI_STATUS ReturnStatus
;
3972 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3975 // return the worst status met
3977 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3979 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3980 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3981 if (EFI_ERROR (Status
)) {
3982 ReturnStatus
= Status
;
3987 Status
= DevNullTextOutClearScreen (Private
);
3988 if (EFI_ERROR (Status
)) {
3989 ReturnStatus
= Status
;
3992 return ReturnStatus
;
3997 ConSplitterTextOutSetCursorPosition (
3998 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4004 Routine Description:
4005 Sets the current coordinates of the cursor position
4008 This - Protocol instance pointer.
4009 Column, Row - the position to set the cursor to. Must be greater than or
4010 equal to zero and less than the number of columns and rows
4014 EFI_SUCCESS - The operation completed successfully.
4015 EFI_DEVICE_ERROR - The device had an error and
4016 could not complete the request.
4017 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
4018 cursor position is invalid for the current mode.
4023 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4025 EFI_STATUS ReturnStatus
;
4028 INT32
*TextOutModeMap
;
4032 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4033 TextOutModeMap
= NULL
;
4034 ModeNumber
= Private
->TextOutMode
.Mode
;
4037 // Get current MaxColumn and MaxRow from intersection map
4039 if (Private
->TextOutModeMap
!= NULL
) {
4040 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4041 CurrentMode
= *TextOutModeMap
;
4043 CurrentMode
= ModeNumber
;
4046 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4047 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4049 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
4050 return EFI_UNSUPPORTED
;
4053 // return the worst status met
4055 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4057 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4058 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
4059 Private
->TextOutList
[Index
].TextOut
,
4063 if (EFI_ERROR (Status
)) {
4064 ReturnStatus
= Status
;
4069 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
4071 return ReturnStatus
;
4076 ConSplitterTextOutEnableCursor (
4077 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4082 Routine Description:
4083 Makes the cursor visible or invisible
4086 This - Protocol instance pointer.
4087 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
4088 set to be invisible.
4091 EFI_SUCCESS - The operation completed successfully.
4092 EFI_DEVICE_ERROR - The device had an error and could not complete the
4093 request, or the device does not support changing
4095 EFI_UNSUPPORTED - The output device is not in a valid text mode.
4100 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4102 EFI_STATUS ReturnStatus
;
4104 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4107 // return the worst status met
4109 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4111 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4112 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
4113 Private
->TextOutList
[Index
].TextOut
,
4116 if (EFI_ERROR (Status
)) {
4117 ReturnStatus
= Status
;
4122 DevNullTextOutEnableCursor (Private
, Visible
);
4124 return ReturnStatus
;