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
,
80 ConSplitterAbsolutePointerReset
,
81 ConSplitterAbsolutePointerGetState
,
83 (EFI_ABSOLUTE_POINTER_MODE
*) NULL
90 0x10000, //AbsoluteMaxX
91 0x10000, //AbsoluteMaxY
92 0x10000, //AbsoluteMaxZ
96 (EFI_ABSOLUTE_POINTER_PROTOCOL
**) NULL
,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
120 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL gUgaDrawProtocolTemplate
= {
121 ConSpliterUgaDrawGetMode
,
122 ConSpliterUgaDrawSetMode
,
126 GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL gGraphicsOutputProtocolTemplate
= {
127 ConSpliterGraphicsOutputQueryMode
,
128 ConSpliterGraphicsOutputSetMode
,
129 ConSpliterGraphicsOutputBlt
,
133 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
134 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
137 ConSplitterTextOutReset
,
138 ConSplitterTextOutOutputString
,
139 ConSplitterTextOutTestString
,
140 ConSplitterTextOutQueryMode
,
141 ConSplitterTextOutSetMode
,
142 ConSplitterTextOutSetAttribute
,
143 ConSplitterTextOutClearScreen
,
144 ConSplitterTextOutSetCursorPosition
,
145 ConSplitterTextOutEnableCursor
,
146 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
165 (EFI_UGA_PIXEL
*) NULL
,
172 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
173 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) NULL
,
178 ConSpliterConsoleControlGetMode
,
179 ConSpliterConsoleControlSetMode
,
180 ConSpliterConsoleControlLockStdIn
184 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
186 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
190 EfiConsoleControlScreenText
,
197 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
198 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
201 ConSplitterTextOutReset
,
202 ConSplitterTextOutOutputString
,
203 ConSplitterTextOutTestString
,
204 ConSplitterTextOutQueryMode
,
205 ConSplitterTextOutSetMode
,
206 ConSplitterTextOutSetAttribute
,
207 ConSplitterTextOutClearScreen
,
208 ConSplitterTextOutSetCursorPosition
,
209 ConSplitterTextOutEnableCursor
,
210 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
229 (EFI_UGA_PIXEL
*) NULL
,
236 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
237 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) NULL
,
242 ConSpliterConsoleControlGetMode
,
243 ConSpliterConsoleControlSetMode
,
244 ConSpliterConsoleControlLockStdIn
248 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
250 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
254 EfiConsoleControlScreenText
,
261 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
262 ConSplitterConInDriverBindingSupported
,
263 ConSplitterConInDriverBindingStart
,
264 ConSplitterConInDriverBindingStop
,
270 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
271 ConSplitterSimplePointerDriverBindingSupported
,
272 ConSplitterSimplePointerDriverBindingStart
,
273 ConSplitterSimplePointerDriverBindingStop
,
280 // Driver binding instance for Absolute Pointer protocol
282 EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding
= {
283 ConSplitterAbsolutePointerDriverBindingSupported
,
284 ConSplitterAbsolutePointerDriverBindingStart
,
285 ConSplitterAbsolutePointerDriverBindingStop
,
291 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
292 ConSplitterConOutDriverBindingSupported
,
293 ConSplitterConOutDriverBindingStart
,
294 ConSplitterConOutDriverBindingStop
,
300 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
301 ConSplitterStdErrDriverBindingSupported
,
302 ConSplitterStdErrDriverBindingStart
,
303 ConSplitterStdErrDriverBindingStop
,
310 The user Entry Point for module ConSplitter. The user code starts with this function.
312 @param[in] ImageHandle The firmware allocated handle for the EFI image.
313 @param[in] SystemTable A pointer to the EFI System Table.
315 @retval EFI_SUCCESS The entry point is executed successfully.
316 @retval other Some error occurs when executing this entry point.
321 InitializeConSplitter(
322 IN EFI_HANDLE ImageHandle
,
323 IN EFI_SYSTEM_TABLE
*SystemTable
329 // Install driver model protocol(s).
331 Status
= EfiLibInstallDriverBindingComponentName2 (
334 &gConSplitterConInDriverBinding
,
336 &gConSplitterConInComponentName
,
337 &gConSplitterConInComponentName2
339 ASSERT_EFI_ERROR (Status
);
341 Status
= EfiLibInstallDriverBindingComponentName2 (
344 &gConSplitterSimplePointerDriverBinding
,
346 &gConSplitterSimplePointerComponentName
,
347 &gConSplitterSimplePointerComponentName2
349 ASSERT_EFI_ERROR (Status
);
351 Status
= EfiLibInstallDriverBindingComponentName2 (
354 &gConSplitterAbsolutePointerDriverBinding
,
356 &gConSplitterAbsolutePointerComponentName
,
357 &gConSplitterAbsolutePointerComponentName2
359 ASSERT_EFI_ERROR (Status
);
361 Status
= EfiLibInstallDriverBindingComponentName2 (
364 &gConSplitterConOutDriverBinding
,
366 &gConSplitterConOutComponentName
,
367 &gConSplitterConOutComponentName2
369 ASSERT_EFI_ERROR (Status
);
371 Status
= EfiLibInstallDriverBindingComponentName2 (
374 &gConSplitterStdErrDriverBinding
,
376 &gConSplitterStdErrComponentName
,
377 &gConSplitterStdErrComponentName2
379 ASSERT_EFI_ERROR (Status
);
383 // Call the original Entry Point
385 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
393 ConSplitterDriverEntry (
394 IN EFI_HANDLE ImageHandle
,
395 IN EFI_SYSTEM_TABLE
*SystemTable
400 Intialize a virtual console device to act as an agrigator of physical console
404 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
405 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
413 ASSERT (FeaturePcdGet (PcdConOutGopSupport
) ||
414 FeaturePcdGet (PcdConOutUgaSupport
));
416 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
417 // The virtual handles will always exist even if no console exist in the
418 // system. This is need to support hotplug devices like USB.
421 // Create virtual device handle for StdErr Splitter
423 Status
= ConSplitterTextOutConstructor (&mStdErr
);
424 if (!EFI_ERROR (Status
)) {
425 Status
= gBS
->InstallMultipleProtocolInterfaces (
426 &mStdErr
.VirtualHandle
,
427 &gEfiSimpleTextOutProtocolGuid
,
429 &gEfiPrimaryStandardErrorDeviceGuid
,
435 // Create virtual device handle for ConIn Splitter
437 Status
= ConSplitterTextInConstructor (&mConIn
);
438 if (!EFI_ERROR (Status
)) {
439 Status
= gBS
->InstallMultipleProtocolInterfaces (
440 &mConIn
.VirtualHandle
,
441 &gEfiSimpleTextInProtocolGuid
,
443 &gEfiSimpleTextInputExProtocolGuid
,
445 &gEfiSimplePointerProtocolGuid
,
446 &mConIn
.SimplePointer
,
447 &gEfiAbsolutePointerProtocolGuid
,
448 &mConIn
.AbsolutePointer
,
449 &gEfiPrimaryConsoleInDeviceGuid
,
453 if (!EFI_ERROR (Status
)) {
455 // Update the EFI System Table with new virtual console
457 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
458 gST
->ConIn
= &mConIn
.TextIn
;
462 // Create virtual device handle for ConOut Splitter
464 Status
= ConSplitterTextOutConstructor (&mConOut
);
465 if (!EFI_ERROR (Status
)) {
466 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
468 // In EFI mode, UGA Draw protocol is installed
470 Status
= gBS
->InstallMultipleProtocolInterfaces (
471 &mConOut
.VirtualHandle
,
472 &gEfiSimpleTextOutProtocolGuid
,
474 &gEfiUgaDrawProtocolGuid
,
476 &gEfiConsoleControlProtocolGuid
,
477 &mConOut
.ConsoleControl
,
478 &gEfiPrimaryConsoleOutDeviceGuid
,
482 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
484 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
486 Status
= gBS
->InstallMultipleProtocolInterfaces (
487 &mConOut
.VirtualHandle
,
488 &gEfiSimpleTextOutProtocolGuid
,
490 &gEfiGraphicsOutputProtocolGuid
,
491 &mConOut
.GraphicsOutput
,
492 &gEfiConsoleControlProtocolGuid
,
493 &mConOut
.ConsoleControl
,
494 &gEfiPrimaryConsoleOutDeviceGuid
,
500 // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are
501 // installed on virtual handle.
503 Status
= gBS
->InstallMultipleProtocolInterfaces (
504 &mConOut
.VirtualHandle
,
505 &gEfiSimpleTextOutProtocolGuid
,
507 &gEfiGraphicsOutputProtocolGuid
,
508 &mConOut
.GraphicsOutput
,
509 &gEfiUgaDrawProtocolGuid
,
511 &gEfiConsoleControlProtocolGuid
,
512 &mConOut
.ConsoleControl
,
513 &gEfiPrimaryConsoleOutDeviceGuid
,
519 if (!EFI_ERROR (Status
)) {
521 // Update the EFI System Table with new virtual console
523 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
524 gST
->ConOut
= &mConOut
.TextOut
;
529 // Update the CRC32 in the EFI System Table header
532 gBS
->CalculateCrc32 (
542 ConSplitterTextInConstructor (
543 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
549 Construct the ConSplitter.
553 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
556 EFI_OUT_OF_RESOURCES - Out of resources.
563 // Initilize console input splitter's private data.
565 Status
= ConSplitterGrowBuffer (
566 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
567 &ConInPrivate
->TextInListCount
,
568 (VOID
**) &ConInPrivate
->TextInList
570 if (EFI_ERROR (Status
)) {
571 return EFI_OUT_OF_RESOURCES
;
574 // Create Event to support locking StdIn Device
576 Status
= gBS
->CreateEvent (
577 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
579 ConSpliterConsoleControlLockStdInEvent
,
581 &ConInPrivate
->LockEvent
583 ASSERT_EFI_ERROR (Status
);
585 Status
= gBS
->CreateEvent (
588 ConSplitterTextInWaitForKey
,
590 &ConInPrivate
->TextIn
.WaitForKey
592 ASSERT_EFI_ERROR (Status
);
595 // Buffer for Simple Text Input Ex Protocol
597 Status
= ConSplitterGrowBuffer (
598 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
599 &ConInPrivate
->TextInExListCount
,
600 (VOID
**) &ConInPrivate
->TextInExList
602 if (EFI_ERROR (Status
)) {
603 return EFI_OUT_OF_RESOURCES
;
606 Status
= gBS
->CreateEvent (
609 ConSplitterTextInWaitForKey
,
611 &ConInPrivate
->TextInEx
.WaitForKeyEx
613 ASSERT_EFI_ERROR (Status
);
615 InitializeListHead (&ConInPrivate
->NotifyList
);
618 // Allocate Buffer and Create Event for Absolute Pointer and Simple Pointer Protocols
620 ConInPrivate
->AbsolutePointer
.Mode
= &ConInPrivate
->AbsolutePointerMode
;
622 Status
= ConSplitterGrowBuffer (
623 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
624 &ConInPrivate
->AbsolutePointerListCount
,
625 (VOID
**) &ConInPrivate
->AbsolutePointerList
627 if (EFI_ERROR (Status
)) {
628 return EFI_OUT_OF_RESOURCES
;
631 Status
= gBS
->CreateEvent (
634 ConSplitterAbsolutePointerWaitForInput
,
636 &ConInPrivate
->AbsolutePointer
.WaitForInput
638 ASSERT_EFI_ERROR (Status
);
640 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
642 Status
= ConSplitterGrowBuffer (
643 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
644 &ConInPrivate
->PointerListCount
,
645 (VOID
**) &ConInPrivate
->PointerList
647 if (EFI_ERROR (Status
)) {
648 return EFI_OUT_OF_RESOURCES
;
651 Status
= gBS
->CreateEvent (
654 ConSplitterSimplePointerWaitForInput
,
656 &ConInPrivate
->SimplePointer
.WaitForInput
663 ConSplitterTextOutConstructor (
664 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
668 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
671 // Copy protocols template
673 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
674 CopyMem (&ConOutPrivate
->UgaDraw
, &gUgaDrawProtocolTemplate
, sizeof (EFI_UGA_DRAW_PROTOCOL
));
677 if (FeaturePcdGet (PcdConOutGopSupport
)) {
678 CopyMem (&ConOutPrivate
->GraphicsOutput
, &gGraphicsOutputProtocolTemplate
, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL
));
682 // Initilize console output splitter's private data.
684 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
687 // When new console device is added, the new mode will be set later,
688 // so put current mode back to init state.
690 ConOutPrivate
->TextOutMode
.Mode
= 0xFF;
692 Status
= ConSplitterGrowBuffer (
693 sizeof (TEXT_OUT_AND_GOP_DATA
),
694 &ConOutPrivate
->TextOutListCount
,
695 (VOID
**) &ConOutPrivate
->TextOutList
697 if (EFI_ERROR (Status
)) {
698 return EFI_OUT_OF_RESOURCES
;
701 Status
= ConSplitterGrowBuffer (
702 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
703 &ConOutPrivate
->TextOutQueryDataCount
,
704 (VOID
**) &ConOutPrivate
->TextOutQueryData
706 if (EFI_ERROR (Status
)) {
707 return EFI_OUT_OF_RESOURCES
;
710 // Setup the DevNullTextOut console to 80 x 25
712 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
713 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
714 DevNullTextOutSetMode (ConOutPrivate
, 0);
716 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
718 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
720 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
722 if (FeaturePcdGet (PcdConOutGopSupport
)) {
724 // Setup resource for mode information in Graphics Output Protocol interface
726 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
727 return EFI_OUT_OF_RESOURCES
;
729 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
730 return EFI_OUT_OF_RESOURCES
;
733 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
734 // DevNull will be updated to user-defined mode after driver has started.
736 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
737 return EFI_OUT_OF_RESOURCES
;
739 Info
= &ConOutPrivate
->GraphicsOutputModeBuffer
[0];
741 Info
->HorizontalResolution
= 800;
742 Info
->VerticalResolution
= 600;
743 Info
->PixelFormat
= PixelBltOnly
;
744 Info
->PixelsPerScanLine
= 800;
745 CopyMem (ConOutPrivate
->GraphicsOutput
.Mode
->Info
, Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
746 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
749 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
750 // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
752 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
753 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
755 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
757 // Initial current mode to unknow state, and then set to mode 0
759 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
760 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
768 ConSplitterSupported (
769 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
770 IN EFI_HANDLE ControllerHandle
,
776 Generic Supported Check
779 This - Pointer to protocol.
780 ControllerHandle - Controller Handle.
785 EFI_UNSUPPORTED - unsupported.
786 EFI_SUCCESS - operation is OK.
794 // Make sure the Console Splitter does not attempt to attach to itself
796 if (ControllerHandle
== mConIn
.VirtualHandle
) {
797 return EFI_UNSUPPORTED
;
800 if (ControllerHandle
== mConOut
.VirtualHandle
) {
801 return EFI_UNSUPPORTED
;
804 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
805 return EFI_UNSUPPORTED
;
808 // Check to see whether the handle has the ConsoleInDevice GUID on it
810 Status
= gBS
->OpenProtocol (
814 This
->DriverBindingHandle
,
816 EFI_OPEN_PROTOCOL_BY_DRIVER
819 if (EFI_ERROR (Status
)) {
826 This
->DriverBindingHandle
,
835 ConSplitterConInDriverBindingSupported (
836 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
837 IN EFI_HANDLE ControllerHandle
,
838 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
843 Console In Supported Check
846 This - Pointer to protocol.
847 ControllerHandle - Controller handle.
848 RemainingDevicePath - Remaining device path.
856 return ConSplitterSupported (
859 &gEfiConsoleInDeviceGuid
865 ConSplitterSimplePointerDriverBindingSupported (
866 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
867 IN EFI_HANDLE ControllerHandle
,
868 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
873 Standard Error Supported Check
876 This - Pointer to protocol.
877 ControllerHandle - Controller handle.
878 RemainingDevicePath - Remaining device path.
886 return ConSplitterSupported (
889 &gEfiSimplePointerProtocolGuid
895 ConSplitterAbsolutePointerDriverBindingSupported (
896 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
897 IN EFI_HANDLE ControllerHandle
,
898 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
903 Absolute Pointer Supported Check
906 This - Pointer to protocol.
907 ControllerHandle - Controller handle.
908 RemainingDevicePath - Remaining device path.
916 return ConSplitterSupported (
919 &gEfiAbsolutePointerProtocolGuid
925 ConSplitterConOutDriverBindingSupported (
926 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
927 IN EFI_HANDLE ControllerHandle
,
928 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
933 Console Out Supported Check
936 This - Pointer to protocol.
937 ControllerHandle - Controller handle.
938 RemainingDevicePath - Remaining device path.
946 return ConSplitterSupported (
949 &gEfiConsoleOutDeviceGuid
955 ConSplitterStdErrDriverBindingSupported (
956 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
957 IN EFI_HANDLE ControllerHandle
,
958 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
963 Standard Error Supported Check
966 This - Pointer to protocol.
967 ControllerHandle - Controller handle.
968 RemainingDevicePath - Remaining device path.
976 return ConSplitterSupported (
979 &gEfiStandardErrorDeviceGuid
987 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
988 IN EFI_HANDLE ControllerHandle
,
989 IN EFI_HANDLE ConSplitterVirtualHandle
,
990 IN EFI_GUID
*DeviceGuid
,
991 IN EFI_GUID
*InterfaceGuid
,
997 Start ConSplitter on ControllerHandle, and create the virtual
998 agrogated console device on first call Start for a SimpleTextIn handle.
1001 (Standard DriverBinding Protocol Start() function)
1004 EFI_ERROR if a SimpleTextIn protocol is not started.
1012 // Check to see whether the handle has the ConsoleInDevice GUID on it
1014 Status
= gBS
->OpenProtocol (
1018 This
->DriverBindingHandle
,
1020 EFI_OPEN_PROTOCOL_BY_DRIVER
1022 if (EFI_ERROR (Status
)) {
1026 Status
= gBS
->OpenProtocol (
1030 This
->DriverBindingHandle
,
1031 ConSplitterVirtualHandle
,
1032 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1034 if (EFI_ERROR (Status
)) {
1038 return gBS
->OpenProtocol (
1042 This
->DriverBindingHandle
,
1043 ConSplitterVirtualHandle
,
1044 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1050 ConSplitterConInDriverBindingStart (
1051 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1052 IN EFI_HANDLE ControllerHandle
,
1053 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1057 Routine Description:
1058 Start ConSplitter on ControllerHandle, and create the virtual
1059 agrogated console device on first call Start for a SimpleTextIn handle.
1062 This - Pointer to protocol.
1063 ControllerHandle - Controller handle.
1064 RemainingDevicePath - Remaining device path.
1069 EFI_ERROR if a SimpleTextIn protocol is not started.
1074 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1075 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1078 // Start ConSplitter on ControllerHandle, and create the virtual
1079 // agrogated console device on first call Start for a SimpleTextIn handle.
1081 Status
= ConSplitterStart (
1084 mConIn
.VirtualHandle
,
1085 &gEfiConsoleInDeviceGuid
,
1086 &gEfiSimpleTextInProtocolGuid
,
1089 if (EFI_ERROR (Status
)) {
1093 Status
= ConSplitterTextInAddDevice (&mConIn
, TextIn
);
1094 if (EFI_ERROR (Status
)) {
1098 Status
= gBS
->OpenProtocol (
1100 &gEfiSimpleTextInputExProtocolGuid
,
1101 (VOID
**) &TextInEx
,
1102 This
->DriverBindingHandle
,
1103 mConIn
.VirtualHandle
,
1104 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1106 if (EFI_ERROR (Status
)) {
1110 Status
= ConSplitterTextInExAddDevice (&mConIn
, TextInEx
);
1117 ConSplitterSimplePointerDriverBindingStart (
1118 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1119 IN EFI_HANDLE ControllerHandle
,
1120 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1124 Routine Description:
1125 Start ConSplitter on ControllerHandle, and create the virtual
1126 agrogated console device on first call Start for a SimpleTextIn handle.
1129 This - Pointer to protocol.
1130 ControllerHandle - Controller handle.
1131 RemainingDevicePath - Remaining device path.
1135 EFI_ERROR if a SimpleTextIn protocol is not started.
1140 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1142 Status
= ConSplitterStart (
1145 mConIn
.VirtualHandle
,
1146 &gEfiSimplePointerProtocolGuid
,
1147 &gEfiSimplePointerProtocolGuid
,
1148 (VOID
**) &SimplePointer
1150 if (EFI_ERROR (Status
)) {
1154 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
1159 ConSplitterAbsolutePointerDriverBindingStart (
1160 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1161 IN EFI_HANDLE ControllerHandle
,
1162 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1166 Routine Description:
1167 Start ConSplitter on ControllerHandle, and create the virtual
1168 agrogated console device on first call Start for a ConIn handle.
1171 This - Pointer to protocol.
1172 ControllerHandle - Controller handle.
1173 RemainingDevicePath - Remaining device path.
1177 EFI_ERROR if a AbsolutePointer protocol is not started.
1182 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1184 Status
= ConSplitterStart (
1187 mConIn
.VirtualHandle
,
1188 &gEfiAbsolutePointerProtocolGuid
,
1189 &gEfiAbsolutePointerProtocolGuid
,
1190 (VOID
**) &AbsolutePointer
1193 if (EFI_ERROR (Status
)) {
1197 return ConSplitterAbsolutePointerAddDevice (&mConIn
, AbsolutePointer
);
1202 ConSplitterConOutDriverBindingStart (
1203 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1204 IN EFI_HANDLE ControllerHandle
,
1205 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1209 Routine Description:
1210 Start ConSplitter on ControllerHandle, and create the virtual
1211 agrogated console device on first call Start for a SimpleTextIn handle.
1214 This - Pointer to protocol.
1215 ControllerHandle - Controller handle.
1216 RemainingDevicePath - Remaining device path.
1219 EFI_ERROR if a SimpleTextIn protocol is not started.
1224 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1225 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1226 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1228 Status
= ConSplitterStart (
1231 mConOut
.VirtualHandle
,
1232 &gEfiConsoleOutDeviceGuid
,
1233 &gEfiSimpleTextOutProtocolGuid
,
1236 if (EFI_ERROR (Status
)) {
1240 GraphicsOutput
= NULL
;
1243 // Try to Open Graphics Output protocol
1245 Status
= gBS
->OpenProtocol (
1247 &gEfiGraphicsOutputProtocolGuid
,
1248 (VOID
**) &GraphicsOutput
,
1249 This
->DriverBindingHandle
,
1250 mConOut
.VirtualHandle
,
1251 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1254 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
1256 // Open UGA_DRAW protocol
1258 Status
= gBS
->OpenProtocol (
1260 &gEfiUgaDrawProtocolGuid
,
1262 This
->DriverBindingHandle
,
1263 mConOut
.VirtualHandle
,
1264 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1269 // When new console device is added, the new mode will be set later,
1270 // so put current mode back to init state.
1272 mConOut
.TextOutMode
.Mode
= 0xFF;
1275 // If both ConOut and StdErr incorporate the same Text Out device,
1276 // their MaxMode and QueryData should be the intersection of both.
1278 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1279 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1281 if (FeaturePcdGet (PcdConOutUgaSupport
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
1283 // Match the UGA mode data of ConOut with the current mode
1285 if (UgaDraw
!= NULL
) {
1288 &mConOut
.UgaHorizontalResolution
,
1289 &mConOut
.UgaVerticalResolution
,
1290 &mConOut
.UgaColorDepth
,
1291 &mConOut
.UgaRefreshRate
1300 ConSplitterStdErrDriverBindingStart (
1301 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1302 IN EFI_HANDLE ControllerHandle
,
1303 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1307 Routine Description:
1308 Start ConSplitter on ControllerHandle, and create the virtual
1309 agrogated console device on first call Start for a SimpleTextIn handle.
1312 This - Pointer to protocol.
1313 ControllerHandle - Controller handle.
1314 RemainingDevicePath - Remaining device path.
1317 EFI_ERROR if a SimpleTextIn protocol is not started.
1322 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1324 Status
= ConSplitterStart (
1327 mStdErr
.VirtualHandle
,
1328 &gEfiStandardErrorDeviceGuid
,
1329 &gEfiSimpleTextOutProtocolGuid
,
1332 if (EFI_ERROR (Status
)) {
1337 // When new console device is added, the new mode will be set later,
1338 // so put current mode back to init state.
1340 mStdErr
.TextOutMode
.Mode
= 0xFF;
1343 // If both ConOut and StdErr incorporate the same Text Out device,
1344 // their MaxMode and QueryData should be the intersection of both.
1346 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1347 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1348 if (EFI_ERROR (Status
)) {
1352 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1353 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1354 gST
->StdErr
= &mStdErr
.TextOut
;
1356 // Update the CRC32 in the EFI System Table header
1359 gBS
->CalculateCrc32 (
1360 (UINT8
*) &gST
->Hdr
,
1361 gST
->Hdr
.HeaderSize
,
1373 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1374 IN EFI_HANDLE ControllerHandle
,
1375 IN EFI_HANDLE ConSplitterVirtualHandle
,
1376 IN EFI_GUID
*DeviceGuid
,
1377 IN EFI_GUID
*InterfaceGuid
,
1382 Routine Description:
1385 (Standard DriverBinding Protocol Stop() function)
1395 Status
= gBS
->OpenProtocol (
1399 This
->DriverBindingHandle
,
1401 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1403 if (EFI_ERROR (Status
)) {
1407 // close the protocol refered.
1409 gBS
->CloseProtocol (
1412 This
->DriverBindingHandle
,
1413 ConSplitterVirtualHandle
1415 gBS
->CloseProtocol (
1418 This
->DriverBindingHandle
,
1427 ConSplitterConInDriverBindingStop (
1428 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1429 IN EFI_HANDLE ControllerHandle
,
1430 IN UINTN NumberOfChildren
,
1431 IN EFI_HANDLE
*ChildHandleBuffer
1435 Routine Description:
1438 (Standard DriverBinding Protocol Stop() function)
1447 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1449 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1450 if (NumberOfChildren
== 0) {
1454 Status
= gBS
->OpenProtocol (
1456 &gEfiSimpleTextInputExProtocolGuid
,
1457 (VOID
**) &TextInEx
,
1458 This
->DriverBindingHandle
,
1460 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1462 if (EFI_ERROR (Status
)) {
1466 Status
= ConSplitterTextInExDeleteDevice (&mConIn
, TextInEx
);
1467 if (EFI_ERROR (Status
)) {
1472 Status
= ConSplitterStop (
1475 mConIn
.VirtualHandle
,
1476 &gEfiConsoleInDeviceGuid
,
1477 &gEfiSimpleTextInProtocolGuid
,
1480 if (EFI_ERROR (Status
)) {
1484 // Delete this console input device's data structures.
1486 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1491 ConSplitterSimplePointerDriverBindingStop (
1492 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1493 IN EFI_HANDLE ControllerHandle
,
1494 IN UINTN NumberOfChildren
,
1495 IN EFI_HANDLE
*ChildHandleBuffer
1499 Routine Description:
1502 (Standard DriverBinding Protocol Stop() function)
1511 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1513 if (NumberOfChildren
== 0) {
1517 Status
= ConSplitterStop (
1520 mConIn
.VirtualHandle
,
1521 &gEfiSimplePointerProtocolGuid
,
1522 &gEfiSimplePointerProtocolGuid
,
1523 (VOID
**) &SimplePointer
1525 if (EFI_ERROR (Status
)) {
1529 // Delete this console input device's data structures.
1531 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1536 ConSplitterAbsolutePointerDriverBindingStop (
1537 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1538 IN EFI_HANDLE ControllerHandle
,
1539 IN UINTN NumberOfChildren
,
1540 IN EFI_HANDLE
*ChildHandleBuffer
1544 Routine Description:
1547 (Standard DriverBinding Protocol Stop() function)
1556 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1558 if (NumberOfChildren
== 0) {
1562 Status
= ConSplitterStop (
1565 mConIn
.VirtualHandle
,
1566 &gEfiAbsolutePointerProtocolGuid
,
1567 &gEfiAbsolutePointerProtocolGuid
,
1568 (VOID
**) &AbsolutePointer
1570 if (EFI_ERROR (Status
)) {
1574 // Delete this console input device's data structures.
1576 return ConSplitterAbsolutePointerDeleteDevice (&mConIn
, AbsolutePointer
);
1581 ConSplitterConOutDriverBindingStop (
1582 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1583 IN EFI_HANDLE ControllerHandle
,
1584 IN UINTN NumberOfChildren
,
1585 IN EFI_HANDLE
*ChildHandleBuffer
1589 Routine Description:
1592 (Standard DriverBinding Protocol Stop() function)
1601 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1603 if (NumberOfChildren
== 0) {
1607 Status
= ConSplitterStop (
1610 mConOut
.VirtualHandle
,
1611 &gEfiConsoleOutDeviceGuid
,
1612 &gEfiSimpleTextOutProtocolGuid
,
1615 if (EFI_ERROR (Status
)) {
1620 // Delete this console output device's data structures.
1622 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1627 ConSplitterStdErrDriverBindingStop (
1628 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1629 IN EFI_HANDLE ControllerHandle
,
1630 IN UINTN NumberOfChildren
,
1631 IN EFI_HANDLE
*ChildHandleBuffer
1635 Routine Description:
1638 (Standard DriverBinding Protocol Stop() function)
1642 EFI_SUCCESS - Complete successfully.
1647 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1649 if (NumberOfChildren
== 0) {
1653 Status
= ConSplitterStop (
1656 mStdErr
.VirtualHandle
,
1657 &gEfiStandardErrorDeviceGuid
,
1658 &gEfiSimpleTextOutProtocolGuid
,
1661 if (EFI_ERROR (Status
)) {
1665 // Delete this console error out device's data structures.
1667 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1668 if (EFI_ERROR (Status
)) {
1672 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1673 gST
->StandardErrorHandle
= NULL
;
1676 // Update the CRC32 in the EFI System Table header
1679 gBS
->CalculateCrc32 (
1680 (UINT8
*) &gST
->Hdr
,
1681 gST
->Hdr
.HeaderSize
,
1690 ConSplitterGrowBuffer (
1691 IN UINTN SizeOfCount
,
1693 IN OUT VOID
**Buffer
1697 Routine Description:
1698 Take the passed in Buffer of size SizeOfCount and grow the buffer
1699 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1700 bytes. Copy the current data in Buffer to the new version of Buffer
1701 and free the old version of buffer.
1705 SizeOfCount - Size of element in array
1706 Count - Current number of elements in array
1707 Buffer - Bigger version of passed in Buffer with all the data
1710 EFI_SUCCESS - Buffer size has grown
1711 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1722 // grow the buffer to new buffer size,
1723 // copy the old buffer's content to the new-size buffer,
1724 // then free the old buffer.
1726 OldSize
= *Count
* SizeOfCount
;
1727 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1728 NewSize
= *Count
* SizeOfCount
;
1730 Ptr
= AllocateZeroPool (NewSize
);
1732 return EFI_OUT_OF_RESOURCES
;
1735 CopyMem (Ptr
, *Buffer
, OldSize
);
1737 if (*Buffer
!= NULL
) {
1747 ConSplitterTextInAddDevice (
1748 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1749 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1753 Routine Description:
1760 EFI_OUT_OF_RESOURCES
1767 // If the Text In List is full, enlarge it by calling growbuffer().
1769 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1770 Status
= ConSplitterGrowBuffer (
1771 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1772 &Private
->TextInListCount
,
1773 (VOID
**) &Private
->TextInList
1775 if (EFI_ERROR (Status
)) {
1776 return EFI_OUT_OF_RESOURCES
;
1780 // Add the new text-in device data structure into the Text In List.
1782 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1783 Private
->CurrentNumberOfConsoles
++;
1786 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1788 gBS
->CheckEvent (TextIn
->WaitForKey
);
1794 ConSplitterTextInDeleteDevice (
1795 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1796 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1800 Routine Description:
1813 // Remove the specified text-in device data structure from the Text In List,
1814 // and rearrange the remaining data structures in the Text In List.
1816 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1817 if (Private
->TextInList
[Index
] == TextIn
) {
1818 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1819 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1822 Private
->CurrentNumberOfConsoles
--;
1827 return EFI_NOT_FOUND
;
1831 ConSplitterTextInExAddDevice (
1832 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1833 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1839 // If the TextInEx List is full, enlarge it by calling growbuffer().
1841 if (Private
->CurrentNumberOfExConsoles
>= Private
->TextInExListCount
) {
1842 Status
= ConSplitterGrowBuffer (
1843 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
1844 &Private
->TextInExListCount
,
1845 (VOID
**) &Private
->TextInExList
1847 if (EFI_ERROR (Status
)) {
1848 return EFI_OUT_OF_RESOURCES
;
1852 // Add the new text-in device data structure into the Text In List.
1854 Private
->TextInExList
[Private
->CurrentNumberOfExConsoles
] = TextInEx
;
1855 Private
->CurrentNumberOfExConsoles
++;
1858 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1860 gBS
->CheckEvent (TextInEx
->WaitForKeyEx
);
1866 ConSplitterTextInExDeleteDevice (
1867 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1868 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1873 // Remove the specified text-in device data structure from the Text In List,
1874 // and rearrange the remaining data structures in the Text In List.
1876 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
1877 if (Private
->TextInExList
[Index
] == TextInEx
) {
1878 for (Index
= Index
; Index
< Private
->CurrentNumberOfExConsoles
- 1; Index
++) {
1879 Private
->TextInExList
[Index
] = Private
->TextInExList
[Index
+ 1];
1882 Private
->CurrentNumberOfExConsoles
--;
1887 return EFI_NOT_FOUND
;
1891 ConSplitterSimplePointerAddDevice (
1892 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1893 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1897 Routine Description:
1903 EFI_OUT_OF_RESOURCES
1911 // If the Text In List is full, enlarge it by calling growbuffer().
1913 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1914 Status
= ConSplitterGrowBuffer (
1915 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1916 &Private
->PointerListCount
,
1917 (VOID
**) &Private
->PointerList
1919 if (EFI_ERROR (Status
)) {
1920 return EFI_OUT_OF_RESOURCES
;
1924 // Add the new text-in device data structure into the Text In List.
1926 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1927 Private
->CurrentNumberOfPointers
++;
1932 ConSplitterSimplePointerDeleteDevice (
1933 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1934 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1938 Routine Description:
1950 // Remove the specified text-in device data structure from the Text In List,
1951 // and rearrange the remaining data structures in the Text In List.
1953 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1954 if (Private
->PointerList
[Index
] == SimplePointer
) {
1955 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1956 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1959 Private
->CurrentNumberOfPointers
--;
1964 return EFI_NOT_FOUND
;
1968 ConSplitterAbsolutePointerAddDevice (
1969 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1970 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
1974 Routine Description:
1980 EFI_OUT_OF_RESOURCES
1988 // If the Absolute Pointer List is full, enlarge it by calling growbuffer().
1990 if (Private
->CurrentNumberOfAbsolutePointers
>= Private
->AbsolutePointerListCount
) {
1991 Status
= ConSplitterGrowBuffer (
1992 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
1993 &Private
->AbsolutePointerListCount
,
1994 (VOID
**) &Private
->AbsolutePointerList
1996 if (EFI_ERROR (Status
)) {
1997 return EFI_OUT_OF_RESOURCES
;
2001 // Add the new text-in device data structure into the Text In List.
2003 Private
->AbsolutePointerList
[Private
->CurrentNumberOfAbsolutePointers
] = AbsolutePointer
;
2004 Private
->CurrentNumberOfAbsolutePointers
++;
2009 ConSplitterAbsolutePointerDeleteDevice (
2010 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2011 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
2015 Routine Description:
2027 // Remove the specified text-in device data structure from the Text In List,
2028 // and rearrange the remaining data structures in the Text In List.
2030 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
2031 if (Private
->AbsolutePointerList
[Index
] == AbsolutePointer
) {
2032 for (Index
= Index
; Index
< Private
->CurrentNumberOfAbsolutePointers
- 1; Index
++) {
2033 Private
->AbsolutePointerList
[Index
] = Private
->AbsolutePointerList
[Index
+ 1];
2036 Private
->CurrentNumberOfAbsolutePointers
--;
2041 return EFI_NOT_FOUND
;
2046 ConSplitterGrowMapTable (
2047 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
2051 Routine Description:
2064 INT32
*TextOutModeMap
;
2065 INT32
*OldTextOutModeMap
;
2069 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
2070 OldTextOutModeMap
= Private
->TextOutModeMap
;
2071 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
2073 TextOutModeMap
= AllocateZeroPool (TotalSize
);
2074 if (TextOutModeMap
== NULL
) {
2075 return EFI_OUT_OF_RESOURCES
;
2078 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
2079 Private
->TextOutModeMap
= TextOutModeMap
;
2082 // If TextOutList has been enlarged, need to realloc the mode map table
2083 // The mode map table is regarded as a two dimension array.
2086 // 0 ---------> TextOutListCount ----> TextOutListCount
2087 // | -------------------------------------------
2094 // -------------------------------------------
2097 if (OldTextOutModeMap
!= NULL
) {
2099 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
2101 SrcAddress
= OldTextOutModeMap
;
2104 // Copy the old data to the new one
2106 while (Index
< Private
->TextOutMode
.MaxMode
) {
2107 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
2108 TextOutModeMap
+= NewSize
;
2113 // Free the old buffer
2115 FreePool (OldTextOutModeMap
);
2123 ConSplitterAddOutputMode (
2124 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2125 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2129 Routine Description:
2144 MaxMode
= TextOut
->Mode
->MaxMode
;
2145 Private
->TextOutMode
.MaxMode
= MaxMode
;
2148 // Grow the buffer if query data buffer is not large enough to
2149 // hold all the mode supported by the first console.
2151 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
2152 Status
= ConSplitterGrowBuffer (
2153 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
2154 &Private
->TextOutQueryDataCount
,
2155 (VOID
**) &Private
->TextOutQueryData
2157 if (EFI_ERROR (Status
)) {
2158 return EFI_OUT_OF_RESOURCES
;
2162 // Allocate buffer for the output mode map
2164 Status
= ConSplitterGrowMapTable (Private
);
2165 if (EFI_ERROR (Status
)) {
2166 return EFI_OUT_OF_RESOURCES
;
2169 // As the first textout device, directly add the mode in to QueryData
2170 // and at the same time record the mapping between QueryData and TextOut.
2174 while (Mode
< MaxMode
) {
2175 Status
= TextOut
->QueryMode (
2178 &Private
->TextOutQueryData
[Mode
].Columns
,
2179 &Private
->TextOutQueryData
[Mode
].Rows
2182 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2185 if ((EFI_ERROR(Status
)) && (Mode
== 1)) {
2186 Private
->TextOutQueryData
[Mode
].Columns
= 0;
2187 Private
->TextOutQueryData
[Mode
].Rows
= 0;
2189 Private
->TextOutModeMap
[Index
] = Mode
;
2191 Index
+= Private
->TextOutListCount
;
2198 Reconstruct TextOutModeMap to get intersection of modes
2200 This routine reconstruct TextOutModeMap to get the intersection
2201 of modes for all console out devices. Because EFI/UEFI spec require
2202 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the
2203 intersection for mode 0 and mode 1.
2205 @parm TextOutModeMap Current text out mode map, begin with the mode 80x25
2206 @parm NewlyAddedMap New text out mode map, begin with the mode 80x25
2207 @parm MapStepSize Mode step size for one console device
2208 @parm NewMapStepSize Mode step size for one console device
2209 @parm MaxMode Current max text mode
2210 @parm CurrentMode Current text mode
2217 ConSplitterGetIntersection (
2218 IN INT32
*TextOutModeMap
,
2219 IN INT32
*NewlyAddedMap
,
2220 IN UINTN MapStepSize
,
2221 IN UINTN NewMapStepSize
,
2223 OUT INT32
*CurrentMode
2227 INT32
*CurrentMapEntry
;
2228 INT32
*NextMapEntry
;
2229 INT32 CurrentMaxMode
;
2233 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved
2234 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection
2235 // for mode 0 and mode 1, mode number starts from 2.
2238 CurrentMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2239 NextMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2240 NewlyAddedMap
= &NewlyAddedMap
[NewMapStepSize
* 2];
2242 CurrentMaxMode
= *MaxMode
;
2243 Mode
= *CurrentMode
;
2245 while (Index
< CurrentMaxMode
) {
2246 if (*NewlyAddedMap
== -1) {
2248 // This mode is not supported any more. Remove it. Special care
2249 // must be taken as this remove will also affect current mode;
2251 if (Index
== *CurrentMode
) {
2253 } else if (Index
< *CurrentMode
) {
2258 if (CurrentMapEntry
!= NextMapEntry
) {
2259 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
2262 NextMapEntry
+= MapStepSize
;
2265 CurrentMapEntry
+= MapStepSize
;
2266 NewlyAddedMap
+= NewMapStepSize
;
2270 *CurrentMode
= Mode
;
2277 ConSplitterSyncOutputMode (
2278 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2279 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2283 Routine Description:
2286 Private - Private data structure.
2287 TextOut - Text Out Protocol.
2294 INT32 CurrentMaxMode
;
2297 INT32
*TextOutModeMap
;
2300 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
2307 // Must make sure that current mode won't change even if mode number changes
2309 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
2310 TextOutModeMap
= Private
->TextOutModeMap
;
2311 StepSize
= Private
->TextOutListCount
;
2312 TextOutQueryData
= Private
->TextOutQueryData
;
2315 // Query all the mode that the newly added TextOut supports
2318 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
2319 while (Mode
< TextOut
->Mode
->MaxMode
) {
2320 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
2321 if (EFI_ERROR(Status
)) {
2323 MapTable
[StepSize
] = Mode
;
2324 TextOutQueryData
[Mode
].Columns
= 0;
2325 TextOutQueryData
[Mode
].Rows
= 0;
2331 // Search the intersection map and QueryData database to see if they intersects
2334 while (Index
< CurrentMaxMode
) {
2335 QueryMode
= *(TextOutModeMap
+ Index
* StepSize
);
2336 if ((TextOutQueryData
[QueryMode
].Rows
== Rows
) && (TextOutQueryData
[QueryMode
].Columns
== Columns
)) {
2337 MapTable
[Index
* StepSize
] = Mode
;
2347 // Now search the TextOutModeMap table to find the intersection of supported
2348 // mode between ConSplitter and the newly added device.
2350 ConSplitterGetIntersection (
2355 &Private
->TextOutMode
.MaxMode
,
2356 &Private
->TextOutMode
.Mode
2364 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2369 Routine Description:
2376 EFI_OUT_OF_RESOURCES
2380 UINTN ConOutNumOfConsoles
;
2381 UINTN StdErrNumOfConsoles
;
2382 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
2383 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
2387 UINTN ConOutColumns
;
2389 UINTN StdErrColumns
;
2390 INT32 ConOutMaxMode
;
2391 INT32 StdErrMaxMode
;
2396 INT32
*ConOutModeMap
;
2397 INT32
*StdErrModeMap
;
2398 INT32
*ConOutMapTable
;
2399 INT32
*StdErrMapTable
;
2400 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
2401 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
2402 UINTN ConOutStepSize
;
2403 UINTN StdErrStepSize
;
2404 BOOLEAN FoundTheSameTextOut
;
2405 UINTN ConOutMapTableSize
;
2406 UINTN StdErrMapTableSize
;
2408 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
2409 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
2410 ConOutTextOutList
= mConOut
.TextOutList
;
2411 StdErrTextOutList
= mStdErr
.TextOutList
;
2414 FoundTheSameTextOut
= FALSE
;
2415 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
2417 while (Indexj
< StdErrNumOfConsoles
) {
2418 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
2419 FoundTheSameTextOut
= TRUE
;
2424 StdErrTextOutList
++;
2428 ConOutTextOutList
++;
2431 if (!FoundTheSameTextOut
) {
2435 // Must make sure that current mode won't change even if mode number changes
2437 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
2438 ConOutModeMap
= mConOut
.TextOutModeMap
;
2439 ConOutStepSize
= mConOut
.TextOutListCount
;
2440 ConOutQueryData
= mConOut
.TextOutQueryData
;
2442 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
2443 StdErrModeMap
= mStdErr
.TextOutModeMap
;
2444 StdErrStepSize
= mStdErr
.TextOutListCount
;
2445 StdErrQueryData
= mStdErr
.TextOutQueryData
;
2448 // Allocate the map table and set the map table's index to -1.
2450 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
2451 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
2452 if (ConOutMapTable
== NULL
) {
2453 return EFI_OUT_OF_RESOURCES
;
2456 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
2458 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
2459 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
2460 if (StdErrMapTable
== NULL
) {
2461 return EFI_OUT_OF_RESOURCES
;
2464 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
2467 // Find the intersection of the two set of modes. If they actually intersect, the
2468 // correponding entry in the map table is set to 1.
2471 while (Mode
< ConOutMaxMode
) {
2473 // Search the intersection map and QueryData database to see if they intersect
2476 ConOutMode
= *(ConOutModeMap
+ Mode
* ConOutStepSize
);
2477 ConOutRows
= ConOutQueryData
[ConOutMode
].Rows
;
2478 ConOutColumns
= ConOutQueryData
[ConOutMode
].Columns
;
2479 while (Index
< StdErrMaxMode
) {
2480 StdErrMode
= *(StdErrModeMap
+ Index
* StdErrStepSize
);
2481 StdErrRows
= StdErrQueryData
[StdErrMode
].Rows
;
2482 StdErrColumns
= StdErrQueryData
[StdErrMode
].Columns
;
2483 if ((StdErrRows
== ConOutRows
) && (StdErrColumns
== ConOutColumns
)) {
2484 ConOutMapTable
[Mode
] = 1;
2485 StdErrMapTable
[Index
] = 1;
2495 // Now search the TextOutModeMap table to find the intersection of supported
2496 // mode between ConSplitter and the newly added device.
2498 ConSplitterGetIntersection (
2501 mConOut
.TextOutListCount
,
2503 &(mConOut
.TextOutMode
.MaxMode
),
2504 &(mConOut
.TextOutMode
.Mode
)
2506 if (mConOut
.TextOutMode
.Mode
< 0) {
2507 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2510 ConSplitterGetIntersection (
2513 mStdErr
.TextOutListCount
,
2515 &(mStdErr
.TextOutMode
.MaxMode
),
2516 &(mStdErr
.TextOutMode
.Mode
)
2518 if (mStdErr
.TextOutMode
.Mode
< 0) {
2519 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2522 FreePool (ConOutMapTable
);
2523 FreePool (StdErrMapTable
);
2530 ConSplitterAddGraphicsOutputMode (
2531 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2532 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2533 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2537 Routine Description:
2550 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
2552 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2553 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2554 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*ModeBuffer
;
2555 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*MatchedMode
;
2558 BOOLEAN AlreadyExist
;
2559 UINT32 UgaHorizontalResolution
;
2560 UINT32 UgaVerticalResolution
;
2561 UINT32 UgaColorDepth
;
2562 UINT32 UgaRefreshRate
;
2564 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2565 return EFI_UNSUPPORTED
;
2568 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2573 if (Private
->CurrentNumberOfUgaDraw
!= 0) {
2575 // If any UGA device has already been added, then there is no need to
2576 // calculate intersection of display mode of different GOP/UGA device,
2577 // since only one display mode will be exported (i.e. user-defined mode)
2582 if (GraphicsOutput
!= NULL
) {
2583 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2585 // This is the first Graphics Output device added
2587 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2588 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2589 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2590 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2591 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2592 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2595 // Allocate resource for the private mode buffer
2597 ModeBuffer
= AllocatePool (GraphicsOutput
->Mode
->SizeOfInfo
* GraphicsOutput
->Mode
->MaxMode
);
2598 if (ModeBuffer
== NULL
) {
2599 return EFI_OUT_OF_RESOURCES
;
2601 FreePool (Private
->GraphicsOutputModeBuffer
);
2602 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2605 // Store all supported display modes to the private mode buffer
2608 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2609 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2610 if (EFI_ERROR (Status
)) {
2613 CopyMem (Mode
, Info
, SizeOfInfo
);
2619 // Check intersection of display mode
2621 ModeBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
) * CurrentGraphicsOutputMode
->MaxMode
);
2622 if (ModeBuffer
== NULL
) {
2623 return EFI_OUT_OF_RESOURCES
;
2626 MatchedMode
= ModeBuffer
;
2627 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2628 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2631 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2632 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2633 if (EFI_ERROR (Status
)) {
2636 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2637 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2646 AlreadyExist
= FALSE
;
2648 for (Info
= ModeBuffer
; Info
< MatchedMode
; Info
++) {
2649 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2650 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2651 AlreadyExist
= TRUE
;
2656 if (!AlreadyExist
) {
2657 CopyMem (MatchedMode
, Mode
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2660 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly
2662 MatchedMode
->Version
= 0;
2663 MatchedMode
->PixelFormat
= PixelBltOnly
;
2664 ZeroMem (&MatchedMode
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2674 // Drop the old mode buffer, assign it to a new one
2676 FreePool (Private
->GraphicsOutputModeBuffer
);
2677 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2680 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2682 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2683 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2684 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2685 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2686 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
2687 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2691 // Graphics console driver can ensure the same mode for all GOP devices
2693 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2694 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2695 if ((Mode
->HorizontalResolution
== GraphicsOutput
->Mode
->Info
->HorizontalResolution
) &&
2696 (Mode
->VerticalResolution
== GraphicsOutput
->Mode
->Info
->VerticalResolution
)) {
2697 CurrentIndex
= Index
;
2701 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2703 // if user defined mode is not found, set to default mode 800x600
2705 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2706 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2707 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2708 CurrentIndex
= Index
;
2714 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2716 // Graphics console driver can ensure the same mode for all GOP devices
2717 // so we can get the current mode from this video device
2721 &UgaHorizontalResolution
,
2722 &UgaVerticalResolution
,
2727 CurrentGraphicsOutputMode
->MaxMode
= 1;
2728 Info
= CurrentGraphicsOutputMode
->Info
;
2730 Info
->HorizontalResolution
= UgaHorizontalResolution
;
2731 Info
->VerticalResolution
= UgaVerticalResolution
;
2732 Info
->PixelFormat
= PixelBltOnly
;
2733 Info
->PixelsPerScanLine
= UgaHorizontalResolution
;
2734 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2735 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
2736 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2739 // Update the private mode buffer
2741 CopyMem (&Private
->GraphicsOutputModeBuffer
[0], Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2744 // Only mode 0 is available to be set
2751 if (GraphicsOutput
!= NULL
) {
2752 Private
->CurrentNumberOfGraphicsOutput
++;
2754 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2755 Private
->CurrentNumberOfUgaDraw
++;
2759 // Force GraphicsOutput mode to be set,
2760 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2762 Private
->HardwareNeedsStarting
= TRUE
;
2764 // Current mode number may need update now, so set it to an invalid mode number
2766 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2768 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.
2770 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) CurrentIndex
);
2773 // If user defined mode is not valid for UGA, set to the default mode 800x600.
2775 if (EFI_ERROR(Status
)) {
2776 (Private
->GraphicsOutputModeBuffer
[0]).HorizontalResolution
= 800;
2777 (Private
->GraphicsOutputModeBuffer
[0]).VerticalResolution
= 600;
2778 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, 0);
2785 ConsplitterSetConsoleOutMode (
2786 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
2790 Routine Description:
2792 This routine will get the current console mode information (column, row)
2793 from ConsoleOutMode variable and set it; if the variable does not exist,
2794 set to user defined console mode.
2814 CONSOLE_OUT_MODE
*ModeInfo
;
2815 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
2819 TextOut
= &Private
->TextOut
;
2820 MaxMode
= (UINTN
) (TextOut
->Mode
->MaxMode
);
2821 ModeInfoSize
= sizeof (CONSOLE_OUT_MODE
);
2823 ModeInfo
= AllocateZeroPool (sizeof(CONSOLE_OUT_MODE
));
2824 ASSERT(ModeInfo
!= NULL
);
2826 Status
= gRT
->GetVariable (
2828 &gEfiGenericPlatformVariableGuid
,
2835 // Set to the default mode 80 x 25 required by EFI/UEFI spec;
2836 // user can also define other valid default console mode here.
2838 if (EFI_ERROR(Status
)) {
2839 ModeInfo
->Column
= 80;
2841 Status
= gRT
->SetVariable (
2843 &gEfiGenericPlatformVariableGuid
,
2844 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2845 sizeof (CONSOLE_OUT_MODE
),
2850 for (Mode
= 0; Mode
< MaxMode
; Mode
++) {
2851 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Col
, &Row
);
2852 if (!EFI_ERROR(Status
)) {
2853 if (Col
== ModeInfo
->Column
&& Row
== ModeInfo
->Row
) {
2856 if (Col
== 80 && Row
== 25) {
2862 Status
= TextOut
->SetMode (TextOut
, PreferMode
);
2865 // if current mode setting is failed, default 80x25 mode will be set.
2867 if (EFI_ERROR(Status
)) {
2868 Status
= TextOut
->SetMode (TextOut
, BaseMode
);
2869 ASSERT(!EFI_ERROR(Status
));
2871 ModeInfo
->Column
= 80;
2875 // Update ConOutMode variable
2877 Status
= gRT
->SetVariable (
2879 &gEfiGenericPlatformVariableGuid
,
2880 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2881 sizeof (CONSOLE_OUT_MODE
),
2886 gBS
->FreePool (ModeInfo
);
2891 ConSplitterTextOutAddDevice (
2892 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2893 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2894 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2895 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2899 Routine Description:
2910 UINTN CurrentNumOfConsoles
;
2913 UINT32 UgaHorizontalResolution
;
2914 UINT32 UgaVerticalResolution
;
2915 UINT32 UgaColorDepth
;
2916 UINT32 UgaRefreshRate
;
2917 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2919 Status
= EFI_SUCCESS
;
2920 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2923 // If the Text Out List is full, enlarge it by calling growbuffer().
2925 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2926 Status
= ConSplitterGrowBuffer (
2927 sizeof (TEXT_OUT_AND_GOP_DATA
),
2928 &Private
->TextOutListCount
,
2929 (VOID
**) &Private
->TextOutList
2931 if (EFI_ERROR (Status
)) {
2932 return EFI_OUT_OF_RESOURCES
;
2935 // Also need to reallocate the TextOutModeMap table
2937 Status
= ConSplitterGrowMapTable (Private
);
2938 if (EFI_ERROR (Status
)) {
2939 return EFI_OUT_OF_RESOURCES
;
2943 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2945 TextAndGop
->TextOut
= TextOut
;
2946 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2947 TextAndGop
->UgaDraw
= UgaDraw
;
2949 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2951 // If No GOP/UGA device then use the ConOut device
2953 TextAndGop
->TextOutEnabled
= TRUE
;
2956 // If GOP/UGA device use ConOut device only used if screen is in Text mode
2958 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2961 if (CurrentNumOfConsoles
== 0) {
2963 // Add the first device's output mode to console splitter's mode list
2965 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2967 ConSplitterSyncOutputMode (Private
, TextOut
);
2970 Private
->CurrentNumberOfConsoles
++;
2973 // Scan both TextOutList, for the intersection TextOut device
2974 // maybe both ConOut and StdErr incorporate the same Text Out
2975 // device in them, thus the output of both should be synced.
2977 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2979 CurrentMode
= Private
->TextOutMode
.Mode
;
2980 MaxMode
= Private
->TextOutMode
.MaxMode
;
2981 ASSERT (MaxMode
>= 1);
2984 // Update DevNull mode according to current video device
2986 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2987 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2988 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2991 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2992 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2993 Status
= UgaDraw
->GetMode (
2995 &UgaHorizontalResolution
,
2996 &UgaVerticalResolution
,
3000 if (!EFI_ERROR (Status
)) {
3001 Status
= ConSpliterUgaDrawSetMode (
3003 UgaHorizontalResolution
,
3004 UgaVerticalResolution
,
3010 // If GetMode/SetMode is failed, set to 800x600 mode
3012 if(EFI_ERROR (Status
)) {
3013 Status
= ConSpliterUgaDrawSetMode (
3024 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
3026 // We just added a new GOP or UGA device in graphics mode
3028 if (FeaturePcdGet (PcdConOutGopSupport
)) {
3029 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
3030 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
3031 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
3033 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
3035 // The new console supports the same mode of the current console so sync up
3037 DevNullSyncStdOut (Private
);
3040 // If ConOut, then set the mode to Mode #0 which us 80 x 25
3042 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
3046 // After adding new console device, all existing console devices should be
3047 // synced to the current shared mode.
3049 ConsplitterSetConsoleOutMode (Private
);
3055 ConSplitterTextOutDeleteDevice (
3056 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
3057 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
3061 Routine Description:
3072 UINTN CurrentNumOfConsoles
;
3073 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
3077 // Remove the specified text-out device data structure from the Text out List,
3078 // and rearrange the remaining data structures in the Text out List.
3080 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
3081 Index
= (INT32
) CurrentNumOfConsoles
- 1;
3082 TextOutList
= Private
->TextOutList
;
3083 while (Index
>= 0) {
3084 if (TextOutList
->TextOut
== TextOut
) {
3085 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
3086 CurrentNumOfConsoles
--;
3087 if (TextOutList
->UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
3088 Private
->CurrentNumberOfUgaDraw
--;
3090 if (TextOutList
->GraphicsOutput
!= NULL
) {
3091 Private
->CurrentNumberOfGraphicsOutput
--;
3100 // The specified TextOut is not managed by the ConSplitter driver
3103 return EFI_NOT_FOUND
;
3106 if (CurrentNumOfConsoles
== 0) {
3108 // If the number of consoles is zero clear the Dev NULL device
3110 Private
->CurrentNumberOfConsoles
= 0;
3111 Private
->TextOutMode
.MaxMode
= 1;
3112 Private
->TextOutQueryData
[0].Columns
= 80;
3113 Private
->TextOutQueryData
[0].Rows
= 25;
3114 DevNullTextOutSetMode (Private
, 0);
3119 // Max Mode is realy an intersection of the QueryMode command to all
3120 // devices. So we must copy the QueryMode of the first device to
3124 Private
->TextOutQueryData
,
3125 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
3128 FreePool (Private
->TextOutModeMap
);
3129 Private
->TextOutModeMap
= NULL
;
3130 TextOutList
= Private
->TextOutList
;
3133 // Add the first TextOut to the QueryData array and ModeMap table
3135 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
3138 // Now add one by one
3141 Private
->CurrentNumberOfConsoles
= 1;
3143 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
3144 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
3146 Private
->CurrentNumberOfConsoles
++;
3150 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3155 // ConSplitter TextIn member functions
3159 ConSplitterTextInReset (
3160 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3161 IN BOOLEAN ExtendedVerification
3165 Routine Description:
3166 Reset the input device and optionaly run diagnostics
3169 This - Protocol instance pointer.
3170 ExtendedVerification - Driver may perform diagnostics on reset.
3173 EFI_SUCCESS - The device was reset.
3174 EFI_DEVICE_ERROR - The device is not functioning properly and could
3180 EFI_STATUS ReturnStatus
;
3181 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3184 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3186 Private
->KeyEventSignalState
= FALSE
;
3189 // return the worst status met
3191 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3192 Status
= Private
->TextInList
[Index
]->Reset (
3193 Private
->TextInList
[Index
],
3194 ExtendedVerification
3196 if (EFI_ERROR (Status
)) {
3197 ReturnStatus
= Status
;
3201 return ReturnStatus
;
3206 ConSplitterTextInPrivateReadKeyStroke (
3207 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3208 OUT EFI_INPUT_KEY
*Key
3212 Routine Description:
3213 Reads the next keystroke from the input device. The WaitForKey Event can
3214 be used to test for existance of a keystroke via WaitForEvent () call.
3217 This - Protocol instance pointer.
3218 Key - Driver may perform diagnostics on reset.
3221 EFI_SUCCESS - The keystroke information was returned.
3222 EFI_NOT_READY - There was no keystroke data availiable.
3223 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3230 EFI_INPUT_KEY CurrentKey
;
3232 Key
->UnicodeChar
= 0;
3233 Key
->ScanCode
= SCAN_NULL
;
3236 // if no physical console input device exists, return EFI_NOT_READY;
3237 // if any physical console input device has key input,
3238 // return the key and EFI_SUCCESS.
3240 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3241 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
3242 Private
->TextInList
[Index
],
3245 if (!EFI_ERROR (Status
)) {
3251 return EFI_NOT_READY
;
3255 ConSpliterConssoleControlStdInLocked (
3260 Routine Description:
3261 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
3262 the only device locked.
3269 FALSE - StdIn working normally
3273 return mConIn
.PasswordEnabled
;
3278 ConSpliterConsoleControlLockStdInEvent (
3284 Routine Description:
3285 This timer event will fire when StdIn is locked. It will check the key
3286 sequence on StdIn to see if it matches the password. Any error in the
3287 password will cause the check to reset. As long a mConIn.PasswordEnabled is
3288 TRUE the StdIn splitter will not report any input.
3291 (Standard EFI_EVENT_NOTIFY)
3300 CHAR16 BackSpaceString
[2];
3301 CHAR16 SpaceString
[2];
3304 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
3305 if (!EFI_ERROR (Status
)) {
3307 // if it's an ENTER, match password
3309 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
3310 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
3311 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
3313 // Password not match
3315 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
3316 mConIn
.PwdIndex
= 0;
3319 // Key matches password sequence
3321 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
3322 mConIn
.PasswordEnabled
= FALSE
;
3323 Status
= EFI_NOT_READY
;
3325 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
3329 if (mConIn
.PwdIndex
> 0) {
3330 BackSpaceString
[0] = CHAR_BACKSPACE
;
3331 BackSpaceString
[1] = 0;
3333 SpaceString
[0] = ' ';
3336 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
3337 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
3338 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
3342 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
3344 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
3346 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
3347 if (mConIn
.PwdIndex
== 0) {
3348 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
3351 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
3352 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
3357 } while (!EFI_ERROR (Status
));
3362 ConSpliterConsoleControlLockStdIn (
3363 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
3368 Routine Description:
3369 If Password is NULL unlock the password state variable and set the event
3370 timer. If the Password is too big return an error. If the Password is valid
3371 Copy the Password and enable state variable and then arm the periodic timer
3376 EFI_SUCCESS - Lock the StdIn device
3377 EFI_INVALID_PARAMETER - Password is NULL
3378 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
3382 if (Password
== NULL
) {
3383 return EFI_INVALID_PARAMETER
;
3386 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
3388 // Currently have a max password size
3390 return EFI_OUT_OF_RESOURCES
;
3393 // Save the password, initialize state variables and arm event timer
3395 StrCpy (mConIn
.Password
, Password
);
3396 mConIn
.PasswordEnabled
= TRUE
;
3397 mConIn
.PwdIndex
= 0;
3398 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
3405 ConSplitterTextInReadKeyStroke (
3406 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3407 OUT EFI_INPUT_KEY
*Key
3411 Routine Description:
3412 Reads the next keystroke from the input device. The WaitForKey Event can
3413 be used to test for existance of a keystroke via WaitForEvent () call.
3414 If the ConIn is password locked make it look like no keystroke is availible
3417 This - Protocol instance pointer.
3418 Key - Driver may perform diagnostics on reset.
3421 EFI_SUCCESS - The keystroke information was returned.
3422 EFI_NOT_READY - There was no keystroke data availiable.
3423 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3428 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3430 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3431 if (Private
->PasswordEnabled
) {
3433 // If StdIn Locked return not ready
3435 return EFI_NOT_READY
;
3438 Private
->KeyEventSignalState
= FALSE
;
3440 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
3445 ConSplitterTextInWaitForKey (
3451 Routine Description:
3452 This event agregates all the events of the ConIn devices in the spliter.
3453 If the ConIn is password locked then return.
3454 If any events of physical ConIn devices are signaled, signal the ConIn
3455 spliter event. This will cause the calling code to call
3456 ConSplitterTextInReadKeyStroke ().
3459 Event - The Event assoicated with callback.
3460 Context - Context registered when Event was created.
3468 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3471 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3472 if (Private
->PasswordEnabled
) {
3474 // If StdIn Locked return not ready
3480 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3482 if (Private
->KeyEventSignalState
) {
3483 gBS
->SignalEvent (Event
);
3487 // if any physical console input device has key input, signal the event.
3489 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3490 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
3491 if (!EFI_ERROR (Status
)) {
3492 gBS
->SignalEvent (Event
);
3493 Private
->KeyEventSignalState
= TRUE
;
3502 IN EFI_KEY_DATA
*RegsiteredData
,
3503 IN EFI_KEY_DATA
*InputData
3507 Routine Description:
3511 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
3512 state data for the key that was registered.
3513 InputData - A pointer to a buffer that is filled in with the keystroke
3514 state data for the key that was pressed.
3517 TRUE - Key be pressed matches a registered key.
3518 FLASE - Match failed.
3522 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
3524 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
3525 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
3530 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3532 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
3533 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
3536 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
3537 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
3546 // Simple Text Input Ex protocol functions
3551 ConSplitterTextInResetEx (
3552 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3553 IN BOOLEAN ExtendedVerification
3557 Routine Description:
3558 Reset the input device and optionaly run diagnostics
3561 This - Protocol instance pointer.
3562 ExtendedVerification - Driver may perform diagnostics on reset.
3565 EFI_SUCCESS - The device was reset.
3566 EFI_DEVICE_ERROR - The device is not functioning properly and could
3572 EFI_STATUS ReturnStatus
;
3573 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3576 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3578 Private
->KeyEventSignalState
= FALSE
;
3581 // return the worst status met
3583 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3584 Status
= Private
->TextInExList
[Index
]->Reset (
3585 Private
->TextInExList
[Index
],
3586 ExtendedVerification
3588 if (EFI_ERROR (Status
)) {
3589 ReturnStatus
= Status
;
3593 return ReturnStatus
;
3599 ConSplitterTextInReadKeyStrokeEx (
3600 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3601 OUT EFI_KEY_DATA
*KeyData
3605 Routine Description:
3606 Reads the next keystroke from the input device. The WaitForKey Event can
3607 be used to test for existance of a keystroke via WaitForEvent () call.
3610 This - Protocol instance pointer.
3611 KeyData - A pointer to a buffer that is filled in with the keystroke
3612 state data for the key that was pressed.
3615 EFI_SUCCESS - The keystroke information was returned.
3616 EFI_NOT_READY - There was no keystroke data availiable.
3617 EFI_DEVICE_ERROR - The keystroke information was not returned due to
3619 EFI_INVALID_PARAMETER - KeyData is NULL.
3623 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3626 EFI_KEY_DATA CurrentKeyData
;
3629 if (KeyData
== NULL
) {
3630 return EFI_INVALID_PARAMETER
;
3633 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3634 if (Private
->PasswordEnabled
) {
3636 // If StdIn Locked return not ready
3638 return EFI_NOT_READY
;
3641 Private
->KeyEventSignalState
= FALSE
;
3643 KeyData
->Key
.UnicodeChar
= 0;
3644 KeyData
->Key
.ScanCode
= SCAN_NULL
;
3647 // if no physical console input device exists, return EFI_NOT_READY;
3648 // if any physical console input device has key input,
3649 // return the key and EFI_SUCCESS.
3651 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3652 Status
= Private
->TextInExList
[Index
]->ReadKeyStrokeEx (
3653 Private
->TextInExList
[Index
],
3656 if (!EFI_ERROR (Status
)) {
3657 CopyMem (KeyData
, &CurrentKeyData
, sizeof (CurrentKeyData
));
3662 return EFI_NOT_READY
;
3667 ConSplitterTextInSetState (
3668 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3669 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
3673 Routine Description:
3674 Set certain state for the input device.
3677 This - Protocol instance pointer.
3678 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
3679 state for the input device.
3682 EFI_SUCCESS - The device state was set successfully.
3683 EFI_DEVICE_ERROR - The device is not functioning correctly and could
3684 not have the setting adjusted.
3685 EFI_UNSUPPORTED - The device does not have the ability to set its state.
3686 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
3690 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3694 if (KeyToggleState
== NULL
) {
3695 return EFI_INVALID_PARAMETER
;
3698 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3701 // if no physical console input device exists, return EFI_SUCCESS;
3702 // otherwise return the status of setting state of physical console input device
3704 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3705 Status
= Private
->TextInExList
[Index
]->SetState (
3706 Private
->TextInExList
[Index
],
3709 if (EFI_ERROR (Status
)) {
3720 ConSplitterTextInRegisterKeyNotify (
3721 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3722 IN EFI_KEY_DATA
*KeyData
,
3723 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
3724 OUT EFI_HANDLE
*NotifyHandle
3728 Routine Description:
3729 Register a notification function for a particular keystroke for the input device.
3732 This - Protocol instance pointer.
3733 KeyData - A pointer to a buffer that is filled in with the keystroke
3734 information data for the key that was pressed.
3735 KeyNotificationFunction - Points to the function to be called when the key
3736 sequence is typed specified by KeyData.
3737 NotifyHandle - Points to the unique handle assigned to the registered notification.
3740 EFI_SUCCESS - The notification function was registered successfully.
3741 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
3742 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
3746 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3749 TEXT_IN_EX_SPLITTER_NOTIFY
*NewNotify
;
3751 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3754 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
3755 return EFI_INVALID_PARAMETER
;
3758 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3761 // if no physical console input device exists,
3762 // return EFI_SUCCESS directly.
3764 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3769 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3771 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3772 CurrentNotify
= CR (
3774 TEXT_IN_EX_SPLITTER_NOTIFY
,
3776 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
3778 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
3779 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
3780 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
3787 // Allocate resource to save the notification function
3789 NewNotify
= (TEXT_IN_EX_SPLITTER_NOTIFY
*) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY
));
3790 if (NewNotify
== NULL
) {
3791 return EFI_OUT_OF_RESOURCES
;
3793 NewNotify
->NotifyHandleList
= (EFI_HANDLE
*) AllocateZeroPool (sizeof (EFI_HANDLE
) * Private
->CurrentNumberOfExConsoles
);
3794 if (NewNotify
->NotifyHandleList
== NULL
) {
3795 gBS
->FreePool (NewNotify
);
3796 return EFI_OUT_OF_RESOURCES
;
3798 NewNotify
->Signature
= TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
;
3799 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
3800 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
3803 // Return the wrong status of registering key notify of
3804 // physical console input device if meet problems
3806 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3807 Status
= Private
->TextInExList
[Index
]->RegisterKeyNotify (
3808 Private
->TextInExList
[Index
],
3810 KeyNotificationFunction
,
3811 &NewNotify
->NotifyHandleList
[Index
]
3813 if (EFI_ERROR (Status
)) {
3814 gBS
->FreePool (NewNotify
->NotifyHandleList
);
3815 gBS
->FreePool (NewNotify
);
3821 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
3823 Status
= gBS
->InstallMultipleProtocolInterfaces (
3824 &NewNotify
->NotifyHandle
,
3825 &gSimpleTextInExNotifyGuid
,
3829 ASSERT_EFI_ERROR (Status
);
3831 InsertTailList (&mConIn
.NotifyList
, &NewNotify
->NotifyEntry
);
3833 *NotifyHandle
= NewNotify
->NotifyHandle
;
3841 ConSplitterTextInUnregisterKeyNotify (
3842 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3843 IN EFI_HANDLE NotificationHandle
3847 Routine Description:
3848 Remove a registered notification function from a particular keystroke.
3851 This - Protocol instance pointer.
3852 NotificationHandle - The handle of the notification function being unregistered.
3855 EFI_SUCCESS - The notification function was unregistered successfully.
3856 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
3857 EFI_NOT_FOUND - Can not find the matching entry in database.
3861 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3864 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3867 if (NotificationHandle
== NULL
) {
3868 return EFI_INVALID_PARAMETER
;
3871 Status
= gBS
->OpenProtocol (
3873 &gSimpleTextInExNotifyGuid
,
3877 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
3879 if (EFI_ERROR (Status
)) {
3880 return EFI_INVALID_PARAMETER
;
3883 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3886 // if no physical console input device exists,
3887 // return EFI_SUCCESS directly.
3889 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3893 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3894 CurrentNotify
= CR (Link
, TEXT_IN_EX_SPLITTER_NOTIFY
, NotifyEntry
, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
);
3895 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
3896 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3897 Status
= Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3898 Private
->TextInExList
[Index
],
3899 CurrentNotify
->NotifyHandleList
[Index
]
3901 if (EFI_ERROR (Status
)) {
3905 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
3906 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3907 CurrentNotify
->NotifyHandle
,
3908 &gSimpleTextInExNotifyGuid
,
3912 ASSERT_EFI_ERROR (Status
);
3913 gBS
->FreePool (CurrentNotify
->NotifyHandleList
);
3914 gBS
->FreePool (CurrentNotify
);
3919 return EFI_NOT_FOUND
;
3925 ConSplitterSimplePointerReset (
3926 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3927 IN BOOLEAN ExtendedVerification
3931 Routine Description:
3932 Reset the input device and optionaly run diagnostics
3935 This - Protocol instance pointer.
3936 ExtendedVerification - Driver may perform diagnostics on reset.
3939 EFI_SUCCESS - The device was reset.
3940 EFI_DEVICE_ERROR - The device is not functioning properly and could
3946 EFI_STATUS ReturnStatus
;
3947 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3950 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3952 Private
->InputEventSignalState
= FALSE
;
3954 if (Private
->CurrentNumberOfPointers
== 0) {
3958 // return the worst status met
3960 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3961 Status
= Private
->PointerList
[Index
]->Reset (
3962 Private
->PointerList
[Index
],
3963 ExtendedVerification
3965 if (EFI_ERROR (Status
)) {
3966 ReturnStatus
= Status
;
3970 return ReturnStatus
;
3976 ConSplitterSimplePointerPrivateGetState (
3977 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3978 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3982 Routine Description:
3983 Reads the next keystroke from the input device. The WaitForKey Event can
3984 be used to test for existance of a keystroke via WaitForEvent () call.
3987 This - Protocol instance pointer.
3991 EFI_SUCCESS - The keystroke information was returned.
3992 EFI_NOT_READY - There was no keystroke data availiable.
3993 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3999 EFI_STATUS ReturnStatus
;
4001 EFI_SIMPLE_POINTER_STATE CurrentState
;
4003 State
->RelativeMovementX
= 0;
4004 State
->RelativeMovementY
= 0;
4005 State
->RelativeMovementZ
= 0;
4006 State
->LeftButton
= FALSE
;
4007 State
->RightButton
= FALSE
;
4010 // if no physical console input device exists, return EFI_NOT_READY;
4011 // if any physical console input device has key input,
4012 // return the key and EFI_SUCCESS.
4014 ReturnStatus
= EFI_NOT_READY
;
4015 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
4017 Status
= Private
->PointerList
[Index
]->GetState (
4018 Private
->PointerList
[Index
],
4021 if (!EFI_ERROR (Status
)) {
4022 if (ReturnStatus
== EFI_NOT_READY
) {
4023 ReturnStatus
= EFI_SUCCESS
;
4026 if (CurrentState
.LeftButton
) {
4027 State
->LeftButton
= TRUE
;
4030 if (CurrentState
.RightButton
) {
4031 State
->RightButton
= TRUE
;
4034 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
4035 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
4038 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
4039 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
4042 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
4043 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
4045 } else if (Status
== EFI_DEVICE_ERROR
) {
4046 ReturnStatus
= EFI_DEVICE_ERROR
;
4050 return ReturnStatus
;
4055 ConSplitterSimplePointerGetState (
4056 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
4057 IN OUT EFI_SIMPLE_POINTER_STATE
*State
4061 Routine Description:
4062 Reads the next keystroke from the input device. The WaitForKey Event can
4063 be used to test for existance of a keystroke via WaitForEvent () call.
4064 If the ConIn is password locked make it look like no keystroke is availible
4067 This - Protocol instance pointer.
4071 EFI_SUCCESS - The keystroke information was returned.
4072 EFI_NOT_READY - There was no keystroke data availiable.
4073 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
4078 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4080 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
4081 if (Private
->PasswordEnabled
) {
4083 // If StdIn Locked return not ready
4085 return EFI_NOT_READY
;
4088 Private
->InputEventSignalState
= FALSE
;
4090 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
4095 ConSplitterSimplePointerWaitForInput (
4101 Routine Description:
4102 This event agregates all the events of the ConIn devices in the spliter.
4103 If the ConIn is password locked then return.
4104 If any events of physical ConIn devices are signaled, signal the ConIn
4105 spliter event. This will cause the calling code to call
4106 ConSplitterTextInReadKeyStroke ().
4109 Event - The Event assoicated with callback.
4110 Context - Context registered when Event was created.
4118 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4121 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
4122 if (Private
->PasswordEnabled
) {
4124 // If StdIn Locked return not ready
4130 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
4132 if (Private
->InputEventSignalState
) {
4133 gBS
->SignalEvent (Event
);
4137 // if any physical console input device has key input, signal the event.
4139 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
4140 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
4141 if (!EFI_ERROR (Status
)) {
4142 gBS
->SignalEvent (Event
);
4143 Private
->InputEventSignalState
= TRUE
;
4149 // Absolute Pointer Protocol functions
4154 ConSplitterAbsolutePointerReset (
4155 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4156 IN BOOLEAN ExtendedVerification
4160 Routine Description:
4161 Resets the pointer device hardware.
4164 This - Protocol instance pointer.
4165 ExtendedVerification - Driver may perform diagnostics on reset.
4168 EFI_SUCCESS - The device was reset.
4169 EFI_DEVICE_ERROR - The device is not functioning correctly and could
4175 EFI_STATUS ReturnStatus
;
4176 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4179 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4181 Private
->AbsoluteInputEventSignalState
= FALSE
;
4183 if (Private
->CurrentNumberOfAbsolutePointers
== 0) {
4187 // return the worst status met
4189 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4190 Status
= Private
->AbsolutePointerList
[Index
]->Reset (
4191 Private
->AbsolutePointerList
[Index
],
4192 ExtendedVerification
4194 if (EFI_ERROR (Status
)) {
4195 ReturnStatus
= Status
;
4199 return ReturnStatus
;
4204 ConSplitterAbsolutePointerGetState (
4205 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4206 IN OUT EFI_ABSOLUTE_POINTER_STATE
*State
4210 Routine Description:
4211 Retrieves the current state of a pointer device.
4214 This - Protocol instance pointer.
4215 State - A pointer to the state information on the pointer device.
4218 EFI_SUCCESS - The state of the pointer device was returned in State..
4219 EFI_NOT_READY - The state of the pointer device has not changed since the last call to
4221 EFI_DEVICE_ERROR - A device error occurred while attempting to retrieve the pointer
4222 device's current state.
4225 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4227 EFI_STATUS ReturnStatus
;
4229 EFI_ABSOLUTE_POINTER_STATE CurrentState
;
4232 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4233 if (Private
->PasswordEnabled
) {
4235 // If StdIn Locked return not ready
4237 return EFI_NOT_READY
;
4240 Private
->AbsoluteInputEventSignalState
= FALSE
;
4242 State
->CurrentX
= 0;
4243 State
->CurrentY
= 0;
4244 State
->CurrentZ
= 0;
4245 State
->ActiveButtons
= 0;
4248 // if no physical pointer device exists, return EFI_NOT_READY;
4249 // if any physical pointer device has changed state,
4250 // return the state and EFI_SUCCESS.
4252 ReturnStatus
= EFI_NOT_READY
;
4253 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4255 Status
= Private
->AbsolutePointerList
[Index
]->GetState (
4256 Private
->AbsolutePointerList
[Index
],
4259 if (!EFI_ERROR (Status
)) {
4260 if (ReturnStatus
== EFI_NOT_READY
) {
4261 ReturnStatus
= EFI_SUCCESS
;
4264 State
->ActiveButtons
= CurrentState
.ActiveButtons
;
4266 if (!(Private
->AbsolutePointerMode
.AbsoluteMinX
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxX
== 0)) {
4267 State
->CurrentX
= CurrentState
.CurrentX
;
4269 if (!(Private
->AbsolutePointerMode
.AbsoluteMinY
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxY
== 0)) {
4270 State
->CurrentY
= CurrentState
.CurrentY
;
4272 if (!(Private
->AbsolutePointerMode
.AbsoluteMinZ
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxZ
== 0)) {
4273 State
->CurrentZ
= CurrentState
.CurrentZ
;
4276 } else if (Status
== EFI_DEVICE_ERROR
) {
4277 ReturnStatus
= EFI_DEVICE_ERROR
;
4281 return ReturnStatus
;
4286 ConSplitterAbsolutePointerWaitForInput (
4292 Routine Description:
4293 This event agregates all the events of the pointer devices in the splitter.
4294 If the ConIn is password locked then return.
4295 If any events of physical pointer devices are signaled, signal the pointer
4296 splitter event. This will cause the calling code to call
4297 ConSplitterAbsolutePointerGetState ().
4300 Event - The Event assoicated with callback.
4301 Context - Context registered when Event was created.
4309 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4312 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
4313 if (Private
->PasswordEnabled
) {
4315 // If StdIn Locked return not ready
4321 // if AbsoluteInputEventSignalState is flagged before,
4322 // and not cleared by Reset() or GetState(), signal it
4324 if (Private
->AbsoluteInputEventSignalState
) {
4325 gBS
->SignalEvent (Event
);
4329 // if any physical console input device has key input, signal the event.
4331 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4332 Status
= gBS
->CheckEvent (Private
->AbsolutePointerList
[Index
]->WaitForInput
);
4333 if (!EFI_ERROR (Status
)) {
4334 gBS
->SignalEvent (Event
);
4335 Private
->AbsoluteInputEventSignalState
= TRUE
;
4342 ConSplitterTextOutReset (
4343 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4344 IN BOOLEAN ExtendedVerification
4348 Routine Description:
4349 Reset the text output device hardware and optionaly run diagnostics
4352 This - Protocol instance pointer.
4353 ExtendedVerification - Driver may perform more exhaustive verfication
4354 operation of the device during reset.
4357 EFI_SUCCESS - The text output device was reset.
4358 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
4364 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4366 EFI_STATUS ReturnStatus
;
4368 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4371 // return the worst status met
4373 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4375 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4377 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
4378 Private
->TextOutList
[Index
].TextOut
,
4379 ExtendedVerification
4381 if (EFI_ERROR (Status
)) {
4382 ReturnStatus
= Status
;
4387 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
4389 Status
= DevNullTextOutSetMode (Private
, 0);
4390 if (EFI_ERROR (Status
)) {
4391 ReturnStatus
= Status
;
4394 return ReturnStatus
;
4399 ConSplitterTextOutOutputString (
4400 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4405 Routine Description:
4406 Write a Unicode string to the output device.
4409 This - Protocol instance pointer.
4410 String - The NULL-terminated Unicode string to be displayed on the output
4411 device(s). All output devices must also support the Unicode
4412 drawing defined in this file.
4415 EFI_SUCCESS - The string was output to the device.
4416 EFI_DEVICE_ERROR - The device reported an error while attempting to output
4418 EFI_UNSUPPORTED - The output device's mode is not currently in a
4420 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
4421 characters in the Unicode string could not be
4422 rendered and were skipped.
4427 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4429 UINTN BackSpaceCount
;
4430 EFI_STATUS ReturnStatus
;
4431 CHAR16
*TargetString
;
4433 This
->SetAttribute (This
, This
->Mode
->Attribute
);
4435 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4438 for (TargetString
= WString
; *TargetString
; TargetString
++) {
4439 if (*TargetString
== CHAR_BACKSPACE
) {
4445 if (BackSpaceCount
== 0) {
4446 TargetString
= WString
;
4448 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
4449 StrCpy (TargetString
, WString
);
4452 // return the worst status met
4454 Status
= DevNullTextOutOutputString (Private
, TargetString
);
4455 if (EFI_ERROR (Status
)) {
4456 ReturnStatus
= Status
;
4459 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4461 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4462 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
4463 Private
->TextOutList
[Index
].TextOut
,
4466 if (EFI_ERROR (Status
)) {
4467 ReturnStatus
= Status
;
4472 if (BackSpaceCount
) {
4473 FreePool (TargetString
);
4476 return ReturnStatus
;
4481 ConSplitterTextOutTestString (
4482 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4487 Routine Description:
4488 Verifies that all characters in a Unicode string can be output to the
4492 This - Protocol instance pointer.
4493 String - The NULL-terminated Unicode string to be examined for the output
4497 EFI_SUCCESS - The device(s) are capable of rendering the output string.
4498 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
4499 rendered by one or more of the output devices mapped
4505 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4507 EFI_STATUS ReturnStatus
;
4509 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4512 // return the worst status met
4514 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4515 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4516 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
4517 Private
->TextOutList
[Index
].TextOut
,
4520 if (EFI_ERROR (Status
)) {
4521 ReturnStatus
= Status
;
4526 // There is no DevNullTextOutTestString () since a Unicode buffer would
4527 // always return EFI_SUCCESS.
4528 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4530 return ReturnStatus
;
4535 ConSplitterTextOutQueryMode (
4536 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4537 IN UINTN ModeNumber
,
4543 Routine Description:
4544 Returns information for an available text mode that the output device(s)
4548 This - Protocol instance pointer.
4549 ModeNumber - The mode number to return information on.
4550 Columns, Rows - Returns the geometry of the text output device for the
4551 requested ModeNumber.
4554 EFI_SUCCESS - The requested mode information was returned.
4555 EFI_DEVICE_ERROR - The device had an error and could not
4556 complete the request.
4557 EFI_UNSUPPORTED - The mode number was not valid.
4561 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4563 INT32
*TextOutModeMap
;
4565 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4568 // Check whether param ModeNumber is valid.
4569 // ModeNumber should be within range 0 ~ MaxMode - 1.
4571 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4572 return EFI_UNSUPPORTED
;
4575 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4576 return EFI_UNSUPPORTED
;
4580 // We get the available mode from mode intersection map if it's available
4582 if (Private
->TextOutModeMap
!= NULL
) {
4583 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4584 CurrentMode
= (UINTN
)(*TextOutModeMap
);
4585 *Columns
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4586 *Rows
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4588 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
4589 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
4592 if (*Columns
<= 0 && *Rows
<= 0) {
4593 return EFI_UNSUPPORTED
;
4602 ConSplitterTextOutSetMode (
4603 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4608 Routine Description:
4609 Sets the output device(s) to a specified mode.
4612 This - Protocol instance pointer.
4613 ModeNumber - The mode number to set.
4616 EFI_SUCCESS - The requested text mode was set.
4617 EFI_DEVICE_ERROR - The device had an error and
4618 could not complete the request.
4619 EFI_UNSUPPORTED - The mode number was not valid.
4624 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4626 INT32
*TextOutModeMap
;
4627 EFI_STATUS ReturnStatus
;
4629 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4632 // Check whether param ModeNumber is valid.
4633 // ModeNumber should be within range 0 ~ MaxMode - 1.
4635 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4636 return EFI_UNSUPPORTED
;
4639 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4640 return EFI_UNSUPPORTED
;
4643 // If the mode is being set to the curent mode, then just clear the screen and return.
4645 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
4646 return ConSplitterTextOutClearScreen (This
);
4649 // return the worst status met
4651 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4652 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4654 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4655 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
4656 Private
->TextOutList
[Index
].TextOut
,
4657 TextOutModeMap
[Index
]
4660 // If this console device is based on a GOP or UGA device, then sync up the bitmap from
4661 // the GOP/UGA splitter and reclear the text portion of the display in the new mode.
4663 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
4664 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4667 if (EFI_ERROR (Status
)) {
4668 ReturnStatus
= Status
;
4673 // The DevNull Console will support any possible mode as it allocates memory
4675 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
4676 if (EFI_ERROR (Status
)) {
4677 ReturnStatus
= Status
;
4680 return ReturnStatus
;
4685 ConSplitterTextOutSetAttribute (
4686 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4691 Routine Description:
4692 Sets the background and foreground colors for the OutputString () and
4693 ClearScreen () functions.
4696 This - Protocol instance pointer.
4697 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
4698 bits 4..6 are the background color. All other bits are undefined
4699 and must be zero. The valid Attributes are defined in this file.
4702 EFI_SUCCESS - The attribute was set.
4703 EFI_DEVICE_ERROR - The device had an error and
4704 could not complete the request.
4705 EFI_UNSUPPORTED - The attribute requested is not defined.
4710 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4712 EFI_STATUS ReturnStatus
;
4714 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4717 // Check whether param Attribute is valid.
4719 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4720 return EFI_UNSUPPORTED
;
4724 // return the worst status met
4726 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4728 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4729 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
4730 Private
->TextOutList
[Index
].TextOut
,
4733 if (EFI_ERROR (Status
)) {
4734 ReturnStatus
= Status
;
4739 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
4741 return ReturnStatus
;
4746 ConSplitterTextOutClearScreen (
4747 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
4751 Routine Description:
4752 Clears the output device(s) display to the currently selected background
4756 This - Protocol instance pointer.
4759 EFI_SUCCESS - The operation completed successfully.
4760 EFI_DEVICE_ERROR - The device had an error and
4761 could not complete the request.
4762 EFI_UNSUPPORTED - The output device is not in a valid text mode.
4767 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4769 EFI_STATUS ReturnStatus
;
4771 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4774 // return the worst status met
4776 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4778 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4779 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4780 if (EFI_ERROR (Status
)) {
4781 ReturnStatus
= Status
;
4786 Status
= DevNullTextOutClearScreen (Private
);
4787 if (EFI_ERROR (Status
)) {
4788 ReturnStatus
= Status
;
4791 return ReturnStatus
;
4796 ConSplitterTextOutSetCursorPosition (
4797 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4803 Routine Description:
4804 Sets the current coordinates of the cursor position
4807 This - Protocol instance pointer.
4808 Column, Row - the position to set the cursor to. Must be greater than or
4809 equal to zero and less than the number of columns and rows
4813 EFI_SUCCESS - The operation completed successfully.
4814 EFI_DEVICE_ERROR - The device had an error and
4815 could not complete the request.
4816 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
4817 cursor position is invalid for the current mode.
4822 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4824 EFI_STATUS ReturnStatus
;
4827 INT32
*TextOutModeMap
;
4831 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4832 TextOutModeMap
= NULL
;
4833 ModeNumber
= Private
->TextOutMode
.Mode
;
4836 // Get current MaxColumn and MaxRow from intersection map
4838 if (Private
->TextOutModeMap
!= NULL
) {
4839 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4840 CurrentMode
= *TextOutModeMap
;
4842 CurrentMode
= ModeNumber
;
4845 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4846 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4848 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
4849 return EFI_UNSUPPORTED
;
4852 // return the worst status met
4854 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4856 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4857 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
4858 Private
->TextOutList
[Index
].TextOut
,
4862 if (EFI_ERROR (Status
)) {
4863 ReturnStatus
= Status
;
4868 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
4870 return ReturnStatus
;
4875 ConSplitterTextOutEnableCursor (
4876 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4881 Routine Description:
4882 Makes the cursor visible or invisible
4885 This - Protocol instance pointer.
4886 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
4887 set to be invisible.
4890 EFI_SUCCESS - The operation completed successfully.
4891 EFI_DEVICE_ERROR - The device had an error and could not complete the
4892 request, or the device does not support changing
4894 EFI_UNSUPPORTED - The output device is not in a valid text mode.
4899 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4901 EFI_STATUS ReturnStatus
;
4903 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4906 // return the worst status met
4908 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4910 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4911 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
4912 Private
->TextOutList
[Index
].TextOut
,
4915 if (EFI_ERROR (Status
)) {
4916 ReturnStatus
= Status
;
4921 DevNullTextOutEnableCursor (Private
, Visible
);
4923 return ReturnStatus
;