mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	'cast from pointer to integer of different size' when casting from a pointer directly to a 64 bit number. Added an intermediate cast to UINTN. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5009 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			3387 lines
		
	
	
		
			92 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3387 lines
		
	
	
		
			92 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**@file
 | |
|   Console Splitter Driver. Any Handle that attatched
 | |
|   EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
 | |
| 
 | |
|   So far it works like any other driver by opening a SimpleTextIn and/or
 | |
|   SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
 | |
|   difference is this driver does not layer a protocol on the passed in
 | |
|   handle, or construct a child handle like a standard device or bus driver.
 | |
|   This driver produces three virtual handles as children, one for console input
 | |
|   splitter, one for console output splitter and one for error output splitter.
 | |
|   EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
 | |
|   identify the splitter type.
 | |
| 
 | |
|   Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
 | |
|   and Console I/O protocol, will be produced in the driver entry point.
 | |
|   The virtual handle are added on driver entry and never removed.
 | |
|   Such design ensures sytem function well during none console device situation.
 | |
| 
 | |
| Copyright (c) 2006 - 2007 Intel Corporation. <BR>
 | |
| All rights reserved. This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "ConSplitter.h"
 | |
| 
 | |
| //
 | |
| // Global Variables
 | |
| //
 | |
| STATIC TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE,
 | |
|   (EFI_HANDLE) NULL,
 | |
|   {
 | |
|     ConSplitterTextInReset,
 | |
|     ConSplitterTextInReadKeyStroke,
 | |
|     (EFI_EVENT) NULL
 | |
|   },
 | |
|   0,
 | |
|   (EFI_SIMPLE_TEXT_IN_PROTOCOL **) NULL,
 | |
|   0,
 | |
| 
 | |
|   {
 | |
|     ConSplitterSimplePointerReset,
 | |
|     ConSplitterSimplePointerGetState,
 | |
|     (EFI_EVENT) NULL,
 | |
|     (EFI_SIMPLE_POINTER_MODE *) NULL
 | |
|   },
 | |
|   {
 | |
|     0x10000,
 | |
|     0x10000,
 | |
|     0x10000,
 | |
|     TRUE,
 | |
|     TRUE
 | |
|   },
 | |
|   0,
 | |
|   (EFI_SIMPLE_POINTER_PROTOCOL **) NULL,
 | |
|   0,
 | |
| 
 | |
|   FALSE,
 | |
|   {
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | |
|   },
 | |
|   0,
 | |
|   {
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | |
|   },
 | |
|   (EFI_EVENT) NULL,
 | |
| 
 | |
|   FALSE,
 | |
|   FALSE
 | |
| };
 | |
| 
 | |
| STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,
 | |
|   (EFI_HANDLE) NULL,
 | |
|   {
 | |
|     ConSplitterTextOutReset,
 | |
|     ConSplitterTextOutOutputString,
 | |
|     ConSplitterTextOutTestString,
 | |
|     ConSplitterTextOutQueryMode,
 | |
|     ConSplitterTextOutSetMode,
 | |
|     ConSplitterTextOutSetAttribute,
 | |
|     ConSplitterTextOutClearScreen,
 | |
|     ConSplitterTextOutSetCursorPosition,
 | |
|     ConSplitterTextOutEnableCursor,
 | |
|     (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
 | |
|   },
 | |
|   {
 | |
|     1,
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     FALSE,
 | |
|   },
 | |
|   {
 | |
|     ConSpliterGraphicsOutputQueryMode,
 | |
|     ConSpliterGraphicsOutputSetMode,
 | |
|     ConSpliterGraphicsOutputBlt,
 | |
|     NULL
 | |
|   },
 | |
|   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
 | |
|   (TEXT_OUT_GOP_MODE *) NULL,
 | |
|   0,
 | |
|   TRUE,
 | |
|   {
 | |
|     ConSpliterConsoleControlGetMode,
 | |
|     ConSpliterConsoleControlSetMode,
 | |
|     ConSpliterConsoleControlLockStdIn
 | |
|   },
 | |
| 
 | |
|   0,
 | |
|   (TEXT_OUT_AND_GOP_DATA *) NULL,
 | |
|   0,
 | |
|   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,
 | |
|   0,
 | |
|   (INT32 *) NULL,
 | |
| 
 | |
|   EfiConsoleControlScreenText,
 | |
|   0,
 | |
|   0,
 | |
|   (CHAR16 *) NULL,
 | |
|   (INT32 *) NULL
 | |
| };
 | |
| 
 | |
| STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,
 | |
|   (EFI_HANDLE) NULL,
 | |
|   {
 | |
|     ConSplitterTextOutReset,
 | |
|     ConSplitterTextOutOutputString,
 | |
|     ConSplitterTextOutTestString,
 | |
|     ConSplitterTextOutQueryMode,
 | |
|     ConSplitterTextOutSetMode,
 | |
|     ConSplitterTextOutSetAttribute,
 | |
|     ConSplitterTextOutClearScreen,
 | |
|     ConSplitterTextOutSetCursorPosition,
 | |
|     ConSplitterTextOutEnableCursor,
 | |
|     (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
 | |
|   },
 | |
|   {
 | |
|     1,
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     FALSE,
 | |
|   },
 | |
|   {
 | |
|     ConSpliterGraphicsOutputQueryMode,
 | |
|     ConSpliterGraphicsOutputSetMode,
 | |
|     ConSpliterGraphicsOutputBlt,
 | |
|     NULL
 | |
|   },
 | |
|   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
 | |
|   (TEXT_OUT_GOP_MODE *) NULL,
 | |
|   0,
 | |
|   TRUE,
 | |
|   {
 | |
|     ConSpliterConsoleControlGetMode,
 | |
|     ConSpliterConsoleControlSetMode,
 | |
|     ConSpliterConsoleControlLockStdIn
 | |
|   },
 | |
| 
 | |
|   0,
 | |
|   (TEXT_OUT_AND_GOP_DATA *) NULL,
 | |
|   0,
 | |
|   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,
 | |
|   0,
 | |
|   (INT32 *) NULL,
 | |
| 
 | |
|   EfiConsoleControlScreenText,
 | |
|   0,
 | |
|   0,
 | |
|   (CHAR16 *) NULL,
 | |
|   (INT32 *) NULL
 | |
| };
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL           gConSplitterConInDriverBinding = {
 | |
|   ConSplitterConInDriverBindingSupported,
 | |
|   ConSplitterConInDriverBindingStart,
 | |
|   ConSplitterConInDriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL           gConSplitterSimplePointerDriverBinding = {
 | |
|   ConSplitterSimplePointerDriverBindingSupported,
 | |
|   ConSplitterSimplePointerDriverBindingStart,
 | |
|   ConSplitterSimplePointerDriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL           gConSplitterConOutDriverBinding = {
 | |
|   ConSplitterConOutDriverBindingSupported,
 | |
|   ConSplitterConOutDriverBindingStart,
 | |
|   ConSplitterConOutDriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL           gConSplitterStdErrDriverBinding = {
 | |
|   ConSplitterStdErrDriverBindingSupported,
 | |
|   ConSplitterStdErrDriverBindingStart,
 | |
|   ConSplitterStdErrDriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterDriverEntry (
 | |
|   IN EFI_HANDLE                       ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE                 *SystemTable
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Intialize a virtual console device to act as an agrigator of physical console
 | |
|   devices.
 | |
| 
 | |
| Arguments:
 | |
|   ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
 | |
|   SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
 | |
| Returns:
 | |
|   EFI_SUCCESS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // The driver creates virtual handles for ConIn, ConOut, and StdErr.
 | |
|   // The virtual handles will always exist even if no console exist in the
 | |
|   // system. This is need to support hotplug devices like USB.
 | |
|   //
 | |
|   //
 | |
|   // Create virtual device handle for StdErr Splitter
 | |
|   //
 | |
|   Status = ConSplitterTextOutConstructor (&mStdErr);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                     &mStdErr.VirtualHandle,
 | |
|                     &gEfiSimpleTextOutProtocolGuid,
 | |
|                     &mStdErr.TextOut,
 | |
|                     &gEfiPrimaryStandardErrorDeviceGuid,
 | |
|                     NULL,
 | |
|                     NULL
 | |
|                     );
 | |
|   }
 | |
|   //
 | |
|   // Create virtual device handle for ConIn Splitter
 | |
|   //
 | |
|   Status = ConSplitterTextInConstructor (&mConIn);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                     &mConIn.VirtualHandle,
 | |
|                     &gEfiSimpleTextInProtocolGuid,
 | |
|                     &mConIn.TextIn,
 | |
|                     &gEfiSimplePointerProtocolGuid,
 | |
|                     &mConIn.SimplePointer,
 | |
|                     &gEfiPrimaryConsoleInDeviceGuid,
 | |
|                     NULL,
 | |
|                     NULL
 | |
|                     );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Update the EFI System Table with new virtual console
 | |
|       //
 | |
|       gST->ConsoleInHandle  = mConIn.VirtualHandle;
 | |
|       gST->ConIn            = &mConIn.TextIn;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Create virtual device handle for ConOut Splitter
 | |
|   //
 | |
|   Status = ConSplitterTextOutConstructor (&mConOut);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
 | |
|     //
 | |
|     Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                     &mConOut.VirtualHandle,
 | |
|                     &gEfiSimpleTextOutProtocolGuid,
 | |
|                     &mConOut.TextOut,
 | |
|                     &gEfiGraphicsOutputProtocolGuid,
 | |
|                     &mConOut.GraphicsOutput,
 | |
|                     &gEfiConsoleControlProtocolGuid,
 | |
|                     &mConOut.ConsoleControl,
 | |
|                     &gEfiPrimaryConsoleOutDeviceGuid,
 | |
|                     NULL,
 | |
|                     NULL
 | |
|                     );
 | |
| 
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Update the EFI System Table with new virtual console
 | |
|       //
 | |
|       gST->ConsoleOutHandle = mConOut.VirtualHandle;
 | |
|       gST->ConOut           = &mConOut.TextOut;
 | |
|     }
 | |
| 
 | |
|   }
 | |
|   //
 | |
|   // Update the CRC32 in the EFI System Table header
 | |
|   //
 | |
|   gST->Hdr.CRC32 = 0;
 | |
|   gBS->CalculateCrc32 (
 | |
|         (UINT8 *) &gST->Hdr,
 | |
|         gST->Hdr.HeaderSize,
 | |
|         &gST->Hdr.CRC32
 | |
|         );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterTextInConstructor (
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA       *ConInPrivate
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Construct the ConSplitter.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ConInPrivate    - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
 | |
| 
 | |
| Returns:
 | |
|   EFI_OUT_OF_RESOURCES - Out of resources.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Initilize console input splitter's private data.
 | |
|   //
 | |
|   Status = ConSplitterGrowBuffer (
 | |
|             sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL *),
 | |
|             &ConInPrivate->TextInListCount,
 | |
|             (VOID **) &ConInPrivate->TextInList
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // Create Event to support locking StdIn Device
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   ConSpliterConsoleControlLockStdInEvent,
 | |
|                   NULL,
 | |
|                   &ConInPrivate->LockEvent
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_WAIT,
 | |
|                   TPL_NOTIFY,
 | |
|                   ConSplitterTextInWaitForKey,
 | |
|                   ConInPrivate,
 | |
|                   &ConInPrivate->TextIn.WaitForKey
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;
 | |
| 
 | |
|   Status = ConSplitterGrowBuffer (
 | |
|             sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
 | |
|             &ConInPrivate->PointerListCount,
 | |
|             (VOID **) &ConInPrivate->PointerList
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_WAIT,
 | |
|                   TPL_NOTIFY,
 | |
|                   ConSplitterSimplePointerWaitForInput,
 | |
|                   ConInPrivate,
 | |
|                   &ConInPrivate->SimplePointer.WaitForInput
 | |
|                   );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterTextOutConstructor (
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA      *ConOutPrivate
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Initilize console output splitter's private data.
 | |
|   //
 | |
|   ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;
 | |
| 
 | |
|   Status = ConSplitterGrowBuffer (
 | |
|             sizeof (TEXT_OUT_AND_GOP_DATA),
 | |
|             &ConOutPrivate->TextOutListCount,
 | |
|             (VOID **) &ConOutPrivate->TextOutList
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Status = ConSplitterGrowBuffer (
 | |
|             sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
 | |
|             &ConOutPrivate->TextOutQueryDataCount,
 | |
|             (VOID **) &ConOutPrivate->TextOutQueryData
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // Setup the DevNullTextOut console to 80 x 25
 | |
|   //
 | |
|   ConOutPrivate->TextOutQueryData[0].Columns  = 80;
 | |
|   ConOutPrivate->TextOutQueryData[0].Rows     = 25;
 | |
|   DevNullTextOutSetMode (ConOutPrivate, 0);
 | |
| 
 | |
|   //
 | |
|   // Setup resource for mode information in Graphics Output Protocol interface
 | |
|   //
 | |
|   if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
 | |
|   //
 | |
|   if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;
 | |
|   ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;
 | |
| 
 | |
|   //
 | |
|   // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
 | |
|   //  GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
 | |
|   //  GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
 | |
|   //
 | |
|   ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0;
 | |
|   ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;
 | |
|   ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | |
|   ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
 | |
|   ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;
 | |
| 
 | |
|   ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;
 | |
|   //
 | |
|   // Initial current mode to unknow state, and then set to mode 0
 | |
|   //
 | |
|   ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;
 | |
|   ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConSplitterSupported (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_GUID                        *Guid
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Generic Supported Check
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller Handle.
 | |
|   Guid              - Guid.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_UNSUPPORTED - unsupported.
 | |
|   EFI_SUCCESS     - operation is OK.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   VOID        *Instance;
 | |
| 
 | |
|   //
 | |
|   // Make sure the Console Splitter does not attempt to attach to itself
 | |
|   //
 | |
|   if (ControllerHandle == mConIn.VirtualHandle) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (ControllerHandle == mConOut.VirtualHandle) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (ControllerHandle == mStdErr.VirtualHandle) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // Check to see whether the handle has the ConsoleInDevice GUID on it
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   Guid,
 | |
|                   &Instance,
 | |
|                   This->DriverBindingHandle,
 | |
|                   ControllerHandle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|         ControllerHandle,
 | |
|         Guid,
 | |
|         This->DriverBindingHandle,
 | |
|         ControllerHandle
 | |
|         );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterConInDriverBindingSupported (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Console In Supported Check
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_STATUS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return ConSplitterSupported (
 | |
|           This,
 | |
|           ControllerHandle,
 | |
|           &gEfiConsoleInDeviceGuid
 | |
|           );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerDriverBindingSupported (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Standard Error Supported Check
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_STATUS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return ConSplitterSupported (
 | |
|           This,
 | |
|           ControllerHandle,
 | |
|           &gEfiSimplePointerProtocolGuid
 | |
|           );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterConOutDriverBindingSupported (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Console Out Supported Check
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_STATUS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return ConSplitterSupported (
 | |
|           This,
 | |
|           ControllerHandle,
 | |
|           &gEfiConsoleOutDeviceGuid
 | |
|           );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterStdErrDriverBindingSupported (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Standard Error Supported Check
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_STATUS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return ConSplitterSupported (
 | |
|           This,
 | |
|           ControllerHandle,
 | |
|           &gEfiStandardErrorDeviceGuid
 | |
|           );
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterStart (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_HANDLE                      ConSplitterVirtualHandle,
 | |
|   IN  EFI_GUID                        *DeviceGuid,
 | |
|   IN  EFI_GUID                        *InterfaceGuid,
 | |
|   IN  VOID                            **Interface
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Start ConSplitter on ControllerHandle, and create the virtual
 | |
|   agrogated console device on first call Start for a SimpleTextIn handle.
 | |
| 
 | |
| Arguments:
 | |
|   (Standard DriverBinding Protocol Start() function)
 | |
| 
 | |
| Returns:
 | |
|   EFI_ERROR if a SimpleTextIn protocol is not started.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   VOID        *Instance;
 | |
| 
 | |
|   //
 | |
|   // Check to see whether the handle has the ConsoleInDevice GUID on it
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   DeviceGuid,
 | |
|                   &Instance,
 | |
|                   This->DriverBindingHandle,
 | |
|                   ControllerHandle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   DeviceGuid,
 | |
|                   &Instance,
 | |
|                   This->DriverBindingHandle,
 | |
|                   ConSplitterVirtualHandle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return gBS->OpenProtocol (
 | |
|                 ControllerHandle,
 | |
|                 InterfaceGuid,
 | |
|                 Interface,
 | |
|                 This->DriverBindingHandle,
 | |
|                 ConSplitterVirtualHandle,
 | |
|                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                 );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterConInDriverBindingStart (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Start ConSplitter on ControllerHandle, and create the virtual
 | |
|   agrogated console device on first call Start for a SimpleTextIn handle.
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_STATUS
 | |
|   EFI_ERROR if a SimpleTextIn protocol is not started.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn;
 | |
| 
 | |
|   //
 | |
|   // Start ConSplitter on ControllerHandle, and create the virtual
 | |
|   // agrogated console device on first call Start for a SimpleTextIn handle.
 | |
|   //
 | |
|   Status = ConSplitterStart (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mConIn.VirtualHandle,
 | |
|             &gEfiConsoleInDeviceGuid,
 | |
|             &gEfiSimpleTextInProtocolGuid,
 | |
|             (VOID **) &TextIn
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return ConSplitterTextInAddDevice (&mConIn, TextIn);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerDriverBindingStart (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Start ConSplitter on ControllerHandle, and create the virtual
 | |
|   agrogated console device on first call Start for a SimpleTextIn handle.
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_ERROR if a SimpleTextIn protocol is not started.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
 | |
| 
 | |
|   Status = ConSplitterStart (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mConIn.VirtualHandle,
 | |
|             &gEfiSimplePointerProtocolGuid,
 | |
|             &gEfiSimplePointerProtocolGuid,
 | |
|             (VOID **) &SimplePointer
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterConOutDriverBindingStart (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Start ConSplitter on ControllerHandle, and create the virtual
 | |
|   agrogated console device on first call Start for a SimpleTextIn handle.
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
|   EFI_ERROR if a SimpleTextIn protocol is not started.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_TEXT_OUT_PROTOCOL  *TextOut;
 | |
|   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
 | |
|   EFI_UGA_DRAW_PROTOCOL         *UgaDraw;
 | |
| 
 | |
|   Status = ConSplitterStart (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mConOut.VirtualHandle,
 | |
|             &gEfiConsoleOutDeviceGuid,
 | |
|             &gEfiSimpleTextOutProtocolGuid,
 | |
|             (VOID **) &TextOut
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Try to Open Graphics Output protocol
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   &gEfiGraphicsOutputProtocolGuid,
 | |
|                   (VOID **) &GraphicsOutput,
 | |
|                   This->DriverBindingHandle,
 | |
|                   mConOut.VirtualHandle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     GraphicsOutput = NULL;
 | |
|   }
 | |
|   //
 | |
|   // Open UGA_DRAW protocol
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   &gEfiUgaDrawProtocolGuid,
 | |
|                   (VOID **) &UgaDraw,
 | |
|                   This->DriverBindingHandle,
 | |
|                   mConOut.VirtualHandle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     UgaDraw = NULL;
 | |
|   }
 | |
|   //
 | |
|   // If both ConOut and StdErr incorporate the same Text Out device,
 | |
|   // their MaxMode and QueryData should be the intersection of both.
 | |
|   //
 | |
|   Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);
 | |
|   ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterStdErrDriverBindingStart (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Start ConSplitter on ControllerHandle, and create the virtual
 | |
|   agrogated console device on first call Start for a SimpleTextIn handle.
 | |
| 
 | |
| Arguments:
 | |
|   This              - Pointer to protocol.
 | |
|   ControllerHandle  - Controller handle.
 | |
|   RemainingDevicePath  - Remaining device path.
 | |
| 
 | |
| Returns:
 | |
|   EFI_ERROR if a SimpleTextIn protocol is not started.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_TEXT_OUT_PROTOCOL  *TextOut;
 | |
| 
 | |
|   Status = ConSplitterStart (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mStdErr.VirtualHandle,
 | |
|             &gEfiStandardErrorDeviceGuid,
 | |
|             &gEfiSimpleTextOutProtocolGuid,
 | |
|             (VOID **) &TextOut
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // If both ConOut and StdErr incorporate the same Text Out device,
 | |
|   // their MaxMode and QueryData should be the intersection of both.
 | |
|   //
 | |
|   Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);
 | |
|   ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (mStdErr.CurrentNumberOfConsoles == 1) {
 | |
|     gST->StandardErrorHandle  = mStdErr.VirtualHandle;
 | |
|     gST->StdErr               = &mStdErr.TextOut;
 | |
|     //
 | |
|     // Update the CRC32 in the EFI System Table header
 | |
|     //
 | |
|     gST->Hdr.CRC32 = 0;
 | |
|     gBS->CalculateCrc32 (
 | |
|           (UINT8 *) &gST->Hdr,
 | |
|           gST->Hdr.HeaderSize,
 | |
|           &gST->Hdr.CRC32
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  EFI_HANDLE                      ConSplitterVirtualHandle,
 | |
|   IN  EFI_GUID                        *DeviceGuid,
 | |
|   IN  EFI_GUID                        *InterfaceGuid,
 | |
|   IN  VOID                            **Interface
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
|   (Standard DriverBinding Protocol Stop() function)
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   InterfaceGuid,
 | |
|                   Interface,
 | |
|                   This->DriverBindingHandle,
 | |
|                   ControllerHandle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // close the protocol refered.
 | |
|   //
 | |
|   gBS->CloseProtocol (
 | |
|         ControllerHandle,
 | |
|         DeviceGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         ConSplitterVirtualHandle
 | |
|         );
 | |
|   gBS->CloseProtocol (
 | |
|         ControllerHandle,
 | |
|         DeviceGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         ControllerHandle
 | |
|         );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterConInDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  UINTN                           NumberOfChildren,
 | |
|   IN  EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
|   (Standard DriverBinding Protocol Stop() function)
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn;
 | |
| 
 | |
|   if (NumberOfChildren == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = ConSplitterStop (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mConIn.VirtualHandle,
 | |
|             &gEfiConsoleInDeviceGuid,
 | |
|             &gEfiSimpleTextInProtocolGuid,
 | |
|             (VOID **) &TextIn
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Delete this console input device's data structures.
 | |
|   //
 | |
|   return ConSplitterTextInDeleteDevice (&mConIn, TextIn);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  UINTN                           NumberOfChildren,
 | |
|   IN  EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
|   (Standard DriverBinding Protocol Stop() function)
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
 | |
| 
 | |
|   if (NumberOfChildren == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = ConSplitterStop (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mConIn.VirtualHandle,
 | |
|             &gEfiSimplePointerProtocolGuid,
 | |
|             &gEfiSimplePointerProtocolGuid,
 | |
|             (VOID **) &SimplePointer
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Delete this console input device's data structures.
 | |
|   //
 | |
|   return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterConOutDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  UINTN                           NumberOfChildren,
 | |
|   IN  EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
|   (Standard DriverBinding Protocol Stop() function)
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_TEXT_OUT_PROTOCOL  *TextOut;
 | |
| 
 | |
|   if (NumberOfChildren == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = ConSplitterStop (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mConOut.VirtualHandle,
 | |
|             &gEfiConsoleOutDeviceGuid,
 | |
|             &gEfiSimpleTextOutProtocolGuid,
 | |
|             (VOID **) &TextOut
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Delete this console output device's data structures.
 | |
|   //
 | |
|   return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterStdErrDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      ControllerHandle,
 | |
|   IN  UINTN                           NumberOfChildren,
 | |
|   IN  EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
|   (Standard DriverBinding Protocol Stop() function)
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - Complete successfully.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_TEXT_OUT_PROTOCOL  *TextOut;
 | |
| 
 | |
|   if (NumberOfChildren == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = ConSplitterStop (
 | |
|             This,
 | |
|             ControllerHandle,
 | |
|             mStdErr.VirtualHandle,
 | |
|             &gEfiStandardErrorDeviceGuid,
 | |
|             &gEfiSimpleTextOutProtocolGuid,
 | |
|             (VOID **) &TextOut
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Delete this console error out device's data structures.
 | |
|   //
 | |
|   Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (mStdErr.CurrentNumberOfConsoles == 0) {
 | |
|     gST->StandardErrorHandle  = NULL;
 | |
|     gST->StdErr               = NULL;
 | |
|     //
 | |
|     // Update the CRC32 in the EFI System Table header
 | |
|     //
 | |
|     gST->Hdr.CRC32 = 0;
 | |
|     gBS->CalculateCrc32 (
 | |
|           (UINT8 *) &gST->Hdr,
 | |
|           gST->Hdr.HeaderSize,
 | |
|           &gST->Hdr.CRC32
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterGrowBuffer (
 | |
|   IN  UINTN                           SizeOfCount,
 | |
|   IN  UINTN                           *Count,
 | |
|   IN OUT  VOID                        **Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Take the passed in Buffer of size SizeOfCount and grow the buffer
 | |
|   by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
 | |
|   bytes. Copy the current data in Buffer to the new version of Buffer
 | |
|   and free the old version of buffer.
 | |
| 
 | |
| 
 | |
| Arguments:
 | |
|   SizeOfCount - Size of element in array
 | |
|   Count       - Current number of elements in array
 | |
|   Buffer      - Bigger version of passed in Buffer with all the data
 | |
| 
 | |
| Returns:
 | |
|   EFI_SUCCESS - Buffer size has grown
 | |
|   EFI_OUT_OF_RESOURCES - Could not grow the buffer size
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN NewSize;
 | |
|   UINTN OldSize;
 | |
|   VOID  *Ptr;
 | |
| 
 | |
|   //
 | |
|   // grow the buffer to new buffer size,
 | |
|   // copy the old buffer's content to the new-size buffer,
 | |
|   // then free the old buffer.
 | |
|   //
 | |
|   OldSize = *Count * SizeOfCount;
 | |
|   *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;
 | |
|   NewSize = *Count * SizeOfCount;
 | |
| 
 | |
|   Ptr     = AllocateZeroPool (NewSize);
 | |
|   if (Ptr == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   CopyMem (Ptr, *Buffer, OldSize);
 | |
| 
 | |
|   if (*Buffer != NULL) {
 | |
|     FreePool (*Buffer);
 | |
|   }
 | |
| 
 | |
|   *Buffer = Ptr;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterTextInAddDevice (
 | |
|   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
 | |
|   IN  EFI_SIMPLE_TEXT_IN_PROTOCOL     *TextIn
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS
 | |
|   EFI_OUT_OF_RESOURCES
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // If the Text In List is full, enlarge it by calling growbuffer().
 | |
|   //
 | |
|   if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {
 | |
|     Status = ConSplitterGrowBuffer (
 | |
|               sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL *),
 | |
|               &Private->TextInListCount,
 | |
|               (VOID **) &Private->TextInList
 | |
|               );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Add the new text-in device data structure into the Text In List.
 | |
|   //
 | |
|   Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;
 | |
|   Private->CurrentNumberOfConsoles++;
 | |
| 
 | |
|   //
 | |
|   // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
 | |
|   //
 | |
|   gBS->CheckEvent (TextIn->WaitForKey);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterTextInDeleteDevice (
 | |
|   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
 | |
|   IN  EFI_SIMPLE_TEXT_IN_PROTOCOL     *TextIn
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS
 | |
|   EFI_NOT_FOUND
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN Index;
 | |
|   //
 | |
|   // Remove the specified text-in device data structure from the Text In List,
 | |
|   // and rearrange the remaining data structures in the Text In List.
 | |
|   //
 | |
|   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
|     if (Private->TextInList[Index] == TextIn) {
 | |
|       for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {
 | |
|         Private->TextInList[Index] = Private->TextInList[Index + 1];
 | |
|       }
 | |
| 
 | |
|       Private->CurrentNumberOfConsoles--;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterSimplePointerAddDevice (
 | |
|   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
 | |
|   IN  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_OUT_OF_RESOURCES
 | |
|   EFI_SUCCESS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // If the Text In List is full, enlarge it by calling growbuffer().
 | |
|   //
 | |
|   if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {
 | |
|     Status = ConSplitterGrowBuffer (
 | |
|               sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
 | |
|               &Private->PointerListCount,
 | |
|               (VOID **) &Private->PointerList
 | |
|               );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Add the new text-in device data structure into the Text In List.
 | |
|   //
 | |
|   Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;
 | |
|   Private->CurrentNumberOfPointers++;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterSimplePointerDeleteDevice (
 | |
|   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
 | |
|   IN  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN Index;
 | |
|   //
 | |
|   // Remove the specified text-in device data structure from the Text In List,
 | |
|   // and rearrange the remaining data structures in the Text In List.
 | |
|   //
 | |
|   for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
 | |
|     if (Private->PointerList[Index] == SimplePointer) {
 | |
|       for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {
 | |
|         Private->PointerList[Index] = Private->PointerList[Index + 1];
 | |
|       }
 | |
| 
 | |
|       Private->CurrentNumberOfPointers--;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConSplitterGrowMapTable (
 | |
|   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN Size;
 | |
|   UINTN NewSize;
 | |
|   UINTN TotalSize;
 | |
|   INT32 *TextOutModeMap;
 | |
|   INT32 *OldTextOutModeMap;
 | |
|   INT32 *SrcAddress;
 | |
|   INT32 Index;
 | |
| 
 | |
|   NewSize           = Private->TextOutListCount * sizeof (INT32);
 | |
|   OldTextOutModeMap = Private->TextOutModeMap;
 | |
|   TotalSize         = NewSize * Private->TextOutQueryDataCount;
 | |
| 
 | |
|   TextOutModeMap    = AllocateZeroPool (TotalSize);
 | |
|   if (TextOutModeMap == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   SetMem (TextOutModeMap, TotalSize, 0xFF);
 | |
|   Private->TextOutModeMap = TextOutModeMap;
 | |
| 
 | |
|   //
 | |
|   // If TextOutList has been enlarged, need to realloc the mode map table
 | |
|   // The mode map table is regarded as a two dimension array.
 | |
|   //
 | |
|   //                         Old                    New
 | |
|   //  0   ---------> TextOutListCount ----> TextOutListCount
 | |
|   //  |   -------------------------------------------
 | |
|   //  |  |                    |                      |
 | |
|   //  |  |                    |                      |
 | |
|   //  |  |                    |                      |
 | |
|   //  |  |                    |                      |
 | |
|   //  |  |                    |                      |
 | |
|   // \/  |                    |                      |
 | |
|   //      -------------------------------------------
 | |
|   // QueryDataCount
 | |
|   //
 | |
|   if (OldTextOutModeMap != NULL) {
 | |
| 
 | |
|     Size        = Private->CurrentNumberOfConsoles * sizeof (INT32);
 | |
|     Index       = 0;
 | |
|     SrcAddress  = OldTextOutModeMap;
 | |
| 
 | |
|     //
 | |
|     // Copy the old data to the new one
 | |
|     //
 | |
|     while (Index < Private->TextOutMode.MaxMode) {
 | |
|       CopyMem (TextOutModeMap, SrcAddress, Size);
 | |
|       TextOutModeMap += NewSize;
 | |
|       SrcAddress += Size;
 | |
|       Index++;
 | |
|     }
 | |
|     //
 | |
|     // Free the old buffer
 | |
|     //
 | |
|     FreePool (OldTextOutModeMap);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConSplitterAddOutputMode (
 | |
|   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *TextOut
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INT32       MaxMode;
 | |
|   INT32       Mode;
 | |
|   UINTN       Index;
 | |
| 
 | |
|   MaxMode                       = TextOut->Mode->MaxMode;
 | |
|   Private->TextOutMode.MaxMode  = MaxMode;
 | |
| 
 | |
|   //
 | |
|   // Grow the buffer if query data buffer is not large enough to
 | |
|   // hold all the mode supported by the first console.
 | |
|   //
 | |
|   while (MaxMode > (INT32) Private->TextOutQueryDataCount) {
 | |
|     Status = ConSplitterGrowBuffer (
 | |
|               sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
 | |
|               &Private->TextOutQueryDataCount,
 | |
|               (VOID **) &Private->TextOutQueryData
 | |
|               );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Allocate buffer for the output mode map
 | |
|   //
 | |
|   Status = ConSplitterGrowMapTable (Private);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // As the first textout device, directly add the mode in to QueryData
 | |
|   // and at the same time record the mapping between QueryData and TextOut.
 | |
|   //
 | |
|   Mode  = 0;
 | |
|   Index = 0;
 | |
|   while (Mode < MaxMode) {
 | |
|     TextOut->QueryMode (
 | |
|               TextOut,
 | |
|               Mode,
 | |
|               &Private->TextOutQueryData[Mode].Columns,
 | |
|               &Private->TextOutQueryData[Mode].Rows
 | |
|               );
 | |
|     Private->TextOutModeMap[Index] = Mode;
 | |
|     Mode++;
 | |
|     Index += Private->TextOutListCount;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| ConSplitterGetIntersection (
 | |
|   IN  INT32                           *TextOutModeMap,
 | |
|   IN  INT32                           *NewlyAddedMap,
 | |
|   IN  UINTN                           MapStepSize,
 | |
|   IN  UINTN                           NewMapStepSize,
 | |
|   OUT INT32                           *MaxMode,
 | |
|   OUT INT32                           *CurrentMode
 | |
|   )
 | |
| {
 | |
|   INT32 Index;
 | |
|   INT32 *CurrentMapEntry;
 | |
|   INT32 *NextMapEntry;
 | |
|   INT32 CurrentMaxMode;
 | |
|   INT32 Mode;
 | |
| 
 | |
|   Index           = 0;
 | |
|   CurrentMapEntry = TextOutModeMap;
 | |
|   NextMapEntry    = TextOutModeMap;
 | |
|   CurrentMaxMode  = *MaxMode;
 | |
|   Mode            = *CurrentMode;
 | |
| 
 | |
|   while (Index < CurrentMaxMode) {
 | |
|     if (*NewlyAddedMap == -1) {
 | |
|       //
 | |
|       // This mode is not supported any more. Remove it. Special care
 | |
|       // must be taken as this remove will also affect current mode;
 | |
|       //
 | |
|       if (Index == *CurrentMode) {
 | |
|         Mode = -1;
 | |
|       } else if (Index < *CurrentMode) {
 | |
|         Mode--;
 | |
|       }
 | |
|       (*MaxMode)--;
 | |
|     } else {
 | |
|       if (CurrentMapEntry != NextMapEntry) {
 | |
|         CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));
 | |
|       }
 | |
| 
 | |
|       NextMapEntry += MapStepSize;
 | |
|     }
 | |
| 
 | |
|     CurrentMapEntry += MapStepSize;
 | |
|     NewlyAddedMap += NewMapStepSize;
 | |
|     Index++;
 | |
|   }
 | |
| 
 | |
|   *CurrentMode = Mode;
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| ConSplitterSyncOutputMode (
 | |
|   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *TextOut
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
|   Private - Private data structure.
 | |
|   TextOut - Text Out Protocol.
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   INT32                         CurrentMaxMode;
 | |
|   INT32                         Mode;
 | |
|   INT32                         Index;
 | |
|   INT32                         *TextOutModeMap;
 | |
|   INT32                         *MapTable;
 | |
|   TEXT_OUT_SPLITTER_QUERY_DATA  *TextOutQueryData;
 | |
|   UINTN                         Rows;
 | |
|   UINTN                         Columns;
 | |
|   UINTN                         StepSize;
 | |
| 
 | |
|   //
 | |
|   // Must make sure that current mode won't change even if mode number changes
 | |
|   //
 | |
|   CurrentMaxMode    = Private->TextOutMode.MaxMode;
 | |
|   TextOutModeMap    = Private->TextOutModeMap;
 | |
|   StepSize          = Private->TextOutListCount;
 | |
|   TextOutQueryData  = Private->TextOutQueryData;
 | |
| 
 | |
|   //
 | |
|   // Query all the mode that the newly added TextOut supports
 | |
|   //
 | |
|   Mode      = 0;
 | |
|   MapTable  = TextOutModeMap + Private->CurrentNumberOfConsoles;
 | |
|   while (Mode < TextOut->Mode->MaxMode) {
 | |
|     TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);
 | |
| 
 | |
|     //
 | |
|     // Search the QueryData database to see if they intersects
 | |
|     //
 | |
|     Index = 0;
 | |
|     while (Index < CurrentMaxMode) {
 | |
|       if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {
 | |
|         MapTable[Index * StepSize] = Mode;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       Index++;
 | |
|     }
 | |
| 
 | |
|     Mode++;
 | |
|   }
 | |
|   //
 | |
|   // Now search the TextOutModeMap table to find the intersection of supported
 | |
|   // mode between ConSplitter and the newly added device.
 | |
|   //
 | |
|   ConSplitterGetIntersection (
 | |
|     TextOutModeMap,
 | |
|     MapTable,
 | |
|     StepSize,
 | |
|     StepSize,
 | |
|     &Private->TextOutMode.MaxMode,
 | |
|     &Private->TextOutMode.Mode
 | |
|     );
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConSplitterGetIntersectionBetweenConOutAndStrErr (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
|   EFI_OUT_OF_RESOURCES
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN                         ConOutNumOfConsoles;
 | |
|   UINTN                         StdErrNumOfConsoles;
 | |
|   TEXT_OUT_AND_GOP_DATA         *ConOutTextOutList;
 | |
|   TEXT_OUT_AND_GOP_DATA         *StdErrTextOutList;
 | |
|   UINTN                         Indexi;
 | |
|   UINTN                         Indexj;
 | |
|   UINTN                         Rows;
 | |
|   UINTN                         Columns;
 | |
|   INT32                         ConOutMaxMode;
 | |
|   INT32                         StdErrMaxMode;
 | |
|   INT32                         Mode;
 | |
|   INT32                         Index;
 | |
|   INT32                         *ConOutModeMap;
 | |
|   INT32                         *StdErrModeMap;
 | |
|   INT32                         *ConOutMapTable;
 | |
|   INT32                         *StdErrMapTable;
 | |
|   TEXT_OUT_SPLITTER_QUERY_DATA  *ConOutQueryData;
 | |
|   TEXT_OUT_SPLITTER_QUERY_DATA  *StdErrQueryData;
 | |
|   BOOLEAN                       FoundTheSameTextOut;
 | |
|   UINTN                         ConOutMapTableSize;
 | |
|   UINTN                         StdErrMapTableSize;
 | |
| 
 | |
|   ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;
 | |
|   StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;
 | |
|   ConOutTextOutList   = mConOut.TextOutList;
 | |
|   StdErrTextOutList   = mStdErr.TextOutList;
 | |
| 
 | |
|   Indexi              = 0;
 | |
|   FoundTheSameTextOut = FALSE;
 | |
|   while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {
 | |
|     Indexj = 0;
 | |
|     while (Indexj < StdErrNumOfConsoles) {
 | |
|       if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {
 | |
|         FoundTheSameTextOut = TRUE;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       Indexj++;
 | |
|       StdErrTextOutList++;
 | |
|     }
 | |
| 
 | |
|     Indexi++;
 | |
|     ConOutTextOutList++;
 | |
|   }
 | |
| 
 | |
|   if (!FoundTheSameTextOut) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Must make sure that current mode won't change even if mode number changes
 | |
|   //
 | |
|   ConOutMaxMode     = mConOut.TextOutMode.MaxMode;
 | |
|   ConOutModeMap     = mConOut.TextOutModeMap;
 | |
|   ConOutQueryData   = mConOut.TextOutQueryData;
 | |
| 
 | |
|   StdErrMaxMode     = mStdErr.TextOutMode.MaxMode;
 | |
|   StdErrModeMap     = mStdErr.TextOutModeMap;
 | |
|   StdErrQueryData   = mStdErr.TextOutQueryData;
 | |
| 
 | |
|   //
 | |
|   // Allocate the map table and set the map table's index to -1.
 | |
|   //
 | |
|   ConOutMapTableSize  = ConOutMaxMode * sizeof (INT32);
 | |
|   ConOutMapTable      = AllocateZeroPool (ConOutMapTableSize);
 | |
|   if (ConOutMapTable == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);
 | |
| 
 | |
|   StdErrMapTableSize  = StdErrMaxMode * sizeof (INT32);
 | |
|   StdErrMapTable      = AllocateZeroPool (StdErrMapTableSize);
 | |
|   if (StdErrMapTable == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);
 | |
| 
 | |
|   //
 | |
|   // Find the intersection of the two set of modes. If they actually intersect, the
 | |
|   // correponding entry in the map table is set to 1.
 | |
|   //
 | |
|   Mode = 0;
 | |
|   while (Mode < ConOutMaxMode) {
 | |
|     //
 | |
|     // Search the other's QueryData database to see if they intersect
 | |
|     //
 | |
|     Index   = 0;
 | |
|     Rows    = ConOutQueryData[Mode].Rows;
 | |
|     Columns = ConOutQueryData[Mode].Columns;
 | |
|     while (Index < StdErrMaxMode) {
 | |
|       if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {
 | |
|         ConOutMapTable[Mode]  = 1;
 | |
|         StdErrMapTable[Index] = 1;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       Index++;
 | |
|     }
 | |
| 
 | |
|     Mode++;
 | |
|   }
 | |
|   //
 | |
|   // Now search the TextOutModeMap table to find the intersection of supported
 | |
|   // mode between ConSplitter and the newly added device.
 | |
|   //
 | |
|   ConSplitterGetIntersection (
 | |
|     ConOutModeMap,
 | |
|     ConOutMapTable,
 | |
|     mConOut.TextOutListCount,
 | |
|     1,
 | |
|     &(mConOut.TextOutMode.MaxMode),
 | |
|     &(mConOut.TextOutMode.Mode)
 | |
|     );
 | |
|   if (mConOut.TextOutMode.Mode < 0) {
 | |
|     mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);
 | |
|   }
 | |
| 
 | |
|   ConSplitterGetIntersection (
 | |
|     StdErrModeMap,
 | |
|     StdErrMapTable,
 | |
|     mStdErr.TextOutListCount,
 | |
|     1,
 | |
|     &(mStdErr.TextOutMode.MaxMode),
 | |
|     &(mStdErr.TextOutMode.Mode)
 | |
|     );
 | |
|   if (mStdErr.TextOutMode.Mode < 0) {
 | |
|     mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);
 | |
|   }
 | |
| 
 | |
|   FreePool (ConOutMapTable);
 | |
|   FreePool (StdErrMapTable);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConSplitterAddGraphicsOutputMode (
 | |
|   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | |
|   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput,
 | |
|   IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                           Status;
 | |
|   UINTN                                Index;
 | |
|   TEXT_OUT_GOP_MODE                    *Mode;
 | |
|   UINTN                                SizeOfInfo;
 | |
|   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
 | |
|   EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE    *CurrentGraphicsOutputMode;
 | |
|   TEXT_OUT_GOP_MODE                    *ModeBuffer;
 | |
|   TEXT_OUT_GOP_MODE                    *MatchedMode;
 | |
|   UINTN                                NumberIndex;
 | |
|   BOOLEAN                              Match;
 | |
| 
 | |
|   if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;
 | |
| 
 | |
|   if (GraphicsOutput != NULL) {
 | |
|     if (Private->CurrentNumberOfGraphicsOutput == 0) {
 | |
|         //
 | |
|         // This is the first Graphics Output device added
 | |
|         //
 | |
|         CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;
 | |
|         CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;
 | |
|         CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);
 | |
|         CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;
 | |
|         CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;
 | |
|         CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;
 | |
| 
 | |
|         //
 | |
|         // Allocate resource for the private mode buffer
 | |
|         //
 | |
|         ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);
 | |
|         if (ModeBuffer == NULL) {
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
|         FreePool (Private->GraphicsOutputModeBuffer);
 | |
|         Private->GraphicsOutputModeBuffer = ModeBuffer;
 | |
| 
 | |
|         //
 | |
|         // Store all supported display modes to the private mode buffer
 | |
|         //
 | |
|         Mode = ModeBuffer;
 | |
|         for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {
 | |
|           Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             return Status;
 | |
|           }
 | |
|           Mode->HorizontalResolution = Info->HorizontalResolution;
 | |
|           Mode->VerticalResolution = Info->VerticalResolution;
 | |
|           Mode++;
 | |
|           FreePool (Info);
 | |
|         }
 | |
|     } else {
 | |
|       //
 | |
|       // Check intersection of display mode
 | |
|       //
 | |
|       ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);
 | |
|       if (ModeBuffer == NULL) {
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       MatchedMode = ModeBuffer;
 | |
|       Mode = &Private->GraphicsOutputModeBuffer[0];
 | |
|       for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
 | |
|         Match = FALSE;
 | |
| 
 | |
|         for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {
 | |
|           Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             return Status;
 | |
|           }
 | |
|           if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&
 | |
|               (Info->VerticalResolution == Mode->VerticalResolution)){
 | |
|             Match = TRUE;
 | |
|             FreePool (Info);
 | |
|             break;
 | |
|           }
 | |
|           FreePool (Info);
 | |
|         }
 | |
| 
 | |
|         if (Match) {
 | |
|           CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));
 | |
|           MatchedMode++;
 | |
|         }
 | |
| 
 | |
|         Mode++;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Drop the old mode buffer, assign it to a new one
 | |
|       //
 | |
|       FreePool (Private->GraphicsOutputModeBuffer);
 | |
|       Private->GraphicsOutputModeBuffer = ModeBuffer;
 | |
| 
 | |
|       //
 | |
|       // Physical frame buffer is no longer available when there are more than one physical GOP devices
 | |
|       //
 | |
|       CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));
 | |
|       CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;
 | |
|       ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));
 | |
|       CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | |
|       CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
 | |
|       CurrentGraphicsOutputMode->FrameBufferSize = 0;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Select a prefered Display mode 800x600
 | |
|     //
 | |
|     for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
 | |
|       Mode = &Private->GraphicsOutputModeBuffer[Index];
 | |
|       if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Prefered mode is not found, set to mode 0
 | |
|     //
 | |
|     if (Index >= CurrentGraphicsOutputMode->MaxMode) {
 | |
|       Index = 0;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Current mode number may need update now, so set it to an invalide mode number
 | |
|     //
 | |
|     CurrentGraphicsOutputMode->Mode = 0xffff;
 | |
|   } else {
 | |
|     //
 | |
|     // For UGA device, it's inconvenient to retrieve all the supported display modes.
 | |
|     // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
 | |
|     //
 | |
|     CurrentGraphicsOutputMode->MaxMode = 1;
 | |
|     CurrentGraphicsOutputMode->Info->Version = 0;
 | |
|     CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;
 | |
|     CurrentGraphicsOutputMode->Info->VerticalResolution = 600;
 | |
|     CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;
 | |
|     CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;
 | |
|     CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | |
|     CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
 | |
|     CurrentGraphicsOutputMode->FrameBufferSize = 0;
 | |
| 
 | |
|     //
 | |
|     // Update the private mode buffer
 | |
|     //
 | |
|     ModeBuffer = &Private->GraphicsOutputModeBuffer[0];
 | |
|     ModeBuffer->HorizontalResolution = 800;
 | |
|     ModeBuffer->VerticalResolution   = 600;
 | |
| 
 | |
|     //
 | |
|     // Current mode is unknow now, set it to an invalid mode number 0xffff
 | |
|     //
 | |
|     CurrentGraphicsOutputMode->Mode = 0xffff;
 | |
|     Index = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Force GraphicsOutput mode to be set,
 | |
|   // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
 | |
|   //
 | |
|   Private->HardwareNeedsStarting = TRUE;
 | |
|   Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);
 | |
| 
 | |
|   Private->CurrentNumberOfGraphicsOutput++;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterTextOutAddDevice (
 | |
|   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *TextOut,
 | |
|   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput,
 | |
|   IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   UINTN                 CurrentNumOfConsoles;
 | |
|   INT32                 CurrentMode;
 | |
|   INT32                 MaxMode;
 | |
|   TEXT_OUT_AND_GOP_DATA *TextAndGop;
 | |
| 
 | |
|   Status                = EFI_SUCCESS;
 | |
|   CurrentNumOfConsoles  = Private->CurrentNumberOfConsoles;
 | |
| 
 | |
|   //
 | |
|   // If the Text Out List is full, enlarge it by calling growbuffer().
 | |
|   //
 | |
|   while (CurrentNumOfConsoles >= Private->TextOutListCount) {
 | |
|     Status = ConSplitterGrowBuffer (
 | |
|               sizeof (TEXT_OUT_AND_GOP_DATA),
 | |
|               &Private->TextOutListCount,
 | |
|               (VOID **) &Private->TextOutList
 | |
|               );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     //
 | |
|     // Also need to reallocate the TextOutModeMap table
 | |
|     //
 | |
|     Status = ConSplitterGrowMapTable (Private);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TextAndGop          = &Private->TextOutList[CurrentNumOfConsoles];
 | |
| 
 | |
|   TextAndGop->TextOut = TextOut;
 | |
|   TextAndGop->GraphicsOutput = GraphicsOutput;
 | |
|   TextAndGop->UgaDraw = UgaDraw;
 | |
| 
 | |
|   if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {
 | |
|     //
 | |
|     // If No UGA device then use the ConOut device
 | |
|     //
 | |
|     TextAndGop->TextOutEnabled = TRUE;
 | |
|   } else {
 | |
|     //
 | |
|     // If UGA device use ConOut device only used if UGA screen is in Text mode
 | |
|     //
 | |
|     TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);
 | |
|   }
 | |
| 
 | |
|   if (CurrentNumOfConsoles == 0) {
 | |
|     //
 | |
|     // Add the first device's output mode to console splitter's mode list
 | |
|     //
 | |
|     Status = ConSplitterAddOutputMode (Private, TextOut);
 | |
|   } else {
 | |
|     ConSplitterSyncOutputMode (Private, TextOut);
 | |
|   }
 | |
| 
 | |
|   Private->CurrentNumberOfConsoles++;
 | |
| 
 | |
|   //
 | |
|   // Scan both TextOutList, for the intersection TextOut device
 | |
|   // maybe both ConOut and StdErr incorporate the same Text Out
 | |
|   // device in them, thus the output of both should be synced.
 | |
|   //
 | |
|   ConSplitterGetIntersectionBetweenConOutAndStrErr ();
 | |
| 
 | |
|   CurrentMode = Private->TextOutMode.Mode;
 | |
|   MaxMode     = Private->TextOutMode.MaxMode;
 | |
|   ASSERT (MaxMode >= 1);
 | |
| 
 | |
|   if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {
 | |
|     ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
 | |
|   }
 | |
| 
 | |
|   if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {
 | |
|     //
 | |
|     // We just added a new UGA device in graphics mode
 | |
|     //
 | |
|     DevNullGopSync (Private, GraphicsOutput, UgaDraw);
 | |
|   } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {
 | |
|     //
 | |
|     // The new console supports the same mode of the current console so sync up
 | |
|     //
 | |
|     DevNullSyncGopStdOut (Private);
 | |
|   } else {
 | |
|     //
 | |
|     // If ConOut, then set the mode to Mode #0 which us 80 x 25
 | |
|     //
 | |
|     Private->TextOut.SetMode (&Private->TextOut, 0);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ConSplitterTextOutDeleteDevice (
 | |
|   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *TextOut
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   INT32                 Index;
 | |
|   UINTN                 CurrentNumOfConsoles;
 | |
|   TEXT_OUT_AND_GOP_DATA *TextOutList;
 | |
|   EFI_STATUS            Status;
 | |
| 
 | |
|   //
 | |
|   // Remove the specified text-out device data structure from the Text out List,
 | |
|   // and rearrange the remaining data structures in the Text out List.
 | |
|   //
 | |
|   CurrentNumOfConsoles  = Private->CurrentNumberOfConsoles;
 | |
|   Index                 = (INT32) CurrentNumOfConsoles - 1;
 | |
|   TextOutList           = Private->TextOutList;
 | |
|   while (Index >= 0) {
 | |
|     if (TextOutList->TextOut == TextOut) {
 | |
|       CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
 | |
|       CurrentNumOfConsoles--;
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Index--;
 | |
|     TextOutList++;
 | |
|   }
 | |
|   //
 | |
|   // The specified TextOut is not managed by the ConSplitter driver
 | |
|   //
 | |
|   if (Index < 0) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   if (CurrentNumOfConsoles == 0) {
 | |
|     //
 | |
|     // If the number of consoles is zero clear the Dev NULL device
 | |
|     //
 | |
|     Private->CurrentNumberOfConsoles      = 0;
 | |
|     Private->TextOutMode.MaxMode          = 1;
 | |
|     Private->TextOutQueryData[0].Columns  = 80;
 | |
|     Private->TextOutQueryData[0].Rows     = 25;
 | |
|     DevNullTextOutSetMode (Private, 0);
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Max Mode is realy an intersection of the QueryMode command to all
 | |
|   // devices. So we must copy the QueryMode of the first device to
 | |
|   // QueryData.
 | |
|   //
 | |
|   ZeroMem (
 | |
|     Private->TextOutQueryData,
 | |
|     Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)
 | |
|     );
 | |
| 
 | |
|   FreePool (Private->TextOutModeMap);
 | |
|   Private->TextOutModeMap = NULL;
 | |
|   TextOutList             = Private->TextOutList;
 | |
| 
 | |
|   //
 | |
|   // Add the first TextOut to the QueryData array and ModeMap table
 | |
|   //
 | |
|   Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);
 | |
| 
 | |
|   //
 | |
|   // Now add one by one
 | |
|   //
 | |
|   Index = 1;
 | |
|   Private->CurrentNumberOfConsoles = 1;
 | |
|   TextOutList++;
 | |
|   while ((UINTN) Index < CurrentNumOfConsoles) {
 | |
|     ConSplitterSyncOutputMode (Private, TextOutList->TextOut);
 | |
|     Index++;
 | |
|     Private->CurrentNumberOfConsoles++;
 | |
|     TextOutList++;
 | |
|   }
 | |
| 
 | |
|   ConSplitterGetIntersectionBetweenConOutAndStrErr ();
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // ConSplitter TextIn member functions
 | |
| //
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextInReset (
 | |
|   IN  EFI_SIMPLE_TEXT_IN_PROTOCOL     *This,
 | |
|   IN  BOOLEAN                         ExtendedVerification
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset the input device and optionaly run diagnostics
 | |
| 
 | |
|   Arguments:
 | |
|     This                 - Protocol instance pointer.
 | |
|     ExtendedVerification - Driver may perform diagnostics on reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS           - The device was reset.
 | |
|     EFI_DEVICE_ERROR      - The device is not functioning properly and could
 | |
|                             not be reset.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_STATUS                    ReturnStatus;
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   Private                       = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   Private->KeyEventSignalState  = FALSE;
 | |
| 
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
|     Status = Private->TextInList[Index]->Reset (
 | |
|                                           Private->TextInList[Index],
 | |
|                                           ExtendedVerification
 | |
|                                           );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ReturnStatus = Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextInPrivateReadKeyStroke (
 | |
|   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
 | |
|   OUT EFI_INPUT_KEY                   *Key
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can
 | |
|     be used to test for existance of a keystroke via WaitForEvent () call.
 | |
| 
 | |
|   Arguments:
 | |
|     This   - Protocol instance pointer.
 | |
|     Key    - Driver may perform diagnostics on reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS       - The keystroke information was returned.
 | |
|     EFI_NOT_READY     - There was no keystroke data availiable.
 | |
|     EFI_DEVICE_ERROR  - The keydtroke information was not returned due to
 | |
|                         hardware errors.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
|   UINTN         Index;
 | |
|   EFI_INPUT_KEY CurrentKey;
 | |
| 
 | |
|   Key->UnicodeChar  = 0;
 | |
|   Key->ScanCode     = SCAN_NULL;
 | |
| 
 | |
|   //
 | |
|   // if no physical console input device exists, return EFI_NOT_READY;
 | |
|   // if any physical console input device has key input,
 | |
|   // return the key and EFI_SUCCESS.
 | |
|   //
 | |
|   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
|     Status = Private->TextInList[Index]->ReadKeyStroke (
 | |
|                                           Private->TextInList[Index],
 | |
|                                           &CurrentKey
 | |
|                                           );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       *Key = CurrentKey;
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_READY;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ConSpliterConssoleControlStdInLocked (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
 | |
|   the only device locked.
 | |
| 
 | |
| Arguments:
 | |
|   NONE
 | |
| 
 | |
| Returns:
 | |
|   TRUE  - StdIn locked
 | |
|   FALSE - StdIn working normally
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return mConIn.PasswordEnabled;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| EFIAPI
 | |
| ConSpliterConsoleControlLockStdInEvent (
 | |
|   IN  EFI_EVENT                       Event,
 | |
|   IN  VOID                            *Context
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   This timer event will fire when StdIn is locked. It will check the key
 | |
|   sequence on StdIn to see if it matches the password. Any error in the
 | |
|   password will cause the check to reset. As long a mConIn.PasswordEnabled is
 | |
|   TRUE the StdIn splitter will not report any input.
 | |
| 
 | |
| Arguments:
 | |
|   (Standard EFI_EVENT_NOTIFY)
 | |
| 
 | |
| Returns:
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
|   EFI_INPUT_KEY Key;
 | |
|   CHAR16        BackSpaceString[2];
 | |
|   CHAR16        SpaceString[2];
 | |
| 
 | |
|   do {
 | |
|     Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // if it's an ENTER, match password
 | |
|       //
 | |
|       if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {
 | |
|         mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;
 | |
|         if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {
 | |
|           //
 | |
|           // Password not match
 | |
|           //
 | |
|           ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");
 | |
|           mConIn.PwdIndex = 0;
 | |
|         } else {
 | |
|           //
 | |
|           // Key matches password sequence
 | |
|           //
 | |
|           gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);
 | |
|           mConIn.PasswordEnabled  = FALSE;
 | |
|           Status                  = EFI_NOT_READY;
 | |
|         }
 | |
|       } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {
 | |
|         //
 | |
|         // BackSpace met
 | |
|         //
 | |
|         if (mConIn.PwdIndex > 0) {
 | |
|           BackSpaceString[0]  = CHAR_BACKSPACE;
 | |
|           BackSpaceString[1]  = 0;
 | |
| 
 | |
|           SpaceString[0]      = ' ';
 | |
|           SpaceString[1]      = 0;
 | |
| 
 | |
|           ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);
 | |
|           ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);
 | |
|           ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);
 | |
| 
 | |
|           mConIn.PwdIndex--;
 | |
|         }
 | |
|       } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {
 | |
|         //
 | |
|         // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
 | |
|         //
 | |
|         if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {
 | |
|           if (mConIn.PwdIndex == 0) {
 | |
|             ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");
 | |
|           }
 | |
| 
 | |
|           ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");
 | |
|           mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;
 | |
|           mConIn.PwdIndex++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   } while (!EFI_ERROR (Status));
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSpliterConsoleControlLockStdIn (
 | |
|   IN  EFI_CONSOLE_CONTROL_PROTOCOL    *This,
 | |
|   IN  CHAR16                          *Password
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   If Password is NULL unlock the password state variable and set the event
 | |
|   timer. If the Password is too big return an error. If the Password is valid
 | |
|   Copy the Password and enable state variable and then arm the periodic timer
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
|   EFI_SUCCESS           - Lock the StdIn device
 | |
|   EFI_INVALID_PARAMETER - Password is NULL
 | |
|   EFI_OUT_OF_RESOURCES  - Buffer allocation to store the password fails
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   if (Password == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {
 | |
|     //
 | |
|     // Currently have a max password size
 | |
|     //
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // Save the password, initialize state variables and arm event timer
 | |
|   //
 | |
|   StrCpy (mConIn.Password, Password);
 | |
|   mConIn.PasswordEnabled  = TRUE;
 | |
|   mConIn.PwdIndex         = 0;
 | |
|   gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextInReadKeyStroke (
 | |
|   IN  EFI_SIMPLE_TEXT_IN_PROTOCOL     *This,
 | |
|   OUT EFI_INPUT_KEY                   *Key
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can
 | |
|     be used to test for existance of a keystroke via WaitForEvent () call.
 | |
|     If the ConIn is password locked make it look like no keystroke is availible
 | |
| 
 | |
|   Arguments:
 | |
|     This   - Protocol instance pointer.
 | |
|     Key    - Driver may perform diagnostics on reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS       - The keystroke information was returned.
 | |
|     EFI_NOT_READY     - There was no keystroke data availiable.
 | |
|     EFI_DEVICE_ERROR  - The keydtroke information was not returned due to
 | |
|                         hardware errors.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
 | |
| 
 | |
|   Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
|   if (Private->PasswordEnabled) {
 | |
|     //
 | |
|     // If StdIn Locked return not ready
 | |
|     //
 | |
|     return EFI_NOT_READY;
 | |
|   }
 | |
| 
 | |
|   Private->KeyEventSignalState = FALSE;
 | |
| 
 | |
|   return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| EFIAPI
 | |
| ConSplitterTextInWaitForKey (
 | |
|   IN  EFI_EVENT                       Event,
 | |
|   IN  VOID                            *Context
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   This event agregates all the events of the ConIn devices in the spliter.
 | |
|   If the ConIn is password locked then return.
 | |
|   If any events of physical ConIn devices are signaled, signal the ConIn
 | |
|   spliter event. This will cause the calling code to call
 | |
|   ConSplitterTextInReadKeyStroke ().
 | |
| 
 | |
| Arguments:
 | |
|   Event   - The Event assoicated with callback.
 | |
|   Context - Context registered when Event was created.
 | |
| 
 | |
| Returns:
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
 | |
|   if (Private->PasswordEnabled) {
 | |
|     //
 | |
|     // If StdIn Locked return not ready
 | |
|     //
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
 | |
|   //
 | |
|   if (Private->KeyEventSignalState) {
 | |
|     gBS->SignalEvent (Event);
 | |
|     return ;
 | |
|   }
 | |
|   //
 | |
|   // if any physical console input device has key input, signal the event.
 | |
|   //
 | |
|   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
|     Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       gBS->SignalEvent (Event);
 | |
|       Private->KeyEventSignalState = TRUE;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerReset (
 | |
|   IN  EFI_SIMPLE_POINTER_PROTOCOL     *This,
 | |
|   IN  BOOLEAN                         ExtendedVerification
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset the input device and optionaly run diagnostics
 | |
| 
 | |
|   Arguments:
 | |
|     This                 - Protocol instance pointer.
 | |
|     ExtendedVerification - Driver may perform diagnostics on reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS           - The device was reset.
 | |
|     EFI_DEVICE_ERROR      - The device is not functioning properly and could
 | |
|                             not be reset.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_STATUS                    ReturnStatus;
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   Private                         = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
 | |
| 
 | |
|   Private->InputEventSignalState  = FALSE;
 | |
| 
 | |
|   if (Private->CurrentNumberOfPointers == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {
 | |
|     Status = Private->PointerList[Index]->Reset (
 | |
|                                             Private->PointerList[Index],
 | |
|                                             ExtendedVerification
 | |
|                                             );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ReturnStatus = Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerPrivateGetState (
 | |
|   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
 | |
|   IN OUT EFI_SIMPLE_POINTER_STATE     *State
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can
 | |
|     be used to test for existance of a keystroke via WaitForEvent () call.
 | |
| 
 | |
|   Arguments:
 | |
|     This   - Protocol instance pointer.
 | |
|     State  -
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS       - The keystroke information was returned.
 | |
|     EFI_NOT_READY     - There was no keystroke data availiable.
 | |
|     EFI_DEVICE_ERROR  - The keydtroke information was not returned due to
 | |
|                         hardware errors.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_STATUS                ReturnStatus;
 | |
|   UINTN                     Index;
 | |
|   EFI_SIMPLE_POINTER_STATE  CurrentState;
 | |
| 
 | |
|   State->RelativeMovementX  = 0;
 | |
|   State->RelativeMovementY  = 0;
 | |
|   State->RelativeMovementZ  = 0;
 | |
|   State->LeftButton         = FALSE;
 | |
|   State->RightButton        = FALSE;
 | |
| 
 | |
|   //
 | |
|   // if no physical console input device exists, return EFI_NOT_READY;
 | |
|   // if any physical console input device has key input,
 | |
|   // return the key and EFI_SUCCESS.
 | |
|   //
 | |
|   ReturnStatus = EFI_NOT_READY;
 | |
|   for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
 | |
| 
 | |
|     Status = Private->PointerList[Index]->GetState (
 | |
|                                             Private->PointerList[Index],
 | |
|                                             &CurrentState
 | |
|                                             );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       if (ReturnStatus == EFI_NOT_READY) {
 | |
|         ReturnStatus = EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       if (CurrentState.LeftButton) {
 | |
|         State->LeftButton = TRUE;
 | |
|       }
 | |
| 
 | |
|       if (CurrentState.RightButton) {
 | |
|         State->RightButton = TRUE;
 | |
|       }
 | |
| 
 | |
|       if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {
 | |
|         State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;
 | |
|       }
 | |
| 
 | |
|       if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {
 | |
|         State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;
 | |
|       }
 | |
| 
 | |
|       if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {
 | |
|         State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;
 | |
|       }
 | |
|     } else if (Status == EFI_DEVICE_ERROR) {
 | |
|       ReturnStatus = EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerGetState (
 | |
|   IN  EFI_SIMPLE_POINTER_PROTOCOL     *This,
 | |
|   IN OUT EFI_SIMPLE_POINTER_STATE     *State
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can
 | |
|     be used to test for existance of a keystroke via WaitForEvent () call.
 | |
|     If the ConIn is password locked make it look like no keystroke is availible
 | |
| 
 | |
|   Arguments:
 | |
|     This   - Protocol instance pointer.
 | |
|     State  -
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS       - The keystroke information was returned.
 | |
|     EFI_NOT_READY     - There was no keystroke data availiable.
 | |
|     EFI_DEVICE_ERROR  - The keydtroke information was not returned due to
 | |
|                         hardware errors.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
 | |
| 
 | |
|   Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
 | |
|   if (Private->PasswordEnabled) {
 | |
|     //
 | |
|     // If StdIn Locked return not ready
 | |
|     //
 | |
|     return EFI_NOT_READY;
 | |
|   }
 | |
| 
 | |
|   Private->InputEventSignalState = FALSE;
 | |
| 
 | |
|   return ConSplitterSimplePointerPrivateGetState (Private, State);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| EFIAPI
 | |
| ConSplitterSimplePointerWaitForInput (
 | |
|   IN  EFI_EVENT                       Event,
 | |
|   IN  VOID                            *Context
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   This event agregates all the events of the ConIn devices in the spliter.
 | |
|   If the ConIn is password locked then return.
 | |
|   If any events of physical ConIn devices are signaled, signal the ConIn
 | |
|   spliter event. This will cause the calling code to call
 | |
|   ConSplitterTextInReadKeyStroke ().
 | |
| 
 | |
| Arguments:
 | |
|   Event   - The Event assoicated with callback.
 | |
|   Context - Context registered when Event was created.
 | |
| 
 | |
| Returns:
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
 | |
|   if (Private->PasswordEnabled) {
 | |
|     //
 | |
|     // If StdIn Locked return not ready
 | |
|     //
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
 | |
|   //
 | |
|   if (Private->InputEventSignalState) {
 | |
|     gBS->SignalEvent (Event);
 | |
|     return ;
 | |
|   }
 | |
|   //
 | |
|   // if any physical console input device has key input, signal the event.
 | |
|   //
 | |
|   for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
 | |
|     Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       gBS->SignalEvent (Event);
 | |
|       Private->InputEventSignalState = TRUE;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutReset (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  BOOLEAN                         ExtendedVerification
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset the text output device hardware and optionaly run diagnostics
 | |
| 
 | |
|   Arguments:
 | |
|     This                 - Protocol instance pointer.
 | |
|     ExtendedVerification - Driver may perform more exhaustive verfication
 | |
|                            operation of the device during reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS       - The text output device was reset.
 | |
|     EFI_DEVICE_ERROR  - The text output device is not functioning correctly and
 | |
|                         could not be reset.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
| 
 | |
|       Status = Private->TextOutList[Index].TextOut->Reset (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       ExtendedVerification
 | |
|                                                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
 | |
| 
 | |
|   Status = DevNullTextOutSetMode (Private, 0);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ReturnStatus = Status;
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutOutputString (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  CHAR16                          *WString
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Write a Unicode string to the output device.
 | |
| 
 | |
|   Arguments:
 | |
|     This    - Protocol instance pointer.
 | |
|     String  - The NULL-terminated Unicode string to be displayed on the output
 | |
|               device(s). All output devices must also support the Unicode
 | |
|               drawing defined in this file.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS       - The string was output to the device.
 | |
|     EFI_DEVICE_ERROR  - The device reported an error while attempting to output
 | |
|                          the text.
 | |
|     EFI_UNSUPPORTED        - The output device's mode is not currently in a
 | |
|                               defined text mode.
 | |
|     EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
 | |
|                               characters in the Unicode string could not be
 | |
|                               rendered and were skipped.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   UINTN                           BackSpaceCount;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
|   CHAR16                          *TargetString;
 | |
| 
 | |
|   This->SetAttribute (This, This->Mode->Attribute);
 | |
| 
 | |
|   Private         = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   BackSpaceCount  = 0;
 | |
|   for (TargetString = WString; *TargetString; TargetString++) {
 | |
|     if (*TargetString == CHAR_BACKSPACE) {
 | |
|       BackSpaceCount++;
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (BackSpaceCount == 0) {
 | |
|     TargetString = WString;
 | |
|   } else {
 | |
|     TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));
 | |
|     StrCpy (TargetString, WString);
 | |
|   }
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   Status = DevNullTextOutOutputString (Private, TargetString);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ReturnStatus = Status;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->OutputString (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       TargetString
 | |
|                                                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (BackSpaceCount) {
 | |
|     FreePool (TargetString);
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutTestString (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  CHAR16                          *WString
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Verifies that all characters in a Unicode string can be output to the
 | |
|     target device.
 | |
| 
 | |
|   Arguments:
 | |
|     This    - Protocol instance pointer.
 | |
|     String  - The NULL-terminated Unicode string to be examined for the output
 | |
|                device(s).
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS     - The device(s) are capable of rendering the output string.
 | |
|     EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
 | |
|                        rendered by one or more of the output devices mapped
 | |
|                        by the EFI handle.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->TestString (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       WString
 | |
|                                                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // There is no DevNullTextOutTestString () since a Unicode buffer would
 | |
|   // always return EFI_SUCCESS.
 | |
|   // ReturnStatus will be EFI_SUCCESS if no consoles are present
 | |
|   //
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutQueryMode (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  UINTN                           ModeNumber,
 | |
|   OUT UINTN                           *Columns,
 | |
|   OUT UINTN                           *Rows
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Returns information for an available text mode that the output device(s)
 | |
|     supports.
 | |
| 
 | |
|   Arguments:
 | |
|     This       - Protocol instance pointer.
 | |
|     ModeNumber - The mode number to return information on.
 | |
|     Columns, Rows - Returns the geometry of the text output device for the
 | |
|                     requested ModeNumber.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - The requested mode information was returned.
 | |
|     EFI_DEVICE_ERROR - The device had an error and could not
 | |
|                        complete the request.
 | |
|     EFI_UNSUPPORTED - The mode number was not valid.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Check whether param ModeNumber is valid.
 | |
|   // ModeNumber should be within range 0 ~ MaxMode - 1.
 | |
|   //
 | |
|   if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if ((INT32) ModeNumber >= This->Mode->MaxMode) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   *Columns  = Private->TextOutQueryData[ModeNumber].Columns;
 | |
|   *Rows     = Private->TextOutQueryData[ModeNumber].Rows;
 | |
| 
 | |
|   if (*Columns <= 0 && *Rows <= 0) {
 | |
|     return EFI_UNSUPPORTED;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutSetMode (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  UINTN                           ModeNumber
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Sets the output device(s) to a specified mode.
 | |
| 
 | |
|   Arguments:
 | |
|     This       - Protocol instance pointer.
 | |
|     ModeNumber - The mode number to set.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - The requested text mode was set.
 | |
|     EFI_DEVICE_ERROR - The device had an error and
 | |
|                        could not complete the request.
 | |
|     EFI_UNSUPPORTED - The mode number was not valid.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   INT32                           *TextOutModeMap;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Check whether param ModeNumber is valid.
 | |
|   // ModeNumber should be within range 0 ~ MaxMode - 1.
 | |
|   //
 | |
|   if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if ((INT32) ModeNumber >= This->Mode->MaxMode) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // If the mode is being set to the curent mode, then just clear the screen and return.
 | |
|   //
 | |
|   if (Private->TextOutMode.Mode == (INT32) ModeNumber) {
 | |
|     return ConSplitterTextOutClearScreen (This);
 | |
|   }
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->SetMode (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       TextOutModeMap[Index]
 | |
|                                                       );
 | |
|       //
 | |
|       // If this console device is based on a UGA device, then sync up the bitmap from
 | |
|       // the UGA splitter and reclear the text portion of the display in the new mode.
 | |
|       //
 | |
|       if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {
 | |
|         Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);
 | |
|       }
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // The DevNull Console will support any possible mode as it allocates memory
 | |
|   //
 | |
|   Status = DevNullTextOutSetMode (Private, ModeNumber);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ReturnStatus = Status;
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutSetAttribute (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  UINTN                           Attribute
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Sets the background and foreground colors for the OutputString () and
 | |
|     ClearScreen () functions.
 | |
| 
 | |
|   Arguments:
 | |
|     This      - Protocol instance pointer.
 | |
|     Attribute - The attribute to set. Bits 0..3 are the foreground color, and
 | |
|                 bits 4..6 are the background color. All other bits are undefined
 | |
|                 and must be zero. The valid Attributes are defined in this file.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - The attribute was set.
 | |
|     EFI_DEVICE_ERROR - The device had an error and
 | |
|                        could not complete the request.
 | |
|     EFI_UNSUPPORTED - The attribute requested is not defined.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Check whether param Attribute is valid.
 | |
|   //
 | |
|   if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->SetAttribute (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       Attribute
 | |
|                                                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Private->TextOutMode.Attribute = (INT32) Attribute;
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutClearScreen (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Clears the output device(s) display to the currently selected background
 | |
|     color.
 | |
| 
 | |
|   Arguments:
 | |
|     This      - Protocol instance pointer.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - The operation completed successfully.
 | |
|     EFI_DEVICE_ERROR - The device had an error and
 | |
|                        could not complete the request.
 | |
|     EFI_UNSUPPORTED - The output device is not in a valid text mode.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = DevNullTextOutClearScreen (Private);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ReturnStatus = Status;
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutSetCursorPosition (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  UINTN                           Column,
 | |
|   IN  UINTN                           Row
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Sets the current coordinates of the cursor position
 | |
| 
 | |
|   Arguments:
 | |
|     This        - Protocol instance pointer.
 | |
|     Column, Row - the position to set the cursor to. Must be greater than or
 | |
|                   equal to zero and less than the number of columns and rows
 | |
|                   by QueryMode ().
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - The operation completed successfully.
 | |
|     EFI_DEVICE_ERROR - The device had an error and
 | |
|                        could not complete the request.
 | |
|     EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
 | |
|                        cursor position is invalid for the current mode.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
|   UINTN                           MaxColumn;
 | |
|   UINTN                           MaxRow;
 | |
| 
 | |
|   Private   = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   MaxColumn = Private->TextOutQueryData[Private->TextOutMode.Mode].Columns;
 | |
|   MaxRow    = Private->TextOutQueryData[Private->TextOutMode.Mode].Rows;
 | |
| 
 | |
|   if (Column >= MaxColumn || Row >= MaxRow) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->SetCursorPosition (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       Column,
 | |
|                                                       Row
 | |
|                                                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DevNullTextOutSetCursorPosition (Private, Column, Row);
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ConSplitterTextOutEnableCursor (
 | |
|   IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL    *This,
 | |
|   IN  BOOLEAN                         Visible
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Makes the cursor visible or invisible
 | |
| 
 | |
|   Arguments:
 | |
|     This    - Protocol instance pointer.
 | |
|     Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
 | |
|               set to be invisible.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - The operation completed successfully.
 | |
|     EFI_DEVICE_ERROR - The device had an error and could not complete the
 | |
|                         request, or the device does not support changing
 | |
|                         the cursor mode.
 | |
|     EFI_UNSUPPORTED - The output device is not in a valid text mode.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | |
|   UINTN                           Index;
 | |
|   EFI_STATUS                      ReturnStatus;
 | |
| 
 | |
|   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // return the worst status met
 | |
|   //
 | |
|   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
 | |
| 
 | |
|     if (Private->TextOutList[Index].TextOutEnabled) {
 | |
|       Status = Private->TextOutList[Index].TextOut->EnableCursor (
 | |
|                                                       Private->TextOutList[Index].TextOut,
 | |
|                                                       Visible
 | |
|                                                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ReturnStatus = Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DevNullTextOutEnableCursor (Private, Visible);
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 |