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
;
686 Status
= ConSplitterGrowBuffer (
687 sizeof (TEXT_OUT_AND_GOP_DATA
),
688 &ConOutPrivate
->TextOutListCount
,
689 (VOID
**) &ConOutPrivate
->TextOutList
691 if (EFI_ERROR (Status
)) {
692 return EFI_OUT_OF_RESOURCES
;
695 Status
= ConSplitterGrowBuffer (
696 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
697 &ConOutPrivate
->TextOutQueryDataCount
,
698 (VOID
**) &ConOutPrivate
->TextOutQueryData
700 if (EFI_ERROR (Status
)) {
701 return EFI_OUT_OF_RESOURCES
;
704 // Setup the DevNullTextOut console to 80 x 25
706 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
707 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
708 DevNullTextOutSetMode (ConOutPrivate
, 0);
710 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
712 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
714 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
716 if (FeaturePcdGet (PcdConOutGopSupport
)) {
718 // Setup resource for mode information in Graphics Output Protocol interface
720 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
721 return EFI_OUT_OF_RESOURCES
;
723 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
724 return EFI_OUT_OF_RESOURCES
;
727 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
728 // DevNull will be updated to user-defined mode after driver has started.
730 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
731 return EFI_OUT_OF_RESOURCES
;
733 Info
= &ConOutPrivate
->GraphicsOutputModeBuffer
[0];
735 Info
->HorizontalResolution
= 800;
736 Info
->VerticalResolution
= 600;
737 Info
->PixelFormat
= PixelBltOnly
;
738 Info
->PixelsPerScanLine
= 800;
739 CopyMem (ConOutPrivate
->GraphicsOutput
.Mode
->Info
, Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
740 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
743 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
744 // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
746 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
747 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
749 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
751 // Initial current mode to unknow state, and then set to mode 0
753 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
754 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
762 ConSplitterSupported (
763 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
764 IN EFI_HANDLE ControllerHandle
,
770 Generic Supported Check
773 This - Pointer to protocol.
774 ControllerHandle - Controller Handle.
779 EFI_UNSUPPORTED - unsupported.
780 EFI_SUCCESS - operation is OK.
788 // Make sure the Console Splitter does not attempt to attach to itself
790 if (ControllerHandle
== mConIn
.VirtualHandle
) {
791 return EFI_UNSUPPORTED
;
794 if (ControllerHandle
== mConOut
.VirtualHandle
) {
795 return EFI_UNSUPPORTED
;
798 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
799 return EFI_UNSUPPORTED
;
802 // Check to see whether the handle has the ConsoleInDevice GUID on it
804 Status
= gBS
->OpenProtocol (
808 This
->DriverBindingHandle
,
810 EFI_OPEN_PROTOCOL_BY_DRIVER
813 if (EFI_ERROR (Status
)) {
820 This
->DriverBindingHandle
,
829 ConSplitterConInDriverBindingSupported (
830 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
831 IN EFI_HANDLE ControllerHandle
,
832 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
837 Console In Supported Check
840 This - Pointer to protocol.
841 ControllerHandle - Controller handle.
842 RemainingDevicePath - Remaining device path.
850 return ConSplitterSupported (
853 &gEfiConsoleInDeviceGuid
859 ConSplitterSimplePointerDriverBindingSupported (
860 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
861 IN EFI_HANDLE ControllerHandle
,
862 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
867 Standard Error Supported Check
870 This - Pointer to protocol.
871 ControllerHandle - Controller handle.
872 RemainingDevicePath - Remaining device path.
880 return ConSplitterSupported (
883 &gEfiSimplePointerProtocolGuid
889 ConSplitterAbsolutePointerDriverBindingSupported (
890 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
891 IN EFI_HANDLE ControllerHandle
,
892 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
897 Absolute Pointer Supported Check
900 This - Pointer to protocol.
901 ControllerHandle - Controller handle.
902 RemainingDevicePath - Remaining device path.
910 return ConSplitterSupported (
913 &gEfiAbsolutePointerProtocolGuid
919 ConSplitterConOutDriverBindingSupported (
920 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
921 IN EFI_HANDLE ControllerHandle
,
922 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
927 Console Out Supported Check
930 This - Pointer to protocol.
931 ControllerHandle - Controller handle.
932 RemainingDevicePath - Remaining device path.
940 return ConSplitterSupported (
943 &gEfiConsoleOutDeviceGuid
949 ConSplitterStdErrDriverBindingSupported (
950 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
951 IN EFI_HANDLE ControllerHandle
,
952 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
957 Standard Error Supported Check
960 This - Pointer to protocol.
961 ControllerHandle - Controller handle.
962 RemainingDevicePath - Remaining device path.
970 return ConSplitterSupported (
973 &gEfiStandardErrorDeviceGuid
981 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
982 IN EFI_HANDLE ControllerHandle
,
983 IN EFI_HANDLE ConSplitterVirtualHandle
,
984 IN EFI_GUID
*DeviceGuid
,
985 IN EFI_GUID
*InterfaceGuid
,
991 Start ConSplitter on ControllerHandle, and create the virtual
992 agrogated console device on first call Start for a SimpleTextIn handle.
995 (Standard DriverBinding Protocol Start() function)
998 EFI_ERROR if a SimpleTextIn protocol is not started.
1006 // Check to see whether the handle has the ConsoleInDevice GUID on it
1008 Status
= gBS
->OpenProtocol (
1012 This
->DriverBindingHandle
,
1014 EFI_OPEN_PROTOCOL_BY_DRIVER
1016 if (EFI_ERROR (Status
)) {
1020 Status
= gBS
->OpenProtocol (
1024 This
->DriverBindingHandle
,
1025 ConSplitterVirtualHandle
,
1026 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1028 if (EFI_ERROR (Status
)) {
1032 return gBS
->OpenProtocol (
1036 This
->DriverBindingHandle
,
1037 ConSplitterVirtualHandle
,
1038 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1044 ConSplitterConInDriverBindingStart (
1045 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1046 IN EFI_HANDLE ControllerHandle
,
1047 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1051 Routine Description:
1052 Start ConSplitter on ControllerHandle, and create the virtual
1053 agrogated console device on first call Start for a SimpleTextIn handle.
1056 This - Pointer to protocol.
1057 ControllerHandle - Controller handle.
1058 RemainingDevicePath - Remaining device path.
1063 EFI_ERROR if a SimpleTextIn protocol is not started.
1068 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1069 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1072 // Start ConSplitter on ControllerHandle, and create the virtual
1073 // agrogated console device on first call Start for a SimpleTextIn handle.
1075 Status
= ConSplitterStart (
1078 mConIn
.VirtualHandle
,
1079 &gEfiConsoleInDeviceGuid
,
1080 &gEfiSimpleTextInProtocolGuid
,
1083 if (EFI_ERROR (Status
)) {
1087 Status
= ConSplitterTextInAddDevice (&mConIn
, TextIn
);
1088 if (EFI_ERROR (Status
)) {
1092 Status
= gBS
->OpenProtocol (
1094 &gEfiSimpleTextInputExProtocolGuid
,
1095 (VOID
**) &TextInEx
,
1096 This
->DriverBindingHandle
,
1097 mConIn
.VirtualHandle
,
1098 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1100 if (EFI_ERROR (Status
)) {
1104 Status
= ConSplitterTextInExAddDevice (&mConIn
, TextInEx
);
1111 ConSplitterSimplePointerDriverBindingStart (
1112 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1113 IN EFI_HANDLE ControllerHandle
,
1114 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1118 Routine Description:
1119 Start ConSplitter on ControllerHandle, and create the virtual
1120 agrogated console device on first call Start for a SimpleTextIn handle.
1123 This - Pointer to protocol.
1124 ControllerHandle - Controller handle.
1125 RemainingDevicePath - Remaining device path.
1129 EFI_ERROR if a SimpleTextIn protocol is not started.
1134 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1136 Status
= ConSplitterStart (
1139 mConIn
.VirtualHandle
,
1140 &gEfiSimplePointerProtocolGuid
,
1141 &gEfiSimplePointerProtocolGuid
,
1142 (VOID
**) &SimplePointer
1144 if (EFI_ERROR (Status
)) {
1148 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
1153 ConSplitterAbsolutePointerDriverBindingStart (
1154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1155 IN EFI_HANDLE ControllerHandle
,
1156 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1160 Routine Description:
1161 Start ConSplitter on ControllerHandle, and create the virtual
1162 agrogated console device on first call Start for a ConIn handle.
1165 This - Pointer to protocol.
1166 ControllerHandle - Controller handle.
1167 RemainingDevicePath - Remaining device path.
1171 EFI_ERROR if a AbsolutePointer protocol is not started.
1176 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1178 Status
= ConSplitterStart (
1181 mConIn
.VirtualHandle
,
1182 &gEfiAbsolutePointerProtocolGuid
,
1183 &gEfiAbsolutePointerProtocolGuid
,
1184 (VOID
**) &AbsolutePointer
1187 if (EFI_ERROR (Status
)) {
1191 return ConSplitterAbsolutePointerAddDevice (&mConIn
, AbsolutePointer
);
1196 ConSplitterConOutDriverBindingStart (
1197 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1198 IN EFI_HANDLE ControllerHandle
,
1199 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1203 Routine Description:
1204 Start ConSplitter on ControllerHandle, and create the virtual
1205 agrogated console device on first call Start for a SimpleTextIn handle.
1208 This - Pointer to protocol.
1209 ControllerHandle - Controller handle.
1210 RemainingDevicePath - Remaining device path.
1213 EFI_ERROR if a SimpleTextIn protocol is not started.
1218 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1219 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1220 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1222 Status
= ConSplitterStart (
1225 mConOut
.VirtualHandle
,
1226 &gEfiConsoleOutDeviceGuid
,
1227 &gEfiSimpleTextOutProtocolGuid
,
1230 if (EFI_ERROR (Status
)) {
1234 // Try to Open Graphics Output protocol
1236 Status
= gBS
->OpenProtocol (
1238 &gEfiGraphicsOutputProtocolGuid
,
1239 (VOID
**) &GraphicsOutput
,
1240 This
->DriverBindingHandle
,
1241 mConOut
.VirtualHandle
,
1242 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1244 if (EFI_ERROR (Status
)) {
1245 GraphicsOutput
= NULL
;
1248 // Open UGA_DRAW protocol
1250 Status
= gBS
->OpenProtocol (
1252 &gEfiUgaDrawProtocolGuid
,
1254 This
->DriverBindingHandle
,
1255 mConOut
.VirtualHandle
,
1256 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1258 if (EFI_ERROR (Status
)) {
1262 // If both ConOut and StdErr incorporate the same Text Out device,
1263 // their MaxMode and QueryData should be the intersection of both.
1265 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1266 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1268 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
1270 // Match the UGA mode data of ConOut with the current mode
1272 if (UgaDraw
!= NULL
) {
1275 &mConOut
.UgaHorizontalResolution
,
1276 &mConOut
.UgaVerticalResolution
,
1277 &mConOut
.UgaColorDepth
,
1278 &mConOut
.UgaRefreshRate
1287 ConSplitterStdErrDriverBindingStart (
1288 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1289 IN EFI_HANDLE ControllerHandle
,
1290 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1294 Routine Description:
1295 Start ConSplitter on ControllerHandle, and create the virtual
1296 agrogated console device on first call Start for a SimpleTextIn handle.
1299 This - Pointer to protocol.
1300 ControllerHandle - Controller handle.
1301 RemainingDevicePath - Remaining device path.
1304 EFI_ERROR if a SimpleTextIn protocol is not started.
1309 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1311 Status
= ConSplitterStart (
1314 mStdErr
.VirtualHandle
,
1315 &gEfiStandardErrorDeviceGuid
,
1316 &gEfiSimpleTextOutProtocolGuid
,
1319 if (EFI_ERROR (Status
)) {
1323 // If both ConOut and StdErr incorporate the same Text Out device,
1324 // their MaxMode and QueryData should be the intersection of both.
1326 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1327 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1328 if (EFI_ERROR (Status
)) {
1332 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1333 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1334 gST
->StdErr
= &mStdErr
.TextOut
;
1336 // Update the CRC32 in the EFI System Table header
1339 gBS
->CalculateCrc32 (
1340 (UINT8
*) &gST
->Hdr
,
1341 gST
->Hdr
.HeaderSize
,
1353 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1354 IN EFI_HANDLE ControllerHandle
,
1355 IN EFI_HANDLE ConSplitterVirtualHandle
,
1356 IN EFI_GUID
*DeviceGuid
,
1357 IN EFI_GUID
*InterfaceGuid
,
1362 Routine Description:
1365 (Standard DriverBinding Protocol Stop() function)
1375 Status
= gBS
->OpenProtocol (
1379 This
->DriverBindingHandle
,
1381 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1383 if (EFI_ERROR (Status
)) {
1387 // close the protocol refered.
1389 gBS
->CloseProtocol (
1392 This
->DriverBindingHandle
,
1393 ConSplitterVirtualHandle
1395 gBS
->CloseProtocol (
1398 This
->DriverBindingHandle
,
1407 ConSplitterConInDriverBindingStop (
1408 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1409 IN EFI_HANDLE ControllerHandle
,
1410 IN UINTN NumberOfChildren
,
1411 IN EFI_HANDLE
*ChildHandleBuffer
1415 Routine Description:
1418 (Standard DriverBinding Protocol Stop() function)
1427 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1429 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1430 if (NumberOfChildren
== 0) {
1434 Status
= gBS
->OpenProtocol (
1436 &gEfiSimpleTextInputExProtocolGuid
,
1437 (VOID
**) &TextInEx
,
1438 This
->DriverBindingHandle
,
1440 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1442 if (EFI_ERROR (Status
)) {
1446 Status
= ConSplitterTextInExDeleteDevice (&mConIn
, TextInEx
);
1447 if (EFI_ERROR (Status
)) {
1452 Status
= ConSplitterStop (
1455 mConIn
.VirtualHandle
,
1456 &gEfiConsoleInDeviceGuid
,
1457 &gEfiSimpleTextInProtocolGuid
,
1460 if (EFI_ERROR (Status
)) {
1464 // Delete this console input device's data structures.
1466 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1471 ConSplitterSimplePointerDriverBindingStop (
1472 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1473 IN EFI_HANDLE ControllerHandle
,
1474 IN UINTN NumberOfChildren
,
1475 IN EFI_HANDLE
*ChildHandleBuffer
1479 Routine Description:
1482 (Standard DriverBinding Protocol Stop() function)
1491 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1493 if (NumberOfChildren
== 0) {
1497 Status
= ConSplitterStop (
1500 mConIn
.VirtualHandle
,
1501 &gEfiSimplePointerProtocolGuid
,
1502 &gEfiSimplePointerProtocolGuid
,
1503 (VOID
**) &SimplePointer
1505 if (EFI_ERROR (Status
)) {
1509 // Delete this console input device's data structures.
1511 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1516 ConSplitterAbsolutePointerDriverBindingStop (
1517 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1518 IN EFI_HANDLE ControllerHandle
,
1519 IN UINTN NumberOfChildren
,
1520 IN EFI_HANDLE
*ChildHandleBuffer
1524 Routine Description:
1527 (Standard DriverBinding Protocol Stop() function)
1536 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1538 if (NumberOfChildren
== 0) {
1542 Status
= ConSplitterStop (
1545 mConIn
.VirtualHandle
,
1546 &gEfiAbsolutePointerProtocolGuid
,
1547 &gEfiAbsolutePointerProtocolGuid
,
1548 (VOID
**) &AbsolutePointer
1550 if (EFI_ERROR (Status
)) {
1554 // Delete this console input device's data structures.
1556 return ConSplitterAbsolutePointerDeleteDevice (&mConIn
, AbsolutePointer
);
1561 ConSplitterConOutDriverBindingStop (
1562 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1563 IN EFI_HANDLE ControllerHandle
,
1564 IN UINTN NumberOfChildren
,
1565 IN EFI_HANDLE
*ChildHandleBuffer
1569 Routine Description:
1572 (Standard DriverBinding Protocol Stop() function)
1581 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1583 if (NumberOfChildren
== 0) {
1587 Status
= ConSplitterStop (
1590 mConOut
.VirtualHandle
,
1591 &gEfiConsoleOutDeviceGuid
,
1592 &gEfiSimpleTextOutProtocolGuid
,
1595 if (EFI_ERROR (Status
)) {
1600 // Delete this console output device's data structures.
1602 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1607 ConSplitterStdErrDriverBindingStop (
1608 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1609 IN EFI_HANDLE ControllerHandle
,
1610 IN UINTN NumberOfChildren
,
1611 IN EFI_HANDLE
*ChildHandleBuffer
1615 Routine Description:
1618 (Standard DriverBinding Protocol Stop() function)
1622 EFI_SUCCESS - Complete successfully.
1627 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1629 if (NumberOfChildren
== 0) {
1633 Status
= ConSplitterStop (
1636 mStdErr
.VirtualHandle
,
1637 &gEfiStandardErrorDeviceGuid
,
1638 &gEfiSimpleTextOutProtocolGuid
,
1641 if (EFI_ERROR (Status
)) {
1645 // Delete this console error out device's data structures.
1647 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1648 if (EFI_ERROR (Status
)) {
1652 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1653 gST
->StandardErrorHandle
= NULL
;
1656 // Update the CRC32 in the EFI System Table header
1659 gBS
->CalculateCrc32 (
1660 (UINT8
*) &gST
->Hdr
,
1661 gST
->Hdr
.HeaderSize
,
1670 ConSplitterGrowBuffer (
1671 IN UINTN SizeOfCount
,
1673 IN OUT VOID
**Buffer
1677 Routine Description:
1678 Take the passed in Buffer of size SizeOfCount and grow the buffer
1679 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1680 bytes. Copy the current data in Buffer to the new version of Buffer
1681 and free the old version of buffer.
1685 SizeOfCount - Size of element in array
1686 Count - Current number of elements in array
1687 Buffer - Bigger version of passed in Buffer with all the data
1690 EFI_SUCCESS - Buffer size has grown
1691 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1702 // grow the buffer to new buffer size,
1703 // copy the old buffer's content to the new-size buffer,
1704 // then free the old buffer.
1706 OldSize
= *Count
* SizeOfCount
;
1707 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1708 NewSize
= *Count
* SizeOfCount
;
1710 Ptr
= AllocateZeroPool (NewSize
);
1712 return EFI_OUT_OF_RESOURCES
;
1715 CopyMem (Ptr
, *Buffer
, OldSize
);
1717 if (*Buffer
!= NULL
) {
1727 ConSplitterTextInAddDevice (
1728 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1729 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1733 Routine Description:
1740 EFI_OUT_OF_RESOURCES
1747 // If the Text In List is full, enlarge it by calling growbuffer().
1749 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1750 Status
= ConSplitterGrowBuffer (
1751 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1752 &Private
->TextInListCount
,
1753 (VOID
**) &Private
->TextInList
1755 if (EFI_ERROR (Status
)) {
1756 return EFI_OUT_OF_RESOURCES
;
1760 // Add the new text-in device data structure into the Text In List.
1762 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1763 Private
->CurrentNumberOfConsoles
++;
1766 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1768 gBS
->CheckEvent (TextIn
->WaitForKey
);
1774 ConSplitterTextInDeleteDevice (
1775 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1776 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1780 Routine Description:
1793 // Remove the specified text-in device data structure from the Text In List,
1794 // and rearrange the remaining data structures in the Text In List.
1796 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1797 if (Private
->TextInList
[Index
] == TextIn
) {
1798 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1799 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1802 Private
->CurrentNumberOfConsoles
--;
1807 return EFI_NOT_FOUND
;
1811 ConSplitterTextInExAddDevice (
1812 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1813 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1819 // If the TextInEx List is full, enlarge it by calling growbuffer().
1821 if (Private
->CurrentNumberOfExConsoles
>= Private
->TextInExListCount
) {
1822 Status
= ConSplitterGrowBuffer (
1823 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
1824 &Private
->TextInExListCount
,
1825 (VOID
**) &Private
->TextInExList
1827 if (EFI_ERROR (Status
)) {
1828 return EFI_OUT_OF_RESOURCES
;
1832 // Add the new text-in device data structure into the Text In List.
1834 Private
->TextInExList
[Private
->CurrentNumberOfExConsoles
] = TextInEx
;
1835 Private
->CurrentNumberOfExConsoles
++;
1838 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1840 gBS
->CheckEvent (TextInEx
->WaitForKeyEx
);
1846 ConSplitterTextInExDeleteDevice (
1847 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1848 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1853 // Remove the specified text-in device data structure from the Text In List,
1854 // and rearrange the remaining data structures in the Text In List.
1856 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
1857 if (Private
->TextInExList
[Index
] == TextInEx
) {
1858 for (Index
= Index
; Index
< Private
->CurrentNumberOfExConsoles
- 1; Index
++) {
1859 Private
->TextInExList
[Index
] = Private
->TextInExList
[Index
+ 1];
1862 Private
->CurrentNumberOfExConsoles
--;
1867 return EFI_NOT_FOUND
;
1871 ConSplitterSimplePointerAddDevice (
1872 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1873 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1877 Routine Description:
1883 EFI_OUT_OF_RESOURCES
1891 // If the Text In List is full, enlarge it by calling growbuffer().
1893 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1894 Status
= ConSplitterGrowBuffer (
1895 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1896 &Private
->PointerListCount
,
1897 (VOID
**) &Private
->PointerList
1899 if (EFI_ERROR (Status
)) {
1900 return EFI_OUT_OF_RESOURCES
;
1904 // Add the new text-in device data structure into the Text In List.
1906 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1907 Private
->CurrentNumberOfPointers
++;
1912 ConSplitterSimplePointerDeleteDevice (
1913 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1914 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1918 Routine Description:
1930 // Remove the specified text-in device data structure from the Text In List,
1931 // and rearrange the remaining data structures in the Text In List.
1933 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1934 if (Private
->PointerList
[Index
] == SimplePointer
) {
1935 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1936 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1939 Private
->CurrentNumberOfPointers
--;
1944 return EFI_NOT_FOUND
;
1948 ConSplitterAbsolutePointerAddDevice (
1949 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1950 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
1954 Routine Description:
1960 EFI_OUT_OF_RESOURCES
1968 // If the Absolute Pointer List is full, enlarge it by calling growbuffer().
1970 if (Private
->CurrentNumberOfAbsolutePointers
>= Private
->AbsolutePointerListCount
) {
1971 Status
= ConSplitterGrowBuffer (
1972 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
1973 &Private
->AbsolutePointerListCount
,
1974 (VOID
**) &Private
->AbsolutePointerList
1976 if (EFI_ERROR (Status
)) {
1977 return EFI_OUT_OF_RESOURCES
;
1981 // Add the new text-in device data structure into the Text In List.
1983 Private
->AbsolutePointerList
[Private
->CurrentNumberOfAbsolutePointers
] = AbsolutePointer
;
1984 Private
->CurrentNumberOfAbsolutePointers
++;
1989 ConSplitterAbsolutePointerDeleteDevice (
1990 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1991 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
1995 Routine Description:
2007 // Remove the specified text-in device data structure from the Text In List,
2008 // and rearrange the remaining data structures in the Text In List.
2010 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
2011 if (Private
->AbsolutePointerList
[Index
] == AbsolutePointer
) {
2012 for (Index
= Index
; Index
< Private
->CurrentNumberOfAbsolutePointers
- 1; Index
++) {
2013 Private
->AbsolutePointerList
[Index
] = Private
->AbsolutePointerList
[Index
+ 1];
2016 Private
->CurrentNumberOfAbsolutePointers
--;
2021 return EFI_NOT_FOUND
;
2026 ConSplitterGrowMapTable (
2027 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
2031 Routine Description:
2044 INT32
*TextOutModeMap
;
2045 INT32
*OldTextOutModeMap
;
2049 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
2050 OldTextOutModeMap
= Private
->TextOutModeMap
;
2051 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
2053 TextOutModeMap
= AllocateZeroPool (TotalSize
);
2054 if (TextOutModeMap
== NULL
) {
2055 return EFI_OUT_OF_RESOURCES
;
2058 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
2059 Private
->TextOutModeMap
= TextOutModeMap
;
2062 // If TextOutList has been enlarged, need to realloc the mode map table
2063 // The mode map table is regarded as a two dimension array.
2066 // 0 ---------> TextOutListCount ----> TextOutListCount
2067 // | -------------------------------------------
2074 // -------------------------------------------
2077 if (OldTextOutModeMap
!= NULL
) {
2079 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
2081 SrcAddress
= OldTextOutModeMap
;
2084 // Copy the old data to the new one
2086 while (Index
< Private
->TextOutMode
.MaxMode
) {
2087 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
2088 TextOutModeMap
+= NewSize
;
2093 // Free the old buffer
2095 FreePool (OldTextOutModeMap
);
2103 ConSplitterAddOutputMode (
2104 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2105 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2109 Routine Description:
2124 MaxMode
= TextOut
->Mode
->MaxMode
;
2125 Private
->TextOutMode
.MaxMode
= MaxMode
;
2128 // Grow the buffer if query data buffer is not large enough to
2129 // hold all the mode supported by the first console.
2131 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
2132 Status
= ConSplitterGrowBuffer (
2133 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
2134 &Private
->TextOutQueryDataCount
,
2135 (VOID
**) &Private
->TextOutQueryData
2137 if (EFI_ERROR (Status
)) {
2138 return EFI_OUT_OF_RESOURCES
;
2142 // Allocate buffer for the output mode map
2144 Status
= ConSplitterGrowMapTable (Private
);
2145 if (EFI_ERROR (Status
)) {
2146 return EFI_OUT_OF_RESOURCES
;
2149 // As the first textout device, directly add the mode in to QueryData
2150 // and at the same time record the mapping between QueryData and TextOut.
2154 while (Mode
< MaxMode
) {
2155 Status
= TextOut
->QueryMode (
2158 &Private
->TextOutQueryData
[Mode
].Columns
,
2159 &Private
->TextOutQueryData
[Mode
].Rows
2162 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2165 if ((EFI_ERROR(Status
)) && (Mode
== 1)) {
2166 Private
->TextOutQueryData
[Mode
].Columns
= 0;
2167 Private
->TextOutQueryData
[Mode
].Rows
= 0;
2169 Private
->TextOutModeMap
[Index
] = Mode
;
2171 Index
+= Private
->TextOutListCount
;
2178 Reconstruct TextOutModeMap to get intersection of modes
2180 This routine reconstruct TextOutModeMap to get the intersection
2181 of modes for all console out devices. Because EFI/UEFI spec require
2182 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the
2183 intersection for mode 0 and mode 1.
2185 @parm TextOutModeMap Current text out mode map, begin with the mode 80x25
2186 @parm NewlyAddedMap New text out mode map, begin with the mode 80x25
2187 @parm MapStepSize Mode step size for one console device
2188 @parm NewMapStepSize Mode step size for one console device
2189 @parm MaxMode Current max text mode
2190 @parm CurrentMode Current text mode
2197 ConSplitterGetIntersection (
2198 IN INT32
*TextOutModeMap
,
2199 IN INT32
*NewlyAddedMap
,
2200 IN UINTN MapStepSize
,
2201 IN UINTN NewMapStepSize
,
2203 OUT INT32
*CurrentMode
2207 INT32
*CurrentMapEntry
;
2208 INT32
*NextMapEntry
;
2209 INT32 CurrentMaxMode
;
2213 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved
2214 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection
2215 // for mode 0 and mode 1, mode number starts from 2.
2218 CurrentMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2219 NextMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2220 NewlyAddedMap
= &NewlyAddedMap
[NewMapStepSize
* 2];
2222 CurrentMaxMode
= *MaxMode
;
2223 Mode
= *CurrentMode
;
2225 while (Index
< CurrentMaxMode
) {
2226 if (*NewlyAddedMap
== -1) {
2228 // This mode is not supported any more. Remove it. Special care
2229 // must be taken as this remove will also affect current mode;
2231 if (Index
== *CurrentMode
) {
2233 } else if (Index
< *CurrentMode
) {
2238 if (CurrentMapEntry
!= NextMapEntry
) {
2239 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
2242 NextMapEntry
+= MapStepSize
;
2245 CurrentMapEntry
+= MapStepSize
;
2246 NewlyAddedMap
+= NewMapStepSize
;
2250 *CurrentMode
= Mode
;
2257 ConSplitterSyncOutputMode (
2258 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2259 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2263 Routine Description:
2266 Private - Private data structure.
2267 TextOut - Text Out Protocol.
2274 INT32 CurrentMaxMode
;
2277 INT32
*TextOutModeMap
;
2280 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
2287 // Must make sure that current mode won't change even if mode number changes
2289 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
2290 TextOutModeMap
= Private
->TextOutModeMap
;
2291 StepSize
= Private
->TextOutListCount
;
2292 TextOutQueryData
= Private
->TextOutQueryData
;
2295 // Query all the mode that the newly added TextOut supports
2298 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
2299 while (Mode
< TextOut
->Mode
->MaxMode
) {
2300 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
2301 if (EFI_ERROR(Status
)) {
2303 MapTable
[StepSize
] = Mode
;
2304 TextOutQueryData
[Mode
].Columns
= 0;
2305 TextOutQueryData
[Mode
].Rows
= 0;
2311 // Search the intersection map and QueryData database to see if they intersects
2314 while (Index
< CurrentMaxMode
) {
2315 QueryMode
= *(TextOutModeMap
+ Index
* StepSize
);
2316 if ((TextOutQueryData
[QueryMode
].Rows
== Rows
) && (TextOutQueryData
[QueryMode
].Columns
== Columns
)) {
2317 MapTable
[Index
* StepSize
] = Mode
;
2327 // Now search the TextOutModeMap table to find the intersection of supported
2328 // mode between ConSplitter and the newly added device.
2330 ConSplitterGetIntersection (
2335 &Private
->TextOutMode
.MaxMode
,
2336 &Private
->TextOutMode
.Mode
2344 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2349 Routine Description:
2356 EFI_OUT_OF_RESOURCES
2360 UINTN ConOutNumOfConsoles
;
2361 UINTN StdErrNumOfConsoles
;
2362 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
2363 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
2367 UINTN ConOutColumns
;
2369 UINTN StdErrColumns
;
2370 INT32 ConOutMaxMode
;
2371 INT32 StdErrMaxMode
;
2376 INT32
*ConOutModeMap
;
2377 INT32
*StdErrModeMap
;
2378 INT32
*ConOutMapTable
;
2379 INT32
*StdErrMapTable
;
2380 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
2381 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
2382 UINTN ConOutStepSize
;
2383 UINTN StdErrStepSize
;
2384 BOOLEAN FoundTheSameTextOut
;
2385 UINTN ConOutMapTableSize
;
2386 UINTN StdErrMapTableSize
;
2388 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
2389 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
2390 ConOutTextOutList
= mConOut
.TextOutList
;
2391 StdErrTextOutList
= mStdErr
.TextOutList
;
2394 FoundTheSameTextOut
= FALSE
;
2395 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
2397 while (Indexj
< StdErrNumOfConsoles
) {
2398 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
2399 FoundTheSameTextOut
= TRUE
;
2404 StdErrTextOutList
++;
2408 ConOutTextOutList
++;
2411 if (!FoundTheSameTextOut
) {
2415 // Must make sure that current mode won't change even if mode number changes
2417 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
2418 ConOutModeMap
= mConOut
.TextOutModeMap
;
2419 ConOutStepSize
= mConOut
.TextOutListCount
;
2420 ConOutQueryData
= mConOut
.TextOutQueryData
;
2422 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
2423 StdErrModeMap
= mStdErr
.TextOutModeMap
;
2424 StdErrStepSize
= mStdErr
.TextOutListCount
;
2425 StdErrQueryData
= mStdErr
.TextOutQueryData
;
2428 // Allocate the map table and set the map table's index to -1.
2430 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
2431 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
2432 if (ConOutMapTable
== NULL
) {
2433 return EFI_OUT_OF_RESOURCES
;
2436 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
2438 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
2439 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
2440 if (StdErrMapTable
== NULL
) {
2441 return EFI_OUT_OF_RESOURCES
;
2444 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
2447 // Find the intersection of the two set of modes. If they actually intersect, the
2448 // correponding entry in the map table is set to 1.
2451 while (Mode
< ConOutMaxMode
) {
2453 // Search the intersection map and QueryData database to see if they intersect
2456 ConOutMode
= *(ConOutModeMap
+ Mode
* ConOutStepSize
);
2457 ConOutRows
= ConOutQueryData
[ConOutMode
].Rows
;
2458 ConOutColumns
= ConOutQueryData
[ConOutMode
].Columns
;
2459 while (Index
< StdErrMaxMode
) {
2460 StdErrMode
= *(StdErrModeMap
+ Index
* StdErrStepSize
);
2461 StdErrRows
= StdErrQueryData
[StdErrMode
].Rows
;
2462 StdErrColumns
= StdErrQueryData
[StdErrMode
].Columns
;
2463 if ((StdErrRows
== ConOutRows
) && (StdErrColumns
== ConOutColumns
)) {
2464 ConOutMapTable
[Mode
] = 1;
2465 StdErrMapTable
[Index
] = 1;
2475 // Now search the TextOutModeMap table to find the intersection of supported
2476 // mode between ConSplitter and the newly added device.
2478 ConSplitterGetIntersection (
2481 mConOut
.TextOutListCount
,
2483 &(mConOut
.TextOutMode
.MaxMode
),
2484 &(mConOut
.TextOutMode
.Mode
)
2486 if (mConOut
.TextOutMode
.Mode
< 0) {
2487 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2490 ConSplitterGetIntersection (
2493 mStdErr
.TextOutListCount
,
2495 &(mStdErr
.TextOutMode
.MaxMode
),
2496 &(mStdErr
.TextOutMode
.Mode
)
2498 if (mStdErr
.TextOutMode
.Mode
< 0) {
2499 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2502 FreePool (ConOutMapTable
);
2503 FreePool (StdErrMapTable
);
2510 ConSplitterAddGraphicsOutputMode (
2511 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2512 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2513 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2517 Routine Description:
2530 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
2532 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2533 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2534 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*ModeBuffer
;
2535 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*MatchedMode
;
2538 BOOLEAN AlreadyExist
;
2539 UINT32 UgaHorizontalResolution
;
2540 UINT32 UgaVerticalResolution
;
2541 UINT32 UgaColorDepth
;
2542 UINT32 UgaRefreshRate
;
2544 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2545 return EFI_UNSUPPORTED
;
2548 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2553 if (Private
->CurrentNumberOfUgaDraw
!= 0) {
2555 // If any UGA device has already been added, then there is no need to
2556 // calculate intersection of display mode of different GOP/UGA device,
2557 // since only one display mode will be exported (i.e. user-defined mode)
2562 if (GraphicsOutput
!= NULL
) {
2563 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2565 // This is the first Graphics Output device added
2567 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2568 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2569 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2570 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2571 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2572 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2575 // Allocate resource for the private mode buffer
2577 ModeBuffer
= AllocatePool (GraphicsOutput
->Mode
->SizeOfInfo
* GraphicsOutput
->Mode
->MaxMode
);
2578 if (ModeBuffer
== NULL
) {
2579 return EFI_OUT_OF_RESOURCES
;
2581 FreePool (Private
->GraphicsOutputModeBuffer
);
2582 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2585 // Store all supported display modes to the private mode buffer
2588 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2589 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2590 if (EFI_ERROR (Status
)) {
2593 CopyMem (Mode
, Info
, SizeOfInfo
);
2599 // Check intersection of display mode
2601 ModeBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
) * CurrentGraphicsOutputMode
->MaxMode
);
2602 if (ModeBuffer
== NULL
) {
2603 return EFI_OUT_OF_RESOURCES
;
2606 MatchedMode
= ModeBuffer
;
2607 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2608 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2611 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2612 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2613 if (EFI_ERROR (Status
)) {
2616 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2617 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2626 AlreadyExist
= FALSE
;
2628 for (Info
= ModeBuffer
; Info
< MatchedMode
; Info
++) {
2629 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2630 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2631 AlreadyExist
= TRUE
;
2636 if (!AlreadyExist
) {
2637 CopyMem (MatchedMode
, Mode
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2640 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly
2642 MatchedMode
->Version
= 0;
2643 MatchedMode
->PixelFormat
= PixelBltOnly
;
2644 ZeroMem (&MatchedMode
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2654 // Drop the old mode buffer, assign it to a new one
2656 FreePool (Private
->GraphicsOutputModeBuffer
);
2657 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2660 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2662 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2663 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2664 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2665 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2666 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2667 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2671 // Graphics console driver can ensure the same mode for all GOP devices
2673 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2674 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2675 if ((Mode
->HorizontalResolution
== GraphicsOutput
->Mode
->Info
->HorizontalResolution
) &&
2676 (Mode
->VerticalResolution
== GraphicsOutput
->Mode
->Info
->VerticalResolution
)) {
2677 CurrentIndex
= Index
;
2681 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2683 // if user defined mode is not found, set to default mode 800x600
2685 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2686 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2687 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2688 CurrentIndex
= Index
;
2694 if (UgaDraw
!= NULL
) {
2696 // Graphics console driver can ensure the same mode for all GOP devices
2697 // so we can get the current mode from this video device
2701 &UgaHorizontalResolution
,
2702 &UgaVerticalResolution
,
2707 CurrentGraphicsOutputMode
->MaxMode
= 1;
2708 Info
= CurrentGraphicsOutputMode
->Info
;
2710 Info
->HorizontalResolution
= UgaHorizontalResolution
;
2711 Info
->VerticalResolution
= UgaVerticalResolution
;
2712 Info
->PixelFormat
= PixelBltOnly
;
2713 Info
->PixelsPerScanLine
= UgaHorizontalResolution
;
2714 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2715 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2716 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2719 // Update the private mode buffer
2721 CopyMem (&Private
->GraphicsOutputModeBuffer
[0], Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2724 // Only mode 0 is available to be set
2731 if (GraphicsOutput
!= NULL
) {
2732 Private
->CurrentNumberOfGraphicsOutput
++;
2734 if (UgaDraw
!= NULL
) {
2735 Private
->CurrentNumberOfUgaDraw
++;
2739 // Force GraphicsOutput mode to be set,
2740 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2742 Private
->HardwareNeedsStarting
= TRUE
;
2744 // Current mode number may need update now, so set it to an invalid mode number
2746 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2748 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.
2750 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) CurrentIndex
);
2753 // If user defined mode is not valid for UGA, set to the default mode 800x600.
2755 if (EFI_ERROR(Status
)) {
2756 (Private
->GraphicsOutputModeBuffer
[0]).HorizontalResolution
= 800;
2757 (Private
->GraphicsOutputModeBuffer
[0]).VerticalResolution
= 600;
2758 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, 0);
2765 ConSplitterTextOutAddDevice (
2766 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2767 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2768 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2769 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2773 Routine Description:
2784 UINTN CurrentNumOfConsoles
;
2787 UINT32 UgaHorizontalResolution
;
2788 UINT32 UgaVerticalResolution
;
2789 UINT32 UgaColorDepth
;
2790 UINT32 UgaRefreshRate
;
2791 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2793 Status
= EFI_SUCCESS
;
2794 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2797 // If the Text Out List is full, enlarge it by calling growbuffer().
2799 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2800 Status
= ConSplitterGrowBuffer (
2801 sizeof (TEXT_OUT_AND_GOP_DATA
),
2802 &Private
->TextOutListCount
,
2803 (VOID
**) &Private
->TextOutList
2805 if (EFI_ERROR (Status
)) {
2806 return EFI_OUT_OF_RESOURCES
;
2809 // Also need to reallocate the TextOutModeMap table
2811 Status
= ConSplitterGrowMapTable (Private
);
2812 if (EFI_ERROR (Status
)) {
2813 return EFI_OUT_OF_RESOURCES
;
2817 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2819 TextAndGop
->TextOut
= TextOut
;
2820 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2821 TextAndGop
->UgaDraw
= UgaDraw
;
2823 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2825 // If No GOP/UGA device then use the ConOut device
2827 TextAndGop
->TextOutEnabled
= TRUE
;
2830 // If GOP/UGA device use ConOut device only used if screen is in Text mode
2832 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2835 if (CurrentNumOfConsoles
== 0) {
2837 // Add the first device's output mode to console splitter's mode list
2839 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2841 ConSplitterSyncOutputMode (Private
, TextOut
);
2844 Private
->CurrentNumberOfConsoles
++;
2847 // Scan both TextOutList, for the intersection TextOut device
2848 // maybe both ConOut and StdErr incorporate the same Text Out
2849 // device in them, thus the output of both should be synced.
2851 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2853 CurrentMode
= Private
->TextOutMode
.Mode
;
2854 MaxMode
= Private
->TextOutMode
.MaxMode
;
2855 ASSERT (MaxMode
>= 1);
2858 // Update DevNull mode according to current video device
2860 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2861 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2862 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2865 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2866 if (UgaDraw
!= NULL
) {
2867 Status
= UgaDraw
->GetMode (
2869 &UgaHorizontalResolution
,
2870 &UgaVerticalResolution
,
2874 if (!EFI_ERROR (Status
)) {
2875 Status
= ConSpliterUgaDrawSetMode (
2877 UgaHorizontalResolution
,
2878 UgaVerticalResolution
,
2884 // If GetMode/SetMode is failed, set to 800x600 mode
2886 if(EFI_ERROR (Status
)) {
2887 Status
= ConSpliterUgaDrawSetMode (
2898 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2900 // We just added a new GOP or UGA device in graphics mode
2902 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2903 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2904 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2905 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2907 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2909 // The new console supports the same mode of the current console so sync up
2911 DevNullSyncStdOut (Private
);
2914 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2916 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2923 ConSplitterTextOutDeleteDevice (
2924 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2925 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2929 Routine Description:
2940 UINTN CurrentNumOfConsoles
;
2941 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2945 // Remove the specified text-out device data structure from the Text out List,
2946 // and rearrange the remaining data structures in the Text out List.
2948 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2949 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2950 TextOutList
= Private
->TextOutList
;
2951 while (Index
>= 0) {
2952 if (TextOutList
->TextOut
== TextOut
) {
2953 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2954 CurrentNumOfConsoles
--;
2955 if (TextOutList
->UgaDraw
!= NULL
) {
2956 Private
->CurrentNumberOfUgaDraw
--;
2958 if (TextOutList
->GraphicsOutput
!= NULL
) {
2959 Private
->CurrentNumberOfGraphicsOutput
--;
2968 // The specified TextOut is not managed by the ConSplitter driver
2971 return EFI_NOT_FOUND
;
2974 if (CurrentNumOfConsoles
== 0) {
2976 // If the number of consoles is zero clear the Dev NULL device
2978 Private
->CurrentNumberOfConsoles
= 0;
2979 Private
->TextOutMode
.MaxMode
= 1;
2980 Private
->TextOutQueryData
[0].Columns
= 80;
2981 Private
->TextOutQueryData
[0].Rows
= 25;
2982 DevNullTextOutSetMode (Private
, 0);
2987 // Max Mode is realy an intersection of the QueryMode command to all
2988 // devices. So we must copy the QueryMode of the first device to
2992 Private
->TextOutQueryData
,
2993 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2996 FreePool (Private
->TextOutModeMap
);
2997 Private
->TextOutModeMap
= NULL
;
2998 TextOutList
= Private
->TextOutList
;
3001 // Add the first TextOut to the QueryData array and ModeMap table
3003 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
3006 // Now add one by one
3009 Private
->CurrentNumberOfConsoles
= 1;
3011 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
3012 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
3014 Private
->CurrentNumberOfConsoles
++;
3018 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3023 // ConSplitter TextIn member functions
3027 ConSplitterTextInReset (
3028 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3029 IN BOOLEAN ExtendedVerification
3033 Routine Description:
3034 Reset the input device and optionaly run diagnostics
3037 This - Protocol instance pointer.
3038 ExtendedVerification - Driver may perform diagnostics on reset.
3041 EFI_SUCCESS - The device was reset.
3042 EFI_DEVICE_ERROR - The device is not functioning properly and could
3048 EFI_STATUS ReturnStatus
;
3049 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3052 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3054 Private
->KeyEventSignalState
= FALSE
;
3057 // return the worst status met
3059 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3060 Status
= Private
->TextInList
[Index
]->Reset (
3061 Private
->TextInList
[Index
],
3062 ExtendedVerification
3064 if (EFI_ERROR (Status
)) {
3065 ReturnStatus
= Status
;
3069 return ReturnStatus
;
3074 ConSplitterTextInPrivateReadKeyStroke (
3075 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3076 OUT EFI_INPUT_KEY
*Key
3080 Routine Description:
3081 Reads the next keystroke from the input device. The WaitForKey Event can
3082 be used to test for existance of a keystroke via WaitForEvent () call.
3085 This - Protocol instance pointer.
3086 Key - Driver may perform diagnostics on reset.
3089 EFI_SUCCESS - The keystroke information was returned.
3090 EFI_NOT_READY - There was no keystroke data availiable.
3091 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3098 EFI_INPUT_KEY CurrentKey
;
3100 Key
->UnicodeChar
= 0;
3101 Key
->ScanCode
= SCAN_NULL
;
3104 // if no physical console input device exists, return EFI_NOT_READY;
3105 // if any physical console input device has key input,
3106 // return the key and EFI_SUCCESS.
3108 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3109 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
3110 Private
->TextInList
[Index
],
3113 if (!EFI_ERROR (Status
)) {
3119 return EFI_NOT_READY
;
3123 ConSpliterConssoleControlStdInLocked (
3128 Routine Description:
3129 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
3130 the only device locked.
3137 FALSE - StdIn working normally
3141 return mConIn
.PasswordEnabled
;
3146 ConSpliterConsoleControlLockStdInEvent (
3152 Routine Description:
3153 This timer event will fire when StdIn is locked. It will check the key
3154 sequence on StdIn to see if it matches the password. Any error in the
3155 password will cause the check to reset. As long a mConIn.PasswordEnabled is
3156 TRUE the StdIn splitter will not report any input.
3159 (Standard EFI_EVENT_NOTIFY)
3168 CHAR16 BackSpaceString
[2];
3169 CHAR16 SpaceString
[2];
3172 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
3173 if (!EFI_ERROR (Status
)) {
3175 // if it's an ENTER, match password
3177 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
3178 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
3179 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
3181 // Password not match
3183 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
3184 mConIn
.PwdIndex
= 0;
3187 // Key matches password sequence
3189 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
3190 mConIn
.PasswordEnabled
= FALSE
;
3191 Status
= EFI_NOT_READY
;
3193 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
3197 if (mConIn
.PwdIndex
> 0) {
3198 BackSpaceString
[0] = CHAR_BACKSPACE
;
3199 BackSpaceString
[1] = 0;
3201 SpaceString
[0] = ' ';
3204 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
3205 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
3206 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
3210 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
3212 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
3214 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
3215 if (mConIn
.PwdIndex
== 0) {
3216 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
3219 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
3220 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
3225 } while (!EFI_ERROR (Status
));
3230 ConSpliterConsoleControlLockStdIn (
3231 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
3236 Routine Description:
3237 If Password is NULL unlock the password state variable and set the event
3238 timer. If the Password is too big return an error. If the Password is valid
3239 Copy the Password and enable state variable and then arm the periodic timer
3244 EFI_SUCCESS - Lock the StdIn device
3245 EFI_INVALID_PARAMETER - Password is NULL
3246 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
3250 if (Password
== NULL
) {
3251 return EFI_INVALID_PARAMETER
;
3254 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
3256 // Currently have a max password size
3258 return EFI_OUT_OF_RESOURCES
;
3261 // Save the password, initialize state variables and arm event timer
3263 StrCpy (mConIn
.Password
, Password
);
3264 mConIn
.PasswordEnabled
= TRUE
;
3265 mConIn
.PwdIndex
= 0;
3266 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
3273 ConSplitterTextInReadKeyStroke (
3274 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3275 OUT EFI_INPUT_KEY
*Key
3279 Routine Description:
3280 Reads the next keystroke from the input device. The WaitForKey Event can
3281 be used to test for existance of a keystroke via WaitForEvent () call.
3282 If the ConIn is password locked make it look like no keystroke is availible
3285 This - Protocol instance pointer.
3286 Key - Driver may perform diagnostics on reset.
3289 EFI_SUCCESS - The keystroke information was returned.
3290 EFI_NOT_READY - There was no keystroke data availiable.
3291 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3296 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3298 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3299 if (Private
->PasswordEnabled
) {
3301 // If StdIn Locked return not ready
3303 return EFI_NOT_READY
;
3306 Private
->KeyEventSignalState
= FALSE
;
3308 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
3313 ConSplitterTextInWaitForKey (
3319 Routine Description:
3320 This event agregates all the events of the ConIn devices in the spliter.
3321 If the ConIn is password locked then return.
3322 If any events of physical ConIn devices are signaled, signal the ConIn
3323 spliter event. This will cause the calling code to call
3324 ConSplitterTextInReadKeyStroke ().
3327 Event - The Event assoicated with callback.
3328 Context - Context registered when Event was created.
3336 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3339 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3340 if (Private
->PasswordEnabled
) {
3342 // If StdIn Locked return not ready
3348 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3350 if (Private
->KeyEventSignalState
) {
3351 gBS
->SignalEvent (Event
);
3355 // if any physical console input device has key input, signal the event.
3357 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3358 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
3359 if (!EFI_ERROR (Status
)) {
3360 gBS
->SignalEvent (Event
);
3361 Private
->KeyEventSignalState
= TRUE
;
3370 IN EFI_KEY_DATA
*RegsiteredData
,
3371 IN EFI_KEY_DATA
*InputData
3375 Routine Description:
3379 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
3380 state data for the key that was registered.
3381 InputData - A pointer to a buffer that is filled in with the keystroke
3382 state data for the key that was pressed.
3385 TRUE - Key be pressed matches a registered key.
3386 FLASE - Match failed.
3390 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
3392 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
3393 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
3398 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3400 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
3401 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
3404 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
3405 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
3414 // Simple Text Input Ex protocol functions
3419 ConSplitterTextInResetEx (
3420 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3421 IN BOOLEAN ExtendedVerification
3425 Routine Description:
3426 Reset the input device and optionaly run diagnostics
3429 This - Protocol instance pointer.
3430 ExtendedVerification - Driver may perform diagnostics on reset.
3433 EFI_SUCCESS - The device was reset.
3434 EFI_DEVICE_ERROR - The device is not functioning properly and could
3440 EFI_STATUS ReturnStatus
;
3441 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3444 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3446 Private
->KeyEventSignalState
= FALSE
;
3449 // return the worst status met
3451 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3452 Status
= Private
->TextInExList
[Index
]->Reset (
3453 Private
->TextInExList
[Index
],
3454 ExtendedVerification
3456 if (EFI_ERROR (Status
)) {
3457 ReturnStatus
= Status
;
3461 return ReturnStatus
;
3467 ConSplitterTextInReadKeyStrokeEx (
3468 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3469 OUT EFI_KEY_DATA
*KeyData
3473 Routine Description:
3474 Reads the next keystroke from the input device. The WaitForKey Event can
3475 be used to test for existance of a keystroke via WaitForEvent () call.
3478 This - Protocol instance pointer.
3479 KeyData - A pointer to a buffer that is filled in with the keystroke
3480 state data for the key that was pressed.
3483 EFI_SUCCESS - The keystroke information was returned.
3484 EFI_NOT_READY - There was no keystroke data availiable.
3485 EFI_DEVICE_ERROR - The keystroke information was not returned due to
3487 EFI_INVALID_PARAMETER - KeyData is NULL.
3491 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3494 EFI_KEY_DATA CurrentKeyData
;
3497 if (KeyData
== NULL
) {
3498 return EFI_INVALID_PARAMETER
;
3501 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3502 if (Private
->PasswordEnabled
) {
3504 // If StdIn Locked return not ready
3506 return EFI_NOT_READY
;
3509 Private
->KeyEventSignalState
= FALSE
;
3511 KeyData
->Key
.UnicodeChar
= 0;
3512 KeyData
->Key
.ScanCode
= SCAN_NULL
;
3515 // if no physical console input device exists, return EFI_NOT_READY;
3516 // if any physical console input device has key input,
3517 // return the key and EFI_SUCCESS.
3519 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3520 Status
= Private
->TextInExList
[Index
]->ReadKeyStrokeEx (
3521 Private
->TextInExList
[Index
],
3524 if (!EFI_ERROR (Status
)) {
3525 CopyMem (KeyData
, &CurrentKeyData
, sizeof (CurrentKeyData
));
3530 return EFI_NOT_READY
;
3535 ConSplitterTextInSetState (
3536 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3537 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
3541 Routine Description:
3542 Set certain state for the input device.
3545 This - Protocol instance pointer.
3546 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
3547 state for the input device.
3550 EFI_SUCCESS - The device state was set successfully.
3551 EFI_DEVICE_ERROR - The device is not functioning correctly and could
3552 not have the setting adjusted.
3553 EFI_UNSUPPORTED - The device does not have the ability to set its state.
3554 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
3558 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3562 if (KeyToggleState
== NULL
) {
3563 return EFI_INVALID_PARAMETER
;
3566 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3569 // if no physical console input device exists, return EFI_SUCCESS;
3570 // otherwise return the status of setting state of physical console input device
3572 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3573 Status
= Private
->TextInExList
[Index
]->SetState (
3574 Private
->TextInExList
[Index
],
3577 if (EFI_ERROR (Status
)) {
3588 ConSplitterTextInRegisterKeyNotify (
3589 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3590 IN EFI_KEY_DATA
*KeyData
,
3591 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
3592 OUT EFI_HANDLE
*NotifyHandle
3596 Routine Description:
3597 Register a notification function for a particular keystroke for the input device.
3600 This - Protocol instance pointer.
3601 KeyData - A pointer to a buffer that is filled in with the keystroke
3602 information data for the key that was pressed.
3603 KeyNotificationFunction - Points to the function to be called when the key
3604 sequence is typed specified by KeyData.
3605 NotifyHandle - Points to the unique handle assigned to the registered notification.
3608 EFI_SUCCESS - The notification function was registered successfully.
3609 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
3610 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
3614 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3617 TEXT_IN_EX_SPLITTER_NOTIFY
*NewNotify
;
3619 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3622 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
3623 return EFI_INVALID_PARAMETER
;
3626 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3629 // if no physical console input device exists,
3630 // return EFI_SUCCESS directly.
3632 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3637 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3639 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3640 CurrentNotify
= CR (
3642 TEXT_IN_EX_SPLITTER_NOTIFY
,
3644 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
3646 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
3647 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
3648 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
3655 // Allocate resource to save the notification function
3657 NewNotify
= (TEXT_IN_EX_SPLITTER_NOTIFY
*) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY
));
3658 if (NewNotify
== NULL
) {
3659 return EFI_OUT_OF_RESOURCES
;
3661 NewNotify
->NotifyHandleList
= (EFI_HANDLE
*) AllocateZeroPool (sizeof (EFI_HANDLE
) * Private
->CurrentNumberOfExConsoles
);
3662 if (NewNotify
->NotifyHandleList
== NULL
) {
3663 gBS
->FreePool (NewNotify
);
3664 return EFI_OUT_OF_RESOURCES
;
3666 NewNotify
->Signature
= TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
;
3667 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
3668 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
3671 // Return the wrong status of registering key notify of
3672 // physical console input device if meet problems
3674 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3675 Status
= Private
->TextInExList
[Index
]->RegisterKeyNotify (
3676 Private
->TextInExList
[Index
],
3678 KeyNotificationFunction
,
3679 &NewNotify
->NotifyHandleList
[Index
]
3681 if (EFI_ERROR (Status
)) {
3682 gBS
->FreePool (NewNotify
->NotifyHandleList
);
3683 gBS
->FreePool (NewNotify
);
3689 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
3691 Status
= gBS
->InstallMultipleProtocolInterfaces (
3692 &NewNotify
->NotifyHandle
,
3693 &gSimpleTextInExNotifyGuid
,
3697 ASSERT_EFI_ERROR (Status
);
3699 InsertTailList (&mConIn
.NotifyList
, &NewNotify
->NotifyEntry
);
3701 *NotifyHandle
= NewNotify
->NotifyHandle
;
3709 ConSplitterTextInUnregisterKeyNotify (
3710 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3711 IN EFI_HANDLE NotificationHandle
3715 Routine Description:
3716 Remove a registered notification function from a particular keystroke.
3719 This - Protocol instance pointer.
3720 NotificationHandle - The handle of the notification function being unregistered.
3723 EFI_SUCCESS - The notification function was unregistered successfully.
3724 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
3725 EFI_NOT_FOUND - Can not find the matching entry in database.
3729 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3732 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3735 if (NotificationHandle
== NULL
) {
3736 return EFI_INVALID_PARAMETER
;
3739 Status
= gBS
->OpenProtocol (
3741 &gSimpleTextInExNotifyGuid
,
3745 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
3747 if (EFI_ERROR (Status
)) {
3748 return EFI_INVALID_PARAMETER
;
3751 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3754 // if no physical console input device exists,
3755 // return EFI_SUCCESS directly.
3757 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3761 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3762 CurrentNotify
= CR (Link
, TEXT_IN_EX_SPLITTER_NOTIFY
, NotifyEntry
, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
);
3763 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
3764 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3765 Status
= Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3766 Private
->TextInExList
[Index
],
3767 CurrentNotify
->NotifyHandleList
[Index
]
3769 if (EFI_ERROR (Status
)) {
3773 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
3774 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3775 CurrentNotify
->NotifyHandle
,
3776 &gSimpleTextInExNotifyGuid
,
3780 ASSERT_EFI_ERROR (Status
);
3781 gBS
->FreePool (CurrentNotify
->NotifyHandleList
);
3782 gBS
->FreePool (CurrentNotify
);
3787 return EFI_NOT_FOUND
;
3793 ConSplitterSimplePointerReset (
3794 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3795 IN BOOLEAN ExtendedVerification
3799 Routine Description:
3800 Reset the input device and optionaly run diagnostics
3803 This - Protocol instance pointer.
3804 ExtendedVerification - Driver may perform diagnostics on reset.
3807 EFI_SUCCESS - The device was reset.
3808 EFI_DEVICE_ERROR - The device is not functioning properly and could
3814 EFI_STATUS ReturnStatus
;
3815 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3818 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3820 Private
->InputEventSignalState
= FALSE
;
3822 if (Private
->CurrentNumberOfPointers
== 0) {
3826 // return the worst status met
3828 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3829 Status
= Private
->PointerList
[Index
]->Reset (
3830 Private
->PointerList
[Index
],
3831 ExtendedVerification
3833 if (EFI_ERROR (Status
)) {
3834 ReturnStatus
= Status
;
3838 return ReturnStatus
;
3844 ConSplitterSimplePointerPrivateGetState (
3845 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3846 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3850 Routine Description:
3851 Reads the next keystroke from the input device. The WaitForKey Event can
3852 be used to test for existance of a keystroke via WaitForEvent () call.
3855 This - Protocol instance pointer.
3859 EFI_SUCCESS - The keystroke information was returned.
3860 EFI_NOT_READY - There was no keystroke data availiable.
3861 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3867 EFI_STATUS ReturnStatus
;
3869 EFI_SIMPLE_POINTER_STATE CurrentState
;
3871 State
->RelativeMovementX
= 0;
3872 State
->RelativeMovementY
= 0;
3873 State
->RelativeMovementZ
= 0;
3874 State
->LeftButton
= FALSE
;
3875 State
->RightButton
= FALSE
;
3878 // if no physical console input device exists, return EFI_NOT_READY;
3879 // if any physical console input device has key input,
3880 // return the key and EFI_SUCCESS.
3882 ReturnStatus
= EFI_NOT_READY
;
3883 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3885 Status
= Private
->PointerList
[Index
]->GetState (
3886 Private
->PointerList
[Index
],
3889 if (!EFI_ERROR (Status
)) {
3890 if (ReturnStatus
== EFI_NOT_READY
) {
3891 ReturnStatus
= EFI_SUCCESS
;
3894 if (CurrentState
.LeftButton
) {
3895 State
->LeftButton
= TRUE
;
3898 if (CurrentState
.RightButton
) {
3899 State
->RightButton
= TRUE
;
3902 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
3903 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
3906 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
3907 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
3910 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
3911 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
3913 } else if (Status
== EFI_DEVICE_ERROR
) {
3914 ReturnStatus
= EFI_DEVICE_ERROR
;
3918 return ReturnStatus
;
3923 ConSplitterSimplePointerGetState (
3924 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3925 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3929 Routine Description:
3930 Reads the next keystroke from the input device. The WaitForKey Event can
3931 be used to test for existance of a keystroke via WaitForEvent () call.
3932 If the ConIn is password locked make it look like no keystroke is availible
3935 This - Protocol instance pointer.
3939 EFI_SUCCESS - The keystroke information was returned.
3940 EFI_NOT_READY - There was no keystroke data availiable.
3941 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3946 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3948 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3949 if (Private
->PasswordEnabled
) {
3951 // If StdIn Locked return not ready
3953 return EFI_NOT_READY
;
3956 Private
->InputEventSignalState
= FALSE
;
3958 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
3963 ConSplitterSimplePointerWaitForInput (
3969 Routine Description:
3970 This event agregates all the events of the ConIn devices in the spliter.
3971 If the ConIn is password locked then return.
3972 If any events of physical ConIn devices are signaled, signal the ConIn
3973 spliter event. This will cause the calling code to call
3974 ConSplitterTextInReadKeyStroke ().
3977 Event - The Event assoicated with callback.
3978 Context - Context registered when Event was created.
3986 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3989 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3990 if (Private
->PasswordEnabled
) {
3992 // If StdIn Locked return not ready
3998 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
4000 if (Private
->InputEventSignalState
) {
4001 gBS
->SignalEvent (Event
);
4005 // if any physical console input device has key input, signal the event.
4007 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
4008 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
4009 if (!EFI_ERROR (Status
)) {
4010 gBS
->SignalEvent (Event
);
4011 Private
->InputEventSignalState
= TRUE
;
4017 // Absolute Pointer Protocol functions
4022 ConSplitterAbsolutePointerReset (
4023 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4024 IN BOOLEAN ExtendedVerification
4028 Routine Description:
4029 Resets the pointer device hardware.
4032 This - Protocol instance pointer.
4033 ExtendedVerification - Driver may perform diagnostics on reset.
4036 EFI_SUCCESS - The device was reset.
4037 EFI_DEVICE_ERROR - The device is not functioning correctly and could
4043 EFI_STATUS ReturnStatus
;
4044 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4047 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4049 Private
->AbsoluteInputEventSignalState
= FALSE
;
4051 if (Private
->CurrentNumberOfAbsolutePointers
== 0) {
4055 // return the worst status met
4057 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4058 Status
= Private
->AbsolutePointerList
[Index
]->Reset (
4059 Private
->AbsolutePointerList
[Index
],
4060 ExtendedVerification
4062 if (EFI_ERROR (Status
)) {
4063 ReturnStatus
= Status
;
4067 return ReturnStatus
;
4072 ConSplitterAbsolutePointerGetState (
4073 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4074 IN OUT EFI_ABSOLUTE_POINTER_STATE
*State
4078 Routine Description:
4079 Retrieves the current state of a pointer device.
4082 This - Protocol instance pointer.
4083 State - A pointer to the state information on the pointer device.
4086 EFI_SUCCESS - The state of the pointer device was returned in State..
4087 EFI_NOT_READY - The state of the pointer device has not changed since the last call to
4089 EFI_DEVICE_ERROR - A device error occurred while attempting to retrieve the pointer
4090 device's current state.
4093 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4095 EFI_STATUS ReturnStatus
;
4097 EFI_ABSOLUTE_POINTER_STATE CurrentState
;
4100 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4101 if (Private
->PasswordEnabled
) {
4103 // If StdIn Locked return not ready
4105 return EFI_NOT_READY
;
4108 Private
->AbsoluteInputEventSignalState
= FALSE
;
4110 State
->CurrentX
= 0;
4111 State
->CurrentY
= 0;
4112 State
->CurrentZ
= 0;
4113 State
->ActiveButtons
= 0;
4116 // if no physical pointer device exists, return EFI_NOT_READY;
4117 // if any physical pointer device has changed state,
4118 // return the state and EFI_SUCCESS.
4120 ReturnStatus
= EFI_NOT_READY
;
4121 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4123 Status
= Private
->AbsolutePointerList
[Index
]->GetState (
4124 Private
->AbsolutePointerList
[Index
],
4127 if (!EFI_ERROR (Status
)) {
4128 if (ReturnStatus
== EFI_NOT_READY
) {
4129 ReturnStatus
= EFI_SUCCESS
;
4132 State
->ActiveButtons
= CurrentState
.ActiveButtons
;
4134 if (!(Private
->AbsolutePointerMode
.AbsoluteMinX
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxX
== 0)) {
4135 State
->CurrentX
= CurrentState
.CurrentX
;
4137 if (!(Private
->AbsolutePointerMode
.AbsoluteMinY
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxY
== 0)) {
4138 State
->CurrentY
= CurrentState
.CurrentY
;
4140 if (!(Private
->AbsolutePointerMode
.AbsoluteMinZ
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxZ
== 0)) {
4141 State
->CurrentZ
= CurrentState
.CurrentZ
;
4144 } else if (Status
== EFI_DEVICE_ERROR
) {
4145 ReturnStatus
= EFI_DEVICE_ERROR
;
4149 return ReturnStatus
;
4154 ConSplitterAbsolutePointerWaitForInput (
4160 Routine Description:
4161 This event agregates all the events of the pointer devices in the splitter.
4162 If the ConIn is password locked then return.
4163 If any events of physical pointer devices are signaled, signal the pointer
4164 splitter event. This will cause the calling code to call
4165 ConSplitterAbsolutePointerGetState ().
4168 Event - The Event assoicated with callback.
4169 Context - Context registered when Event was created.
4177 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4180 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
4181 if (Private
->PasswordEnabled
) {
4183 // If StdIn Locked return not ready
4189 // if AbsoluteInputEventSignalState is flagged before,
4190 // and not cleared by Reset() or GetState(), signal it
4192 if (Private
->AbsoluteInputEventSignalState
) {
4193 gBS
->SignalEvent (Event
);
4197 // if any physical console input device has key input, signal the event.
4199 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4200 Status
= gBS
->CheckEvent (Private
->AbsolutePointerList
[Index
]->WaitForInput
);
4201 if (!EFI_ERROR (Status
)) {
4202 gBS
->SignalEvent (Event
);
4203 Private
->AbsoluteInputEventSignalState
= TRUE
;
4210 ConSplitterTextOutReset (
4211 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4212 IN BOOLEAN ExtendedVerification
4216 Routine Description:
4217 Reset the text output device hardware and optionaly run diagnostics
4220 This - Protocol instance pointer.
4221 ExtendedVerification - Driver may perform more exhaustive verfication
4222 operation of the device during reset.
4225 EFI_SUCCESS - The text output device was reset.
4226 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
4232 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4234 EFI_STATUS ReturnStatus
;
4236 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4239 // return the worst status met
4241 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4243 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4245 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
4246 Private
->TextOutList
[Index
].TextOut
,
4247 ExtendedVerification
4249 if (EFI_ERROR (Status
)) {
4250 ReturnStatus
= Status
;
4255 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
4257 Status
= DevNullTextOutSetMode (Private
, 0);
4258 if (EFI_ERROR (Status
)) {
4259 ReturnStatus
= Status
;
4262 return ReturnStatus
;
4267 ConSplitterTextOutOutputString (
4268 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4273 Routine Description:
4274 Write a Unicode string to the output device.
4277 This - Protocol instance pointer.
4278 String - The NULL-terminated Unicode string to be displayed on the output
4279 device(s). All output devices must also support the Unicode
4280 drawing defined in this file.
4283 EFI_SUCCESS - The string was output to the device.
4284 EFI_DEVICE_ERROR - The device reported an error while attempting to output
4286 EFI_UNSUPPORTED - The output device's mode is not currently in a
4288 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
4289 characters in the Unicode string could not be
4290 rendered and were skipped.
4295 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4297 UINTN BackSpaceCount
;
4298 EFI_STATUS ReturnStatus
;
4299 CHAR16
*TargetString
;
4301 This
->SetAttribute (This
, This
->Mode
->Attribute
);
4303 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4306 for (TargetString
= WString
; *TargetString
; TargetString
++) {
4307 if (*TargetString
== CHAR_BACKSPACE
) {
4313 if (BackSpaceCount
== 0) {
4314 TargetString
= WString
;
4316 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
4317 StrCpy (TargetString
, WString
);
4320 // return the worst status met
4322 Status
= DevNullTextOutOutputString (Private
, TargetString
);
4323 if (EFI_ERROR (Status
)) {
4324 ReturnStatus
= Status
;
4327 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4329 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4330 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
4331 Private
->TextOutList
[Index
].TextOut
,
4334 if (EFI_ERROR (Status
)) {
4335 ReturnStatus
= Status
;
4340 if (BackSpaceCount
) {
4341 FreePool (TargetString
);
4344 return ReturnStatus
;
4349 ConSplitterTextOutTestString (
4350 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4355 Routine Description:
4356 Verifies that all characters in a Unicode string can be output to the
4360 This - Protocol instance pointer.
4361 String - The NULL-terminated Unicode string to be examined for the output
4365 EFI_SUCCESS - The device(s) are capable of rendering the output string.
4366 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
4367 rendered by one or more of the output devices mapped
4373 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4375 EFI_STATUS ReturnStatus
;
4377 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4380 // return the worst status met
4382 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4383 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4384 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
4385 Private
->TextOutList
[Index
].TextOut
,
4388 if (EFI_ERROR (Status
)) {
4389 ReturnStatus
= Status
;
4394 // There is no DevNullTextOutTestString () since a Unicode buffer would
4395 // always return EFI_SUCCESS.
4396 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4398 return ReturnStatus
;
4403 ConSplitterTextOutQueryMode (
4404 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4405 IN UINTN ModeNumber
,
4411 Routine Description:
4412 Returns information for an available text mode that the output device(s)
4416 This - Protocol instance pointer.
4417 ModeNumber - The mode number to return information on.
4418 Columns, Rows - Returns the geometry of the text output device for the
4419 requested ModeNumber.
4422 EFI_SUCCESS - The requested mode information was returned.
4423 EFI_DEVICE_ERROR - The device had an error and could not
4424 complete the request.
4425 EFI_UNSUPPORTED - The mode number was not valid.
4429 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4431 INT32
*TextOutModeMap
;
4433 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4436 // Check whether param ModeNumber is valid.
4437 // ModeNumber should be within range 0 ~ MaxMode - 1.
4439 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4440 return EFI_UNSUPPORTED
;
4443 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4444 return EFI_UNSUPPORTED
;
4448 // We get the available mode from mode intersection map if it's available
4450 if (Private
->TextOutModeMap
!= NULL
) {
4451 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4452 CurrentMode
= (UINTN
)(*TextOutModeMap
);
4453 *Columns
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4454 *Rows
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4456 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
4457 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
4460 if (*Columns
<= 0 && *Rows
<= 0) {
4461 return EFI_UNSUPPORTED
;
4470 ConSplitterTextOutSetMode (
4471 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4476 Routine Description:
4477 Sets the output device(s) to a specified mode.
4480 This - Protocol instance pointer.
4481 ModeNumber - The mode number to set.
4484 EFI_SUCCESS - The requested text mode was set.
4485 EFI_DEVICE_ERROR - The device had an error and
4486 could not complete the request.
4487 EFI_UNSUPPORTED - The mode number was not valid.
4492 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4494 INT32
*TextOutModeMap
;
4495 EFI_STATUS ReturnStatus
;
4497 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4500 // Check whether param ModeNumber is valid.
4501 // ModeNumber should be within range 0 ~ MaxMode - 1.
4503 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4504 return EFI_UNSUPPORTED
;
4507 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4508 return EFI_UNSUPPORTED
;
4511 // If the mode is being set to the curent mode, then just clear the screen and return.
4513 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
4514 return ConSplitterTextOutClearScreen (This
);
4517 // return the worst status met
4519 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4520 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4522 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4523 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
4524 Private
->TextOutList
[Index
].TextOut
,
4525 TextOutModeMap
[Index
]
4528 // If this console device is based on a GOP or UGA device, then sync up the bitmap from
4529 // the GOP/UGA splitter and reclear the text portion of the display in the new mode.
4531 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
4532 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4535 if (EFI_ERROR (Status
)) {
4536 ReturnStatus
= Status
;
4541 // The DevNull Console will support any possible mode as it allocates memory
4543 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
4544 if (EFI_ERROR (Status
)) {
4545 ReturnStatus
= Status
;
4548 return ReturnStatus
;
4553 ConSplitterTextOutSetAttribute (
4554 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4559 Routine Description:
4560 Sets the background and foreground colors for the OutputString () and
4561 ClearScreen () functions.
4564 This - Protocol instance pointer.
4565 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
4566 bits 4..6 are the background color. All other bits are undefined
4567 and must be zero. The valid Attributes are defined in this file.
4570 EFI_SUCCESS - The attribute was set.
4571 EFI_DEVICE_ERROR - The device had an error and
4572 could not complete the request.
4573 EFI_UNSUPPORTED - The attribute requested is not defined.
4578 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4580 EFI_STATUS ReturnStatus
;
4582 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4585 // Check whether param Attribute is valid.
4587 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4588 return EFI_UNSUPPORTED
;
4592 // return the worst status met
4594 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4596 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4597 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
4598 Private
->TextOutList
[Index
].TextOut
,
4601 if (EFI_ERROR (Status
)) {
4602 ReturnStatus
= Status
;
4607 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
4609 return ReturnStatus
;
4614 ConSplitterTextOutClearScreen (
4615 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
4619 Routine Description:
4620 Clears the output device(s) display to the currently selected background
4624 This - Protocol instance pointer.
4627 EFI_SUCCESS - The operation completed successfully.
4628 EFI_DEVICE_ERROR - The device had an error and
4629 could not complete the request.
4630 EFI_UNSUPPORTED - The output device is not in a valid text mode.
4635 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4637 EFI_STATUS ReturnStatus
;
4639 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4642 // return the worst status met
4644 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4646 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4647 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4648 if (EFI_ERROR (Status
)) {
4649 ReturnStatus
= Status
;
4654 Status
= DevNullTextOutClearScreen (Private
);
4655 if (EFI_ERROR (Status
)) {
4656 ReturnStatus
= Status
;
4659 return ReturnStatus
;
4664 ConSplitterTextOutSetCursorPosition (
4665 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4671 Routine Description:
4672 Sets the current coordinates of the cursor position
4675 This - Protocol instance pointer.
4676 Column, Row - the position to set the cursor to. Must be greater than or
4677 equal to zero and less than the number of columns and rows
4681 EFI_SUCCESS - The operation completed successfully.
4682 EFI_DEVICE_ERROR - The device had an error and
4683 could not complete the request.
4684 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
4685 cursor position is invalid for the current mode.
4690 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4692 EFI_STATUS ReturnStatus
;
4695 INT32
*TextOutModeMap
;
4699 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4700 TextOutModeMap
= NULL
;
4701 ModeNumber
= Private
->TextOutMode
.Mode
;
4704 // Get current MaxColumn and MaxRow from intersection map
4706 if (Private
->TextOutModeMap
!= NULL
) {
4707 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4708 CurrentMode
= *TextOutModeMap
;
4710 CurrentMode
= ModeNumber
;
4713 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4714 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4716 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
4717 return EFI_UNSUPPORTED
;
4720 // return the worst status met
4722 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4724 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4725 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
4726 Private
->TextOutList
[Index
].TextOut
,
4730 if (EFI_ERROR (Status
)) {
4731 ReturnStatus
= Status
;
4736 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
4738 return ReturnStatus
;
4743 ConSplitterTextOutEnableCursor (
4744 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4749 Routine Description:
4750 Makes the cursor visible or invisible
4753 This - Protocol instance pointer.
4754 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
4755 set to be invisible.
4758 EFI_SUCCESS - The operation completed successfully.
4759 EFI_DEVICE_ERROR - The device had an error and could not complete the
4760 request, or the device does not support changing
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
->EnableCursor (
4780 Private
->TextOutList
[Index
].TextOut
,
4783 if (EFI_ERROR (Status
)) {
4784 ReturnStatus
= Status
;
4789 DevNullTextOutEnableCursor (Private
, Visible
);
4791 return ReturnStatus
;