diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_DXE/ConSplitter | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/CORE_DXE/ConSplitter')
-rw-r--r-- | Core/CORE_DXE/ConSplitter/ConSplit.c | 2387 | ||||
-rw-r--r-- | Core/CORE_DXE/ConSplitter/ConSplit.h | 553 | ||||
-rw-r--r-- | Core/CORE_DXE/ConSplitter/ConSplitter.cif | 12 | ||||
-rw-r--r-- | Core/CORE_DXE/ConSplitter/ConSplitter.sdl | 26 | ||||
-rw-r--r-- | Core/CORE_DXE/ConSplitter/In.c | 1159 | ||||
-rw-r--r-- | Core/CORE_DXE/ConSplitter/Out.c | 1323 |
6 files changed, 5460 insertions, 0 deletions
diff --git a/Core/CORE_DXE/ConSplitter/ConSplit.c b/Core/CORE_DXE/ConSplitter/ConSplit.c new file mode 100644 index 0000000..6963438 --- /dev/null +++ b/Core/CORE_DXE/ConSplitter/ConSplit.c @@ -0,0 +1,2387 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.c 7 8/28/13 10:44p Thomaschen $ +// +// $Revision: 7 $ +// +// $Date: 8/28/13 10:44p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.c $ +// +// 7 8/28/13 10:44p Thomaschen +// Fixed for EIP133747. +// +// 6 8/01/13 2:32a Thomaschen +// Add for EIP109384. +// [Files] ConSplit.c, ConSplit.h, In.c, CsmSimpleIn.c. +// +// 5 6/26/13 3:09a Thomaschen +// Remove EIP109384. +// +// 3 6/04/13 1:55a Thomaschen +// Fixed for EIP118202. +// +// 2 11/15/12 9:53p Wesleychen +// Update to rev.55 for EIP103887. +// +// 55 10/29/12 3:44p Artems +// [TAG] EIP103887 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Upgrade Serial Redirection to 4.6.3_Terminal_51 with Core +// 4654, system will hang 0x06. +// [RootCause] Uninitialized variable was used +// [Solution] Initialize DeviceModeNumber variable before using +// [Files] ConSplit.c +// +// 54 10/25/12 2:31a Deepthins +// [TAG] EIP99475 +// [Category] Improvement +// [Description] Multi language module Support in the console splitter +// [Files] ConSplit.c, ConSplit.h , In.c and AmiKeycode.h +// +// 53 10/08/12 4:28p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Important +// [Symptom] system boots in wrong text mode +// [RootCause] Incorrect restore of graphics mode after legacy OPROM +// execution +// [Solution] Added code for correct restoration of system state after +// execution of Consplit.stop function +// [Files] Consplit.c +// +// 52 8/13/12 3:39p Artems +// [TAG] EIP95607 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Execute nsh script and redirect output to file, then exit +// from shell, setup screen will crash +// [RootCause] Console splitter maintains global pool of supportedmodes. +// It's getting adjusted every time new SimpleTextOut (STO) is installed +// If new STO doesn't support particular mode it is getting marked as +// unsupported in global pool +// However once this STO is uninstalled global pool isn't updated, so mode +// is still marked as unsupported, +// though system can support it +// [Solution] Do not connect simpleTextOut driver if it doesn'tsupport +// mode splitter is in +// [Files] Consplit.c +// +// 51 8/02/12 12:13p Artems +// [TAG] EIP95607 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Execute nsh script and redirect output to file, then exit +// from shell, setup screen will crash +// [RootCause] Console splitter maintains global pool of supported +// modes. +// It's getting adjusted every time new SimpleTextOut (STO) is installed +// If new STO doesn't support particular mode it is getting marked as +// unsupported in global pool +// However once this STO is uninstalled global pool isn't updated, so mode +// is still marked as unsupported, +// though system can support it +// [Solution] Added reinitilization of global pool of supported modes on +// STO uninstall event +// [Files] Consplit.h Consplit.c +// +// 50 7/06/12 11:28a Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] Support for monitor native resolution +// [Files] GC.c, Consplit.c, Out.c, Core_Dxe.sdl +// +// 49 12/15/11 12:15p Felixp +// [TAG] EIP73410 +// [Category] Improvement +// [Description] InstallSimplePointerDevice function is updated to +// initialize +// LeftButton and RightButton fields of the +// EFI_SIMPLE_POINTER_MODE structure exposed by +// the splitter based on capabilities of the available mouse devices. +// +// 48 8/12/11 12:19p Artems +// EIP 64107: Added changes for module to be compliant with UEFI +// specification v 2.3.1 +// +// 47 7/11/11 10:10a Felixp +// Improvement (EIP 64049): +// REPORT_NO_CON_OUT_ERROR and REPORT_NO_CON_IN_ERROR SDL tokens are added +// to enable/disable reporting of the console errors. +// +// 46 5/13/11 3:37p Felixp +// Minor improvement in CSStop: the screen is now saved after closing the +// protocol +// +// 45 5/05/11 3:52p Artems +// Added multi-language keyboard support +// +// 44 2/25/11 12:33p Artems +// EIP 53767 - disable reporting keyboard absence on fast boot path +// +// 43 11/15/10 4:59p Felixp +// +// 41 9/24/10 3:38p Felixp +// Enhancement(EIP 43535): +// The pST->ConOut pointer used to be initialized once all ConOut +// device are connected. The Console Splitter driver is updated +// to initialize ConOut-related fields of the systems table +// early (in the entry point) to workaround bugs in some of the +// UEFI OpROM drivers that are using pST->ConOut without NULL checking. +// +// 40 9/24/10 7:39a Felixp +// Additional checks for DXE_NO_CON_OUT and DXE_NO_CON_IN errors are +// added. +// The errors are now reported when no console devices with device path +// available. +// +// 39 8/10/10 2:31p Vyacheslava +// Simple Pointer Protocol bug fixes. (EIP#41832) +// +// 38 6/23/10 3:02p Felixp +// SimplePointer splitter support is added. +// +// 37 2/19/10 9:58a Artems +// Merged previous changes +// +// 36 2/12/10 6:13p Artems +// EIP 34632 Added modification of MasterMode.MaxMode value if one of +// children does not support Mode 2 or higher +// +// 34 8/28/09 9:07a Felixp +// Component Name protocol implementation is upadted to support both +// ComponentName and ComponentName2 protocols +// (based on value of the EFI_SPECIFICATION_VERSION SDL token). +// +// 33 7/08/09 4:42p Artems +// Added missing functions headers +// +// 32 7/07/09 3:35p Artems +// Added functions headers according to code standard +// +// 31 6/16/09 5:50p Artems +// EIP 21415 Fixed error with CursorVisible variable +// +// 30 1/16/09 5:27p Felixp +// Bug fix. +// Headless systems hanging(EIP 18165). +// Symptoms: Systems with no console output devices were hanging towards +// the end of the boot process (prior to OS handoff). +// Details: Some of the global variables used by console splitter +// implementation +// of TxtOut were only initialized once first physical console output +// device is detected, +// which was never happenning of a headless system. +// The conosle splitter is updated to properly initialize the globals +// when no actual console output devices are available. +// UpdateSystemTableConOut function is updated. +// +// 29 1/05/09 3:11p Felixp +// Minor update of UpdateSystemTableConOut. +// Callback event is closed at the end of the function +// (system table needs to be populated only once). +// +// 28 10/09/08 2:50p Felixp +// StdErr and StandardErrorHandle initialization added +// +// 27 1/31/08 12:00p Olegi +// Numlock bootup state made setup driven. +// +// 26 10/23/07 4:07p Olegi +// Added a call to syncronize LEDs of ConIn devices during Start. +// +// 25 10/23/07 10:12a Felixp +// Bug fix: after boot to Shell big part of the small AMI logo stayed on +// the screen. +// It was only happenning when two conditions were met: serial redirection +// was turned off and plug in card with the option ROM was connected to +// the system. +// +// 24 9/17/07 4:04p Olegi +// Added support for AMI_EFIKEYCODE_PROTOCOL and +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. +// +// 23 9/05/07 5:43p Felixp +// Report errors when no ConIn and ConOut devices are not available. +// +// 22 9/05/07 11:13a Felixp +// SimpleTextInEx support removed. It causes problems. Support will add +// again after Core labeling. +// +// 20 1/05/07 5:32p Artems +// +// 19 12/29/06 3:01p Felixp +// 1. Support for GraphicsOutput protocol added +// 2. Support for more then one text mode added +// +// 18 9/27/06 7:42p Felixp +// SetMode funciton of the ConsoleControl protocol is updated to restore +// default UGA mode when switching from grphics to text. +// +// 17 9/13/06 6:16p Felixp +// pST->ConOut initialization logic changed: it is now initialized +// immediately after the first ConOut device has been connected +// +// 16 3/13/06 2:37a Felixp +// +// 15 12/12/05 8:36p Felixp +// RestoreTheScreen update: Restore Cursor Status +// +// 14 12/12/05 9:32a Felixp +// Support for synchronization of console devices +// (now screen is restored after legacy OpROM execution). +// +// 13 11/07/05 10:37a Felixp +// LockStdIn function of ConsoleControl protocol implemented +// +// 12 7/15/05 7:17p Felixp +// CONSOLE_DEVICES_STARTED_PROTOCOL_GUID added. +// BDS uses it to notify Splitter that Console Devices have been started. +// Once Splitter receives notification, it will install ConIn and ConOut +// in System Table +// +// 11 5/27/05 12:16p Felixp +// +// 10 5/27/05 12:47a Felixp +// Support for ConsoleControl protocol added +// +// 9 4/08/05 7:40a Felixp +// fix: from now on when new device added, others not cleared +// +// 8 3/04/05 9:17a Mandal +// +// 7 2/24/05 5:30p Felixp +// 1. Coded added to Start/Stop functions to open processed handles in +// BY_CHILD_CONTROLLER mode +// 2. GetControllerName implemented +// +// 6 2/11/05 6:11p Felixp +// Logic to update ConDev variables +// +// 5 2/02/05 4:20p Felixp +// +// 3 2/02/05 2:32p Felixp +// Splitter opens TxtIn and TxtOut in BY_DRIVER mode (used to be +// GET_PROTOCOL) +// +// 2 2/01/05 1:17a Felixp +// +// 1 1/28/05 1:16p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 1/07/05 11:57a Felixp +// +// 3 1/04/05 5:15p Robert +// Changed component name to be more consistent with the other drivers +// that have been developed +// +// 2 1/03/05 5:47p Robert +// Working beta version of the consplitter +// +// 1 12/30/04 9:47a Robert +// Initial check in +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: ConSplit.c +// +// Description: Console Splitter driver that creates a cetralized input and +// output console so that the correct data is going to and coming +// from the correct devices +// +//<AMI_FHDR_END> +//********************************************************************** + +//---------------------------------------------------------------------------- + +#include "ConSplit.h" +#include <Protocol/DevicePath.h> +#include <Protocol/ConsoleControl.h> +#include <Protocol/HiiDataBase.h> +#include <Setup.h> +#include <Dxe.h> +#include <Hob.h> +#include <Token.h> + +//---------------------------------------------------------------------------- + +EFI_HANDLE ConSplitHandle = NULL; + +DLIST ConInList; +DLIST ConOutList; +DLIST ConPointerList; +DLIST ConInKeyNotifyList; + +EFI_KEY_TOGGLE_STATE mCSToggleState = TOGGLE_STATE_VALID; +BOOLEAN NumLockSet = FALSE; +static BOOLEAN InitModesTableCalled = FALSE; + +static EFI_GUID gSimpleTextOutGuid = EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID; +static EFI_GUID gSimpleInGuid = EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID; +static EFI_GUID gSimpleInExGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; +static EFI_GUID gAmiEfiKeycodeGuid = AMI_EFIKEYCODE_PROTOCOL_GUID; +static EFI_GUID gSimplePointerGuid = EFI_SIMPLE_POINTER_PROTOCOL_GUID; +static EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID; +static EFI_GUID gAmiMultiLangSupportGuid = AMI_MULTI_LANG_SUPPORT_PROTOCOL_GUID; + +extern SIMPLE_TEXT_OUTPUT_MODE MasterMode; + + +EFI_STATUS InstallConOutDevice( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut, + IN EFI_HANDLE Handle + ); + +EFI_STATUS InstallConInDevice( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx, + IN AMI_EFIKEYCODE_PROTOCOL *KeycodeIn, + IN EFI_HANDLE Handle + ); + +EFI_STATUS InstallSimplePointerDevice( + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer, + IN EFI_HANDLE Handle + ); + +EFI_STATUS ConOutHandleCheck( + IN EFI_HANDLE Handle + ); + +EFI_STATUS ConInHandleCheck( + IN EFI_HANDLE Handle + ); + +VOID CSSetKbLayoutNotifyFn( + IN EFI_EVENT Event, + IN VOID *Context +); + +EFI_HII_DATABASE_PROTOCOL *HiiDatabase = NULL; +EFI_HII_KEYBOARD_LAYOUT *gKeyDescriptorList = NULL; +UINT16 KeyDescriptorListSize = 0; +static EFI_GUID SetKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID; + +EFI_STATUS ConSimplePointerHandleCheck( IN EFI_HANDLE Handle ); + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterDriverBindingProtocol = { + CSSupported, + CSStart, + CSStop, + 0x10, + NULL, + NULL + }; +AMI_MULTI_LANG_SUPPORT_PROTOCOL gMultiLangSupportProtocol = { + KeyboardLayoutMap +}; + +#ifdef EFI_DEBUG +#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core +#ifndef LANGUAGE_CODE_ENGLISH +#define LANGUAGE_CODE_ENGLISH "eng" +#endif +static BOOLEAN LanguageCodesEqual( + CONST CHAR8* LangCode1, CONST CHAR8* LangCode2 +){ + return LangCode1[0]==LangCode2[0] + && LangCode1[1]==LangCode2[1] + && LangCode1[2]==LangCode2[2]; +} +static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; +#endif +static CHAR16 *gDriverName=L"AMI Console Splitter Driver"; +static CHAR16 *gControllerName=L"AMI Console Splitter"; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: ComponentNameGetControllerName +// +// Description: +// EFI_COMPONENT_NAME_PROTOCOL GetControllerName function +// +// Input: +// IN EFI_COMPONENT_NAME_PROTOCOL* This - pointer to protocol instance +// IN EFI_HANDLE Controller - controller handle +// IN EFI_HANDLE ChildHandle - child handle +// IN CHAR8* Language - pointer to language description +// OUT CHAR16** ControllerName - pointer to store pointer to controller name +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - controller name returned +// EFI_INVALID_PARAMETER - language undefined +// EFI_UNSUPPORTED - given language not supported +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +static EFI_STATUS ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName +) +{ + //Supports only English + if(!Language || !ControllerName) + return EFI_INVALID_PARAMETER; + + if ( ChildHandle!=ConSplitHandle + || !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH) + ) return EFI_UNSUPPORTED; + + *ControllerName=gControllerName; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Name: ComponentNameGetDriverName +// +// Description: +// EFI_COMPONENT_NAME_PROTOCOL GetDriverName function +// +// Input: +// IN EFI_COMPONENT_NAME_PROTOCOL* This - pointer to protocol instance +// IN CHAR8* Language - pointer to language description +// OUT CHAR16** DriverName - pointer to store pointer to driver name +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - driver name returned +// EFI_INVALID_PARAMETER - language undefined +// EFI_UNSUPPORTED - given language not supported +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +static EFI_STATUS ComponentNameGetDriverName( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName +) +{ + //Supports only English + if(!Language || !DriverName) + return EFI_INVALID_PARAMETER; + + if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) + return EFI_UNSUPPORTED; + else + *DriverName=gDriverName; + + return EFI_SUCCESS; +} + +//Component Name Protocol +static EFI_COMPONENT_NAME2_PROTOCOL gComponentName = { + ComponentNameGetDriverName, + ComponentNameGetControllerName, + LANGUAGE_CODE_ENGLISH +}; +#endif + +EFI_CONSOLE_CONTROL_SCREEN_MODE ScreenMode = EfiConsoleControlScreenText; +BOOLEAN CursorVisible = TRUE; +BOOLEAN StdInLocked = FALSE; + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: GetMode +// +// Description: +// This function returns current console mode +// +// Input: +// IN EFI_CONSOLE_CONTROL_PROTOCOL *This - pointer to console protocol +// OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode - placeholder for mode to return +// OUT OPTIONAL BOOLEAN *UgaExists - if not NULL on return will have current UGA present state +// OUT OPTIONAL BOOLEAN *StdInLocked - if not NULL on return will have value of STD_IN_LOCKED state +// +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function returns correct values +// +// Modified: +// +// Referrals: +// ScreenMode +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS GetMode( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *UgaExists OPTIONAL, + OUT BOOLEAN *StdInLocked OPTIONAL +) +{ + if (Mode) *Mode = ScreenMode; + if (UgaExists) *UgaExists = TRUE; + if (StdInLocked) *StdInLocked = FALSE; + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: SetMode +// +// Description: +// This function sets current console mode +// +// Input: +// IN EFI_CONSOLE_CONTROL_PROTOCOL *This - pointer to console protocol +// IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode - mode to set +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - mode set successfully +// EFI_INVALID_PARAMETER - incorrect mode given +// +// Modified: +// ScreenMode +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS SetMode( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode +) +{ + if (ScreenMode != Mode) + { + ScreenMode = Mode; + if (ScreenMode == EfiConsoleControlScreenText) + { + //Restore UGA mode when switching from graphics to text + DLINK *ListPtr = ConOutList.pHead; + CON_SPLIT_OUT *SimpleOut; + while ( ListPtr != NULL) + { + SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT); + RestoreUgaMode(SimpleOut->Handle); + ListPtr = ListPtr->pNext; + } + + if (CursorVisible) + mCSOutProtocol.EnableCursor(&mCSOutProtocol,TRUE); + } + else if (ScreenMode == EfiConsoleControlScreenGraphics) + { + DLINK *ListPtr = ConOutList.pHead; + CON_SPLIT_OUT *SimpleOut; + CursorVisible = MasterMode.CursorVisible; + if (CursorVisible) + mCSOutProtocol.EnableCursor(&mCSOutProtocol,FALSE); + //Save UGA mode when switching from text to graphics + while ( ListPtr != NULL) + { + SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT); + SaveUgaMode(SimpleOut->Handle); + ListPtr = ListPtr->pNext; + } + + } + else return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: LockStdIn +// +// Description: +// This function toggles STD_IN_LOCKED state +// +// Input: +// IN EFI_CONSOLE_CONTROL_PROTOCOL *This - pointer to console protocol +// IN CHAR16 *Password - pointer to password string +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// +// Modified: +// StdInLocked +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS LockStdIn( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password +) +{ + //TODO: add support for the password + StdInLocked = !StdInLocked; + return EFI_SUCCESS; +}; + +EFI_GUID gConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + +EFI_CONSOLE_CONTROL_PROTOCOL gConsoleControlProtocol = { + GetMode, + SetMode, + LockStdIn +}; + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UpdateSystemTableConOut +// +// Description: +// This function updates system table ConOut pointer +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to event context +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID UpdateSystemTableConOut() +{ + UINT32 CRC32 = 0; + + if( ConOutList.Size==0 ){ + //Initialize all the global variables used by + //splitter implementation of TxtOut. + //When physical ConOut devices are available, the initialization is performed + //within InitModesTable routine. + VERIFY_EFI_ERROR(ResizeSplitterBuffer(0)); + VERIFY_EFI_ERROR(pBS->AllocatePool(EfiBootServicesData, sizeof(SUPPORT_RES), &SupportedModes)); + SupportedModes[0].Rows = 25; + SupportedModes[0].Columns = 80; + SupportedModes[0].AllDevices = TRUE; + } + + pST->ConOut = &mCSOutProtocol; + pST->ConsoleOutHandle = ConSplitHandle; + // We want to initialize ConOut-related fields of the systems table early + // to workaround bugs in some of the UEFI OpROM drivers + // that are using pST->ConOut without NULL checking. + // We are not installing the instance of SimpleTextOut on ConSplitHandle though, + // because it confuses the logic of TSE notification callbacks. + // The protocol is installed once all ConOut devices are connected + // in ReportNoConOutError. + if (pST->StdErr==NULL){ + pST->StdErr = pST->ConOut; + pST->StandardErrorHandle = pST->ConsoleOutHandle; + } + + // Now calculate the CRC32 value + pST->Hdr.CRC32 = 0; + pST->BootServices->CalculateCrc32(pST, sizeof(EFI_SYSTEM_TABLE), &CRC32); + pST->Hdr.CRC32 = CRC32; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ReportNoConOutError +// +// Description: +// This function checks if physical ConOut devices are available. +// If not, DXE_NO_CON_OUT error is reported. +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to event context +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID ReportNoConOutError( + IN EFI_EVENT Event, + IN VOID *Context +) +{ +#if REPORT_NO_CON_OUT_ERROR + DLINK *Link; + EFI_STATUS Status; + + //Report error if no ConOut devices available or + // all console devices are fake devices (without device path). + for(Link = ConOutList.pHead; Link!=NULL; Link=Link->pNext){ + CON_SPLIT_OUT *SimpleOut = OUTTER(Link, Link, CON_SPLIT_OUT); + VOID *Dp; + + Status = pBS->HandleProtocol( + SimpleOut->Handle, &gEfiDevicePathProtocolGuid, &Dp + ); + if (!EFI_ERROR(Status)) break; // Got one device path + } + //Report error if no ConOut devices with device path exists + if( ConOutList.Size==0 || EFI_ERROR(Status) ) + ERROR_CODE(DXE_NO_CON_OUT, EFI_ERROR_MAJOR); +#endif + pBS->InstallMultipleProtocolInterfaces ( + &ConSplitHandle, &gSimpleTextOutGuid, &mCSOutProtocol, + &gConsoleControlProtocolGuid, &gConsoleControlProtocol, + NULL + ); + pBS->CloseEvent(Event); +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UpdateSystemTableConIn +// +// Description: +// This function updates system table ConIn pointer +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to event context +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID UpdateSystemTableConIn( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + UINT32 CRC32 = 0; + +#if REPORT_NO_CON_IN_ERROR + DLINK *Link; + EFI_STATUS Status; + + EFI_HOB_HANDOFF_INFO_TABLE *pHit; + static EFI_GUID guidHob = HOB_LIST_GUID; + + //Report error if no ConIn devices available or + // all console devices are fake devices (without device path). + for(Link = ConInList.pHead; Link!=NULL; Link=Link->pNext){ + CON_SPLIT_IN *SimpleIn = OUTTER(Link, Link, CON_SPLIT_IN); + VOID *Dp; + + Status = pBS->HandleProtocol( + SimpleIn->Handle, &gEfiDevicePathProtocolGuid, &Dp + ); + if (!EFI_ERROR(Status)) break; // Got one device path + } + + pHit = GetEfiConfigurationTable(pST, &guidHob); + //Report error if no ConIn devices with device path exists + if( (ConInList.Size == 0 || EFI_ERROR(Status)) && (pHit->BootMode == BOOT_WITH_FULL_CONFIGURATION)) + ERROR_CODE(DXE_NO_CON_IN, EFI_ERROR_MAJOR); +#endif + pST->ConIn = &mCSSimpleInProtocol; + + pBS->InstallMultipleProtocolInterfaces ( + &ConSplitHandle, + &gSimpleInGuid, &mCSSimpleInProtocol, + &gSimpleInExGuid, &mCSSimpleInExProtocol, + &gAmiEfiKeycodeGuid, &mCSKeycodeInProtocol, + &gEfiSimplePointerProtocolGuid, &mCSSimplePointerProtocol, + NULL + ); + + pST->ConsoleInHandle = ConSplitHandle; + + // Now calculate the CRC32 value + pST->Hdr.CRC32 = 0; + pST->BootServices->CalculateCrc32(pST, sizeof(EFI_SYSTEM_TABLE), &CRC32); + pST->Hdr.CRC32 = CRC32; + + pBS->CloseEvent(Event); +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSEntryPoint +// +// Description: +// This function is Console splitter driver entry point +// +// Input: +// IN EFI_HANDLE ImageHandle - image handle of Console splitter driver +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - driver installed successfully +// EFI_ERROR - error occured during execution +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + static EFI_GUID guidConInStarted = CONSOLE_IN_DEVICES_STARTED_PROTOCOL_GUID; + static EFI_GUID guidConOutStarted = CONSOLE_OUT_DEVICES_STARTED_PROTOCOL_GUID; + // {8FF925F1-8624-4d38-9ED2-F8F5AA94F84A} + static EFI_GUID gDummyProtocolGuid = + { 0x8ff925f1, 0x8624, 0x4d38, { 0x9e, 0xd2, 0xf8, 0xf5, 0xaa, 0x94, 0xf8, 0x4a } }; + + EFI_STATUS Status; + EFI_EVENT Event; + VOID *pRegistration; + SETUP_DATA *SetupData = NULL; + UINTN VariableSize = 0; + EFI_GUID SetupGuid = SETUP_GUID; + + // initialize AMI library + InitAmiLib(ImageHandle, SystemTable); + + // initiaize the ImageHandle and DriverBindingHandle + gConSplitterDriverBindingProtocol.DriverBindingHandle = NULL; + gConSplitterDriverBindingProtocol.ImageHandle = ImageHandle; + + // Install driver binding protocol here + Status = pBS->InstallMultipleProtocolInterfaces ( + &gConSplitterDriverBindingProtocol.DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, &gConSplitterDriverBindingProtocol, +#ifdef EFI_DEBUG + &gEfiComponentName2ProtocolGuid, &gComponentName, +#endif + &gAmiMultiLangSupportGuid, &gMultiLangSupportProtocol, + NULL); + + // Create and event for the Simple In Interface + Status = pBS->CreateEvent (EFI_EVENT_NOTIFY_WAIT, TPL_NOTIFY, + CSWaitForKey, &mCSSimpleInProtocol, + &mCSSimpleInProtocol.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + // Create and event for the SimpleInEx Interface + Status = pBS->CreateEvent (EFI_EVENT_NOTIFY_WAIT, TPL_NOTIFY, + CSWaitForKey, &mCSSimpleInExProtocol, + &mCSSimpleInExProtocol.WaitForKeyEx + ); + ASSERT_EFI_ERROR (Status); + + + // Create and event for the KeycodeIn Interface + Status = pBS->CreateEvent (EFI_EVENT_NOTIFY_WAIT, TPL_NOTIFY, + CSWaitForKey, &mCSKeycodeInProtocol, + &mCSKeycodeInProtocol.WaitForKeyEx + ); + ASSERT_EFI_ERROR (Status); + + // Create an event for the SimplePointer Interface + Status = pBS->CreateEvent( + EFI_EVENT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterSimplePointerWaitForInput, + &mCSSimplePointerProtocol, + &mCSSimplePointerProtocol.WaitForInput + ); + ASSERT_EFI_ERROR(Status); + + // Initialize the global lists here + DListInit(&ConInList); + DListInit(&ConOutList); + DListInit(&ConPointerList); + DListInit(&ConInKeyNotifyList); + + // Register Protocol Notification to expose + // Console Splitter interface only after all consoles initialized + RegisterProtocolCallback( + &guidConOutStarted, ReportNoConOutError, + NULL, &Event,&pRegistration + ); + RegisterProtocolCallback( + &guidConInStarted, UpdateSystemTableConIn, + NULL, &Event,&pRegistration + ); + + //We need a valid handle + //The only way to create it is to install a protocol + //Let's install a dummy protocol + pBS->InstallMultipleProtocolInterfaces ( + &ConSplitHandle, + &gDummyProtocolGuid, NULL, + NULL + ); + + //install pST->ConOut + UpdateSystemTableConOut(); + +//multi keyboard layout support + Status = pBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + CSSetKbLayoutNotifyFn, + NULL, + &SetKeyboardLayoutEventGuid, + &Event); + CSSetKbLayoutNotifyFn(NULL, NULL); + + // Lighten up the keyboard(s) lights + if(NumLockSet == FALSE) { + Status = GetEfiVariable(L"Setup", &SetupGuid, NULL, &VariableSize, &SetupData); + if (!EFI_ERROR(Status)) { + if (SetupData->Numlock) { + mCSToggleState |= NUM_LOCK_ACTIVE; + } + pBS->FreePool(SetupData); + } + NumLockSet=TRUE; + } + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSSupported +// +// Description: +// This function is Console splitter driver Supported function for driver +// binding protocol +// +// Input: +// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol +// IN EFI_HANDLE ControllerHandle - controller handle to install driver on +// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - driver supports given controller +// EFI_UNSUPPORTED - driver doesn't support given controller +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn = NULL; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx = NULL; + AMI_EFIKEYCODE_PROTOCOL *KeycodeIn = NULL; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut = NULL; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer = NULL; + EFI_STATUS SimplePointerStatus; + EFI_STATUS OutStatus; + EFI_STATUS InStatus; + EFI_STATUS InExStatus; + EFI_STATUS KeycodeInStatus; + INT32 Dummy; + + if (ControllerHandle == ConSplitHandle) + return EFI_UNSUPPORTED; + + // check to see if this device has a simple text out protocol installed on it + OutStatus = pBS->OpenProtocol ( ControllerHandle, &gSimpleTextOutGuid, + &SimpleOut, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + if(!EFI_ERROR(OutStatus)) { + OutStatus = IsModeSupported(SimpleOut, MasterMode.Mode, &Dummy); + if(EFI_ERROR(OutStatus)) { + pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid, + This->DriverBindingHandle, ControllerHandle); + } + } + + + // check to see if this device has a simple input protocol installed on it + InStatus = pBS->OpenProtocol ( ControllerHandle, &gSimpleInGuid, + &SimpleIn, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + InExStatus = pBS->OpenProtocol ( ControllerHandle, &gSimpleInExGuid, + &SimpleInEx, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + KeycodeInStatus = pBS->OpenProtocol ( ControllerHandle, &gAmiEfiKeycodeGuid, + &KeycodeIn, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + + // check if device has simple pointer protocol installed on it + SimplePointerStatus = pBS->OpenProtocol( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + &SimplePointer, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR(SimplePointerStatus)) + pBS->CloseProtocol( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + if (!EFI_ERROR(OutStatus)) + pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid, + This->DriverBindingHandle, ControllerHandle); + + if (!EFI_ERROR(InStatus)) + pBS->CloseProtocol(ControllerHandle, &gSimpleInGuid, + This->DriverBindingHandle, ControllerHandle); + + if (!EFI_ERROR(InExStatus)) + pBS->CloseProtocol(ControllerHandle, &gAmiEfiKeycodeGuid, + This->DriverBindingHandle, ControllerHandle); + + if (!EFI_ERROR(KeycodeInStatus)) + pBS->CloseProtocol(ControllerHandle, &gSimpleInExGuid, + This->DriverBindingHandle, ControllerHandle); + + if ( EFI_ERROR(SimplePointerStatus) && + EFI_ERROR(OutStatus) && + EFI_ERROR(InStatus) && + EFI_ERROR(InExStatus) && + EFI_ERROR(KeycodeInStatus) ) + return EFI_UNSUPPORTED; + + return EFI_SUCCESS; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSStart +// +// Description: +// This function is Console splitter driver Start function for driver +// binding protocol +// +// Input: +// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol +// IN EFI_HANDLE ControllerHandle - controller handle to install driver on +// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - driver started successfully +// EFI_UNSUPPORTED - driver didn't start +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSStart( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn = NULL; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx = NULL; + AMI_EFIKEYCODE_PROTOCOL *KeycodeIn = NULL; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut = NULL; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer = NULL; + EFI_STATUS Status; + EFI_STATUS OutStatus; + EFI_STATUS InStatus; + EFI_STATUS InExStatus; + EFI_STATUS KeycodeInStatus; + + // grab the pointers for the ConIn, ConOut, and StdErr from the System Table + // install the current handles for these devices. + + // if Simple In, add the Con In device to the list and + InStatus = pBS->OpenProtocol(ControllerHandle, &gSimpleInGuid, + &SimpleIn, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + InExStatus = pBS->OpenProtocol(ControllerHandle, &gSimpleInExGuid, + &SimpleInEx, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + KeycodeInStatus = pBS->OpenProtocol(ControllerHandle, &gAmiEfiKeycodeGuid, + &KeycodeIn, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (!EFI_ERROR(InStatus) || !EFI_ERROR(InExStatus) || !EFI_ERROR(KeycodeInStatus)) + { + InStatus = InstallConInDevice(SimpleIn, SimpleInEx, KeycodeIn, ControllerHandle); + if (InStatus == EFI_OUT_OF_RESOURCES) + return InStatus; + + if (!EFI_ERROR(InStatus)) + pBS->OpenProtocol(ControllerHandle, &gSimpleInGuid, + &SimpleIn, This->DriverBindingHandle, + ConSplitHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); + } + + Status = pBS->OpenProtocol( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + &SimplePointer, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR(Status)) { + Status = InstallSimplePointerDevice( SimplePointer, ControllerHandle ); + if (!EFI_ERROR(Status)) { + Status = pBS->OpenProtocol( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + &SimplePointer, + This->DriverBindingHandle, + ConSplitHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else if (Status == EFI_OUT_OF_RESOURCES) + return Status; + } + + // if it has a simple text out add the Con Out device to the list and + OutStatus = pBS->OpenProtocol(ControllerHandle, &gSimpleTextOutGuid, + &SimpleOut, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); + if (!EFI_ERROR(OutStatus) ) + { + OutStatus = InstallConOutDevice(SimpleOut, ControllerHandle); + if (OutStatus == EFI_OUT_OF_RESOURCES) + return OutStatus; + + if (!EFI_ERROR(OutStatus)) + { + RestoreTheScreen(ControllerHandle,SimpleOut); + pBS->OpenProtocol(ControllerHandle, &gSimpleTextOutGuid, + &SimpleOut, This->DriverBindingHandle, + ConSplitHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); + } + } + + // If no devices were installed, then Houston we have a problem + if ( EFI_ERROR(OutStatus) && EFI_ERROR(InStatus) && EFI_ERROR(Status) ) + return EFI_UNSUPPORTED; + + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSStop +// +// Description: +// This function is Console splitter driver Stop function for driver +// binding protocol +// +// Input: +// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol +// IN EFI_HANDLE ControllerHandle - controller handle to install driver on +// IN UINTN NumberOfChildren - number of childs on this handle +// IN OPTIONAL EFI_HANDLE *ChildHandleBuffer - pointer to child handles array +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - driver stopped successfully +// EFI_INVALID_PARAMETER - invalid values passed for NumberOfChildren or +// ChildHandleBuffer +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL +) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + DLINK *ListPtr; + CON_SPLIT_IN *SimpleIn; + CON_SPLIT_OUT *SimpleOut; + CON_SPLIT_SIMPLE_POINTER *SimplePointer = NULL; + BOOLEAN Stopped = FALSE; + DLINK *HandleLink = NULL; + CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL; + CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL; + + if (NumberOfChildren == 0) + return EFI_SUCCESS; + + if ( NumberOfChildren != 1 || + ChildHandleBuffer == NULL || + *ChildHandleBuffer!= ConSplitHandle ) + return EFI_INVALID_PARAMETER; + + // remove simple text out, simple in, simple pointer + ListPtr = ConOutList.pHead; + while ( ListPtr != NULL) + { + SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT); + if ( SimpleOut->Handle == ControllerHandle) + { + pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid, + This->DriverBindingHandle, ControllerHandle); + + pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid, + This->DriverBindingHandle, ConSplitHandle); + DListDelete(&ConOutList, ListPtr); + Stopped = TRUE; + SaveTheScreen(ControllerHandle, SimpleOut->SimpleOut); + Status = pBS->FreePool(SimpleOut); + break; + } + + ListPtr = ListPtr->pNext; + } + + //If we already populated pST->ConOut preserve + //screen buffer and list of supported modes + //to keep using it when ConOut devices are connected + if(ConOutList.Size == 0 && !pST->ConOut) //all devices stops + { + if(SupportedModes != NULL) + { + pBS->FreePool(SupportedModes); + SupportedModes = NULL; + } + + if(ScreenBuffer != NULL) + { + pBS->FreePool(ScreenBuffer); + ScreenBuffer = NULL; + } + + if(AttributeBuffer != NULL) + { + pBS->FreePool(AttributeBuffer); + AttributeBuffer = NULL; + } + + MasterMode.Mode=0; + } else { + if(Stopped && ConOutList.Size > 0) //re-initialize supported modes buffer if at least one child was stopped + AdjustSupportedModes(); + } + + ListPtr = ConInList.pHead; + while ( ListPtr != NULL) + { + SimpleIn = OUTTER(ListPtr, Link, CON_SPLIT_IN); + if ( SimpleIn->Handle == ControllerHandle) + { + DListDelete(&ConInList, ListPtr); + + pBS->CloseProtocol(ControllerHandle, &gSimpleInGuid, + This->DriverBindingHandle, ControllerHandle); + + pBS->CloseProtocol(ControllerHandle, &gSimpleInExGuid, + This->DriverBindingHandle, ControllerHandle); + + pBS->CloseProtocol(ControllerHandle, &gAmiEfiKeycodeGuid, + This->DriverBindingHandle, ControllerHandle); + + pBS->CloseProtocol(ControllerHandle, &gSimpleInGuid, + This->DriverBindingHandle, ConSplitHandle); + break; + } + + ListPtr = ListPtr->pNext; + } + + if (ListPtr != NULL && SimpleIn->SimpleInEx != NULL) { + for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) { + CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY); + + for (HandleLink = CsInKeyNotify->NotifyHandleList.pHead; HandleLink != NULL; + HandleLink = HandleLink->pNext) { + CsInNotifyHandle = OUTTER(HandleLink, Link, CON_SPLIT_IN_KEY_NOTIFY_HANDLE); + + if (SimpleIn->SimpleInEx != CsInNotifyHandle->SimpleInEx) { + continue; + } + + Status = SimpleIn->SimpleInEx->UnregisterKeyNotify( + SimpleIn->SimpleInEx, CsInNotifyHandle->NotifyHandle); + + DListDelete(&(CsInKeyNotify->NotifyHandleList), HandleLink); + Status = pBS->FreePool(CsInNotifyHandle); + } + } + Status = pBS->FreePool(SimpleIn); + } + + ListPtr = ConPointerList.pHead; + while (ListPtr != NULL) { + SimplePointer = OUTTER(ListPtr, Link, CON_SPLIT_SIMPLE_POINTER); + if ( SimplePointer->Handle == ControllerHandle ) { + DListDelete(&ConPointerList, ListPtr); + + pBS->CloseProtocol( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + pBS->CloseProtocol( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + This->DriverBindingHandle, + ConSplitHandle + ); + Status = pBS->FreePool(SimplePointer); + break; + } + ListPtr = ListPtr->pNext; + } + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UpdateConVar +// +// Description: +// This function stores device path of given controller in EFI variable with +// name sVarName +// +// Input: +// IN EFI_HANDLE Controller - controller, which device path to store +// IN CHAR16 *sVarName - name of EFI variable to store device path under +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID UpdateConVar( + IN EFI_HANDLE Controller, + IN CHAR16 *sVarName +) +{ + static EFI_GUID guidDevicePath = EFI_DEVICE_PATH_PROTOCOL_GUID; + static EFI_GUID guidEfiVar = EFI_GLOBAL_VARIABLE; + EFI_DEVICE_PATH_PROTOCOL *pDevicePath, *pConDev = NULL; + EFI_STATUS Status; + UINTN DataSize=0; + UINT32 Attributes; + + Status = pBS->HandleProtocol(Controller,&guidDevicePath, &pDevicePath); + if (EFI_ERROR(Status)) + return; + + Status = GetEfiVariable(sVarName, &guidEfiVar, &Attributes, &DataSize, &pConDev); + if (EFI_ERROR(Status)) + { + if (Status!=EFI_NOT_FOUND) + return; + + DataSize = DPLength(pDevicePath); + pRS->SetVariable(sVarName, &guidEfiVar, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, pDevicePath); + return; + } + + if (!DPIsOneOf(pConDev, pDevicePath, FALSE)) + { + EFI_DEVICE_PATH_PROTOCOL *pNewConDev = DPAddInstance(pConDev, pDevicePath); + DataSize = DPLength(pNewConDev); + pRS->SetVariable(sVarName, &guidEfiVar, Attributes, DataSize, pNewConDev); + pBS->FreePool(pNewConDev); + } + + pBS->FreePool(pConDev); +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: InstallSimplePointerDevice +// +// Description: +// This function adds another ConIn device to splitter +// +// Input: +// *SimpleIn - pointer to new protocol +// *SimpleInEx - pointer to new extended protocol +// *KeycodeIn - pointer to AMI key code protocol +// Handle - handle of new device +// +// Output: +// EFI_SUCCESS - device added successfully +// EFI_UNSUPPORTED - device not supported +// EFI_OUT_OF_RESOURCES - not enough resources to perform operation +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS InstallSimplePointerDevice( + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer, + IN EFI_HANDLE Handle ) +{ + EFI_STATUS Status; + CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL; + + if (EFI_ERROR(ConSimplePointerHandleCheck(Handle))) + return EFI_UNSUPPORTED; + + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CON_SPLIT_SIMPLE_POINTER), + &ConSimplePointer + ); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + ConSimplePointer->SimplePointer = SimplePointer; + ConSimplePointer->Handle = Handle; + mCSSimplePointerProtocol.Mode->LeftButton |= SimplePointer->Mode->LeftButton; + mCSSimplePointerProtocol.Mode->RightButton |= SimplePointer->Mode->RightButton; + DListAdd(&ConPointerList, &ConSimplePointer->Link); + return EFI_SUCCESS; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: InstallConOutDevice +// +// Description: +// This function adds another ConOut device to splitter +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut - pointer to new protocol +// IN EFI_HANDLE Handle - handle of new device +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - device added successfully +// EFI_UNSUPPORTED - device not supported +// EFI_OUT_OF_RESOURCES - not enough resources to perform operation +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS InstallConOutDevice( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut, + IN EFI_HANDLE Handle +) +{ + EFI_STATUS Status; + CON_SPLIT_OUT *ConOut; + INT32 DeviceModeNumber = 0; + BOOLEAN FirstChild = FALSE; + + if (EFI_ERROR(ConOutHandleCheck(Handle))) + return EFI_UNSUPPORTED; + + if(MasterMode.Mode != 0) //already in extended mode + if (EFI_ERROR(IsModeSupported(SimpleOut, MasterMode.Mode, &DeviceModeNumber))) + return EFI_UNSUPPORTED; //device doesn't support current mode - do not include into list + + + if (ConOutList.Size==0 && !InitModesTableCalled) //this is first call + { + FirstChild = TRUE; + Status = InitModesTable(SimpleOut, Handle); + if(EFI_ERROR(Status)) //first device becomes master + return Status; + } + else + UpdateModesTable(SimpleOut, Handle); //all next devices + + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(CON_SPLIT_OUT), &ConOut); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + ConOut->SimpleOut = SimpleOut; + + ConOut->Handle = Handle; + + DListAdd(&ConOutList, &(ConOut->Link)); + + if(!FirstChild) { + // set child display to a current master mode + SimpleOut->SetMode(SimpleOut, DeviceModeNumber); + SimpleOut->EnableCursor(SimpleOut, MasterMode.CursorVisible); + } + UpdateConVar(Handle, L"ConOutDev"); + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: InstallConInDevice +// +// Description: +// This function adds another ConIn device to splitter +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn - pointer to new protocol +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx - pointer to new extended +// protocol +// IN AMI_EFIKEYCODE_PROTOCOL *KeycodeIn - pointer to AMI key code protocol +// IN EFI_HANDLE Handle - handle of new device +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - device added successfully +// EFI_UNSUPPORTED - device not supported +// EFI_OUT_OF_RESOURCES - not enough resources to perform operation +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS InstallConInDevice( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx, + IN AMI_EFIKEYCODE_PROTOCOL *KeycodeIn, + IN EFI_HANDLE Handle +) +{ + EFI_STATUS Status; + CON_SPLIT_IN *ConIn; + DLINK *ListPtr; + CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL; + CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL; + + if (EFI_ERROR(ConInHandleCheck(Handle))) + return EFI_UNSUPPORTED; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(CON_SPLIT_IN), &ConIn); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + ConIn->SimpleIn = SimpleIn; + ConIn->SimpleInEx = SimpleInEx; + ConIn->KeycodeInEx = KeycodeIn; + + ConIn->Handle = Handle; + + DListAdd(&ConInList, &(ConIn->Link)); + + UpdateConVar(Handle, L"ConInDev"); + + if (SimpleInEx == NULL) { + return EFI_SUCCESS; + } + + SimpleInEx->SetState(SimpleInEx, &mCSToggleState); + + for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) { + CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY); + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(CON_SPLIT_IN_KEY_NOTIFY_HANDLE), &CsInNotifyHandle); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + CsInNotifyHandle->SimpleInEx = SimpleInEx; + + Status = SimpleInEx->RegisterKeyNotify(SimpleInEx, &CsInKeyNotify->KeyData, + CsInKeyNotify->KeyNotificationFunction, &(CsInNotifyHandle->NotifyHandle)); + if (EFI_ERROR(Status)) { + Status = pBS->FreePool(CsInNotifyHandle); + continue; + } + + DListAdd(&(CsInKeyNotify->NotifyHandleList), &(CsInNotifyHandle->Link)); + } + + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConOutHandleCheck +// +// Description: +// This function checks if ConOut device already present in Splitter +// +// Input: +// IN EFI_HANDLE Handle - handle of device to check +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - device not present +// EFI_UNSUPPORTED - device already present +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS ConOutHandleCheck( + IN EFI_HANDLE Handle +) +{ + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + // if the list is empty return the status that was passed in + if (SimpleOut == NULL) + return EFI_SUCCESS; + + // check for a handle that was already identified + while ( SimpleOut != NULL) + { + // check the handle + if (SimpleOut->Handle == Handle) + return EFI_UNSUPPORTED; + // go to the next element in the list + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + } + + // if it is a new handle return the status pass in + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConInHandleCheck +// +// Description: +// This function checks if ConIn device already present in Splitter +// +// Input: +// IN EFI_HANDLE Handle - handle of device to check +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - device not present +// EFI_UNSUPPORTED - device already present +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS ConInHandleCheck( + IN EFI_HANDLE Handle +) +{ + CON_SPLIT_IN *SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN); + + // if the list is empty return the status that was passed in + if (SimpleIn == NULL) + return EFI_SUCCESS; + + // check for a handle that was already identified + while ( SimpleIn != NULL) + { + // check the handle + if (SimpleIn->Handle == Handle) + return EFI_UNSUPPORTED; + // go to the next element in the list + SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN); + } + + // if it is a new handle return the status pass in + return EFI_SUCCESS; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConSimplePointerHandleCheck +// +// Description: +// This function checks if ConIn device already present in Splitter. +// +// Input: Handle - handle of device to check +// +// Output: +// EFI_SUCCESS - device not present +// EFI_UNSUPPORTED - device already present +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS ConSimplePointerHandleCheck( IN EFI_HANDLE Handle ) +{ + CON_SPLIT_SIMPLE_POINTER *SimplePointer; + + SimplePointer = OUTTER(ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER); + + // if the list is empty return the status that was passed in + if (SimplePointer == NULL) + return EFI_SUCCESS; + + // check for a handle that was already identified + while ( SimplePointer != NULL) { + + // check the handle + if (SimplePointer->Handle == Handle) + return EFI_UNSUPPORTED; + + // go to the next element in the list + SimplePointer = OUTTER(SimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER); + } + + // if it is a new handle return the status pass in + return EFI_SUCCESS; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: InitModesTable +// +// Description: +// This function fills the SupportedModes table with modes supported by first +// simple text out device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol +// IN EFI_HANDLE Handle - handle of first ConOut device +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - table filled successfully +// EFI_OUT_OF_RESOURCES - not enough resources to perform operation +// +// Modified: SupportedModes, MasterMode +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS InitModesTable( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN EFI_HANDLE Handle +) +{ + INT32 MaxMode; + INT32 CurrentMode; + UINTN Rows, Columns; + INT32 i; + EFI_STATUS Status; + + if(Handle == ConSplitHandle) + return EFI_SUCCESS; + + InitModesTableCalled = TRUE; + + MaxMode = This->Mode->MaxMode; + CurrentMode = This->Mode->Mode; + + //The SupportedModes structure + //may have already been initialized in UpdateSystemTableConOut. + //If this is the case, free the memory before reinitialization. + if (SupportedModes!=NULL){ + //If SupportedModes is not NULL, + //ResizeSplitterBuffer(0) has already been called + pBS->FreePool(SupportedModes); + SupportedModes = NULL; + } + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(SUPPORT_RES)* MaxMode, + &SupportedModes); + if(EFI_ERROR(Status)) + { + MasterMode.MaxMode = 1; + return EFI_SUCCESS; + } + + MasterMode.MaxMode = MaxMode; //modify default value + + for(i = 0; i < MaxMode; i++) + { + Status = This->QueryMode(This, i, &Columns, &Rows); + SupportedModes[i].Rows = (INT32)Rows; + SupportedModes[i].Columns = (INT32)Columns; + SupportedModes[i].AllDevices = EFI_ERROR(Status) ? FALSE : TRUE; + } + +//Make sure MasterMode.Mode <> CurrentMode, otherwise ResizeSplitterBuffer won't do anything + MasterMode.Mode = CurrentMode + 1; + Status = ResizeSplitterBuffer(CurrentMode); + MasterMode.Mode = CurrentMode; + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: IsModeSupported +// +// Description: +// This function determines if mode, specified by ModeNum supported by +// simple text out device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol to check +// IN UINTN ModeNum - mode to check +// OUT INT32 *DeviceModeNumber - device mode number correspondent to ModeNum +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - mode supported by device +// EFI_UNSUPPORTED - mode not supported by device +// +// Modified: +// +// Referrals: SupportedModes +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS IsModeSupported( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNum, + OUT INT32 *DeviceModeNumber) +{ + INT32 MaxMode; + UINTN Rows, Columns; + INT32 i; + EFI_STATUS Status; + + MaxMode = This->Mode->MaxMode; + for(i = 0; i < MaxMode; i++) + { + Status = This->QueryMode(This, i , &Columns, &Rows); + if (!EFI_ERROR(Status) && \ + SupportedModes[ModeNum].Rows == (INT32)Rows && \ + SupportedModes[ModeNum].Columns == (INT32)Columns) + { + *DeviceModeNumber = i; + return EFI_SUCCESS; + } + + } + return EFI_UNSUPPORTED; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UpdateModesTable +// +// Description: +// This function updates supported modes table when new devices started don't +// support some of this modes +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol to check +// IN EFI_HANDLE Handle - handle of device +// +// Output: +// VOID +// +// Modified: SupportedModes +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID UpdateModesTable( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN EFI_HANDLE Handle +) +{ + INT32 i, ModeNumber; + EFI_STATUS Status; + + if(Handle == ConSplitHandle) + return; + + + for(i = 0; i < MasterMode.MaxMode; i++) { + if(SupportedModes[i].AllDevices == FALSE) continue; + Status = IsModeSupported(This, i, &ModeNumber); + SupportedModes[i].AllDevices = EFI_ERROR(Status) ? FALSE : TRUE; + } + +//update MasterMode.MaxMode value based on modes supported by different devices +//lookup for the first mode above 1 not supported by all devices - this will be +//new MaxMode value + for(i = 2; i < MasterMode.MaxMode; i++) { + if(SupportedModes[i].AllDevices == FALSE) { + MasterMode.MaxMode = i; + break; + } + } +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ResizeSplitterBuffer +// +// Description: +// This function allocates new buffers when mode changed +// +// Input: +// IN INT32 ModeNum - new mode +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - new buffers allocated +// EFI_OUT_OF_RESOURCES - not enough resources to perform operation +// +// Modified: ScreenBuffer, EndOfTheScreen,AttributeBuffer +// +// Referrals: SupportedModes, MasterMode +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS ResizeSplitterBuffer( + IN INT32 ModeNum +) +{ + INT32 Row, Col; + CHAR16 *NewCharBuffer; + INT32 *NewAttributeBuffer; + EFI_STATUS Status; + + if(ModeNum != MasterMode.Mode || SupportedModes == NULL) //check if it is first init + { + + if(SupportedModes == NULL) + { + Row = 25; + Col = 80; + } + else + { + Row = SupportedModes[ModeNum].Rows; + Col = SupportedModes[ModeNum].Columns; + } + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(CHAR16) * Row * Col, + &NewCharBuffer); + if(EFI_ERROR(Status)) + return Status; + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(INT32) * Row * Col, + &NewAttributeBuffer); + if(EFI_ERROR(Status)) + { + pBS->FreePool(NewCharBuffer); + return Status; + } + + if(ScreenBuffer != NULL) + pBS->FreePool(ScreenBuffer); + ScreenBuffer = NewCharBuffer; + EndOfTheScreen = ScreenBuffer + (Row * Col); + + if(AttributeBuffer != NULL) + pBS->FreePool(AttributeBuffer); + AttributeBuffer = NewAttributeBuffer; + Columns = Col; + } + MemClearScreen(); + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSSetKbLayoutNotifyFn +// +// Description: +// This function stores a pointer to the current keyboard layout +// +// Input: +// IN EFI_EVENT Event - event that caused this function to be called +// IN VOID *Context - context of the event +// +// Output: +// VOID +// +// Modified: +// gKeyDescriptorList - changed to point to the current EFI_HII_KEYBOARD_LAYOUT +// or, NULL if no layout currently set +// LayoutLength - set to the size of the current keyboard layout +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID CSSetKbLayoutNotifyFn( + IN EFI_EVENT Event, + IN VOID *Context) +{ + EFI_STATUS Status; + + if(HiiDatabase == NULL) { + Status = pBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase); + if(EFI_ERROR(Status)) + return; + } + + Status = HiiDatabase->GetKeyboardLayout(HiiDatabase, NULL, &KeyDescriptorListSize, gKeyDescriptorList); + if (Status == EFI_BUFFER_TOO_SMALL) { + if(gKeyDescriptorList != NULL) + pBS->FreePool(gKeyDescriptorList); + + Status = pBS->AllocatePool(EfiBootServicesData, KeyDescriptorListSize, &gKeyDescriptorList); + if(EFI_ERROR(Status)) { + KeyDescriptorListSize = 0; + gKeyDescriptorList = NULL; + } else { + HiiDatabase->GetKeyboardLayout(HiiDatabase, NULL, &KeyDescriptorListSize, gKeyDescriptorList); + } + } else if(Status == EFI_NOT_FOUND) { + if(gKeyDescriptorList != NULL) { + pBS->FreePool(gKeyDescriptorList); + KeyDescriptorListSize = 0; + gKeyDescriptorList = NULL; + } + } +} + +VOID AdjustSupportedModes( + VOID +) +{ + DLINK *ListPtr; + CON_SPLIT_OUT *SimpleOut; + EFI_STATUS Status; + INT32 i; + UINTN Columns; + UINTN Rows; + + ListPtr = ConOutList.pHead; + SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT); + +//re-initialize supported modes buffer + if(MasterMode.MaxMode < SimpleOut->SimpleOut->Mode->MaxMode) { + if (SupportedModes != NULL) + pBS->FreePool(SupportedModes); + Status = pBS->AllocatePool(EfiBootServicesData, SimpleOut->SimpleOut->Mode->MaxMode * sizeof(SUPPORT_RES), &SupportedModes); + if(EFI_ERROR(Status)) + return; + } + MasterMode.MaxMode = SimpleOut->SimpleOut->Mode->MaxMode; + for(i = 0; i < MasterMode.MaxMode; i++) { + Status = SimpleOut->SimpleOut->QueryMode(SimpleOut->SimpleOut, i, &Columns, &Rows); + SupportedModes[i].Rows = (INT32)Rows; + SupportedModes[i].Columns = (INT32)Columns; + SupportedModes[i].AllDevices = EFI_ERROR(Status) ? FALSE : TRUE; + } + +//update supported modes buffer + ListPtr = ListPtr->pNext; + while(ListPtr != NULL) { + SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT); + UpdateModesTable(SimpleOut->SimpleOut, SimpleOut->Handle); + ListPtr = ListPtr->pNext; + } +} +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: KeyboardLayoutMap +// +// Description: +// This function maps an EFI_KEY to a Unicode character, based on the current +// keyboard layout +// +// Input: +// IN AMI_EFI_KEY_DATA *KeyData - pointer to the key data returned by a device +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - key was mapped successfully +// EFI_NOT_FOUND - the key was not found in the keyboard layout +// EFI_INVALID_PARAMETER - KeyData is NULL +// +// Modified: +// AMI_EFI_KEY_DATA *KeyData - KeyData->Key.UnicodeChar is changed to match +// the character found in the keyboard layout +// +// Referrals: +// EFI_HII_KEYBOARD_LAYOUT* gKeyDescriptorList - Pointer to the current +// keyboard layout +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS KeyboardLayoutMap( + IN AMI_MULTI_LANG_SUPPORT_PROTOCOL *This, + IN OUT AMI_EFI_KEY_DATA *KeyData) +{ + EFI_STATUS Status; + EFI_KEY_DESCRIPTOR *KeyDescriptor; + + BOOLEAN AltState = FALSE; + BOOLEAN ShiftKeyState = FALSE; + BOOLEAN ShiftState = ShiftKeyState; + + static UINT16 ModifierIndex = 0xFFFF; + static CHAR16 ModifierUnicodeChar = 0x0000; + + UINT16 i = 0; + + if(gKeyDescriptorList== NULL) { + return EFI_NOT_FOUND; + } + + KeyDescriptor = (EFI_KEY_DESCRIPTOR*)&(gKeyDescriptorList->Descriptors); + + // check alt status (left alt or right alt) + if( ((KeyData->KeyState.KeyShiftState)&(RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED)) != 0 ) + AltState = TRUE; + + if( ((KeyData->KeyState.KeyShiftState)&(RIGHT_SHIFT_PRESSED|LEFT_SHIFT_PRESSED)) != 0 ) + ShiftKeyState = TRUE; + + Status = EFI_NOT_FOUND; + if ( (ModifierIndex != 0xFFFF) && (KeyDescriptor[ModifierIndex].Modifier == EFI_NS_KEY_MODIFIER) ) { + // Previous key had a modifier, we need to find out what to do + // for now, only handle EFI_NS_KEY_MODIFIER + for (i = ModifierIndex+1; KeyDescriptor[i].Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER && i < gKeyDescriptorList->DescriptorCount; i++) { + if(KeyDescriptor[i].Key == KeyData->EfiKey) { + if ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_STANDARD_SHIFT) != 0) + ShiftState = ShiftKeyState; + else + ShiftState = FALSE; + // account for cAPS lOCK, only applicable if the affected attribute is set + if (!AltState && ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_CAPS_LOCK) != 0) && ((KeyData->KeyState.KeyToggleState&CAPS_LOCK_ACTIVE) != 0)) + ShiftState = !ShiftState; + + if (AltState && ShiftState && (KeyDescriptor[i].ShiftedAltGrUnicode != 0x0000)) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedAltGrUnicode; + Status = EFI_SUCCESS; + } + else if (AltState && !ShiftState && (KeyDescriptor[i].AltGrUnicode != 0x0000)) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].AltGrUnicode; + Status = EFI_SUCCESS; + } + else if (!AltState && ShiftState && (KeyDescriptor[i].ShiftedUnicode != 0x0000)) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedUnicode; + Status = EFI_SUCCESS; + } + else if (!AltState && !ShiftState && (KeyDescriptor[i].Unicode != 0x0000)) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].Unicode; + Status = EFI_SUCCESS; + } + break; + } + } + + if (EFI_ERROR(Status)) + // No match found, just return the deadkey's character + KeyData->Key.UnicodeChar = ModifierUnicodeChar; + ModifierIndex = 0xFFFF; + ModifierUnicodeChar = 0x0000; + return EFI_SUCCESS; + } + + // Search the KeyDescriptorList for a matching key + for(i = 0; i < gKeyDescriptorList->DescriptorCount; i++) + { + if(KeyDescriptor[i].Key == KeyData->EfiKey || (KeyDescriptor[i].Key == 0xA5A5 && KeyData->PS2ScanCode == 0x73)) { + if ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_STANDARD_SHIFT) != 0) + ShiftState = ShiftKeyState; + else + ShiftState = FALSE; + // account for cAPS lOCK, only applicable if the affected attribute is set + if (!AltState && ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_CAPS_LOCK) != 0) && ((KeyData->KeyState.KeyToggleState&CAPS_LOCK_ACTIVE) != 0)) + ShiftState = !ShiftState; + + switch (KeyDescriptor[i].Modifier) { + case EFI_NULL_MODIFIER: + Status = EFI_SUCCESS; + if (AltState && ShiftState) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedAltGrUnicode; + } + else if (AltState && !ShiftState) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].AltGrUnicode; + } + else if (!AltState && ShiftState) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedUnicode; + } + else if (!AltState && !ShiftState) { + KeyData->Key.UnicodeChar = KeyDescriptor[i].Unicode; + } + break; + case EFI_NS_KEY_MODIFIER: + Status = EFI_SUCCESS; + if (AltState && ShiftState && (KeyDescriptor[i].ShiftedAltGrUnicode != 0x0000)) { + ModifierIndex = i; + ModifierUnicodeChar = KeyDescriptor[i].ShiftedAltGrUnicode; + KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character + } + else if (AltState && !ShiftState && (KeyDescriptor[i].AltGrUnicode != 0x0000)) { + ModifierIndex = i; + ModifierUnicodeChar = KeyDescriptor[i].AltGrUnicode; + KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character + } + else if (!AltState && ShiftState && (KeyDescriptor[i].ShiftedUnicode != 0x0000)) { + ModifierIndex = i; + ModifierUnicodeChar = KeyDescriptor[i].ShiftedUnicode; + KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character + } + else if (!AltState && !ShiftState && (KeyDescriptor[i].Unicode != 0x0000)) { + ModifierIndex = i; + ModifierUnicodeChar = KeyDescriptor[i].Unicode; + KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character + } + default: + case EFI_NS_KEY_DEPENDENCY_MODIFIER: + // skip deadkey-dependent modifiers and unknown modifiers + break; + } // switch (KeyDescriptor[i].Modifier) + + if (!EFI_ERROR(Status) && (KeyData->Key.UnicodeChar != 0x0000 || ModifierUnicodeChar != 0x0000)) + break; // successfully mapped a key, break for(...) loop + } + } + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/ConSplitter/ConSplit.h b/Core/CORE_DXE/ConSplitter/ConSplit.h new file mode 100644 index 0000000..f64cad5 --- /dev/null +++ b/Core/CORE_DXE/ConSplitter/ConSplit.h @@ -0,0 +1,553 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.h 4 8/02/13 4:27a Thomaschen $ +// +// $Revision: 4 $ +// +// $Date: 8/02/13 4:27a $ +//***************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.h $ +// +// 4 8/02/13 4:27a Thomaschen +// Add for EIP109384. +// [Files] ConSplit.c, ConSplit.h, In.c, CsmSimpleIn.c. +// +// 3 6/26/13 3:10a Thomaschen +// Remove EIP109384. +// +// 1 6/04/13 1:53a Thomaschen +// Fixed for EIP118202. +// +// 16 10/25/12 2:32a Deepthins +// [TAG] EIP99475 +// [Category] Improvement +// [Description] Multi language module Support in the console splitter +// [Files] ConSplit.c, ConSplit.h , In.c and AmiKeycode.h +// +// 15 8/02/12 12:14p Artems +// [TAG] EIP95607 +// [Category] Bug Fix +// [Symptom] Execute nsh script and redirect output to file, then exit +// from shell, setup screen will crash +// [RootCause] Console splitter maintains global pool of supported +// modes. +// It's getting adjusted every time new SimpleTextOut (STO) is installed +// If new STO doesn't support particular mode it is getting marked as +// unsupported in global pool +// However once this STO is uninstalled global pool isn't updated, so mode +// is still marked as unsupported, +// though system can support it +// [Solution] Added reinitilization of global pool of supported modes on +// STO uninstall event +// [Files] Consplit.h Consplit.c +// +// 14 8/12/11 12:17p Artems +// EIP 64107: Added changes for module to be compliant with UEFI +// specification v 2.3.1 +// +// 13 5/05/11 3:52p Artems +// Added multi-language keyboard support +// +// 12 6/23/10 3:02p Felixp +// SimplePointer splitter support is added. +// +// 11 7/07/09 3:35p Artems +// Added functions headers according to code standard +// +// 10 9/17/07 4:04p Olegi +// Added support for AMI_EFIKEYCODE_PROTOCOL and +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. +// +// 9 9/05/07 11:13a Felixp +// SimpleTextInEx support removed. It causes problems. Support will add +// again after Core labeling. +// +// 8 9/04/07 2:55p Olegi +// Added EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL support. +// +// 7 1/05/07 4:23p Artems +// +// 6 12/29/06 3:01p Felixp +// 1. Support for GraphicsOutput protocol added +// 2. Support for more then one text mode added +// +// 5 9/27/06 7:42p Felixp +// SetMode funciton of the ConsoleControl protocol is updated to restore +// default UGA mode when switching from grphics to text. +// +// 4 3/13/06 2:37a Felixp +// +// 3 12/12/05 9:32a Felixp +// Support for synchronization of console devices +// (now screen is restored after legacy OpROM execution). +// +// 2 11/07/05 10:37a Felixp +// LockStdIn function of ConsoleControl protocol implemented +// +// 1 1/28/05 1:16p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 1/07/05 11:57a Felixp +// +// 3 1/04/05 5:15p Robert +// Changed component name to be more consistent with the other drivers +// that have been developed +// +// 2 1/03/05 5:47p Robert +// Working beta version of the consplitter +// +// 1 12/30/04 9:47a Robert +// Initial check in +// +// +//***************************************************************************** +//<AMI_FHDR_START> +// +// Name: ConSplit.h +// +// Description: This file contains the structure and function prototypes needed +// for the Console Splitter driver +// +//<AMI_FHDR_END> +//***************************************************************************** + +#ifndef __CONSOLE_SPLITTER_H__ +#define __CONSOLE_SPLITTER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//-------------------------------------------------------------------------------- + +#include <EFI.h> +#include <Protocol\SimpleTextOut.h > +#include <Protocol\SimpleTextIn.h> +#include <Protocol\SimpleTextInEx.h> +#include <Protocol\amikeycode.h> +#include <Protocol\SimplePointer.h> +#include <Protocol\DriverBinding.h> +#include <Protocol\ComponentName2.h> +#include <AmiDxeLib.h> + +//-------------------------------------------------------------------------------- + +#pragma pack (1) + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CON_SPLIT_SIMPLE_POINTER +// +// Description: +// This structure represents Splitter Simple Pointer devices linked list. +// +// Fields: Name Type Description +//---------------------------------------------------------------------------- +// Link DLINK Linked list pointer +// SimplePointer EFI_SIMPLE_POINTER_PROTOCOL* Protocol pointer +// Handle EFI_HANDLE Device handle +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct _CON_SPLIT_SIMPLE_POINTER { + DLINK Link; //MUST BE THE FIRST FIELD + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + EFI_HANDLE Handle; +} CON_SPLIT_SIMPLE_POINTER; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CON_SPLIT_OUT +// +// Description: +// This structure represents Splitter ConOut devices linked list +// +// Fields: Name Type Description +//---------------------------------------------------------------------------- +// Link DLINK Linked list pointer +// SimpleOut EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* Protocol pointer +// Handle EFI_HANDLE Device handle +// +// Notes: +// +// Referrals: +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct _CON_SPLIT_OUT + { + DLINK Link; //MUST BE THE FIRST FIELD + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut; + EFI_HANDLE Handle; + } CON_SPLIT_OUT; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CON_SPLIT_IN_KEY_NOTIFY +// +// Description: +// +// Notes: +// +// Referrals: +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + DLINK Link; //MUST BE THE FIRST FIELD + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction; + DLIST NotifyHandleList; +} CON_SPLIT_IN_KEY_NOTIFY; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CON_SPLIT_IN_KEY_NOTIFY +// +// Description: +// +// Notes: +// +// Referrals: +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + DLINK Link; //MUST BE THE FIRST FIELD + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx; + EFI_HANDLE NotifyHandle; +} CON_SPLIT_IN_KEY_NOTIFY_HANDLE; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CON_SPLIT_IN +// +// Description: +// This structure represents Splitter ConIn devices linked list +// +// Fields: Name Type Description +//---------------------------------------------------------------------------- +// Link DLINK Linked list pointer +// SimpleIn EFI_SIMPLE_TEXT_INPUT_PROTOCOL* Protocol pointer +// SimpleInEx EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* Protocol pointer +// KeycodeInEx AMI_EFIKEYCODE_PROTOCOL* Protocol pointer +// Handle EFI_HANDLE Device handle +// +// Notes: +// +// Referrals: +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct _CON_SPLIT_IN + { + DLINK Link; //MUST BE THE FIRST FIELD + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx; + AMI_EFIKEYCODE_PROTOCOL *KeycodeInEx; + EFI_HANDLE Handle; + } CON_SPLIT_IN; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: CON_SPLIT +// +// Description: +// This structure represents Splitter devices structure +// +// Fields: Name Type Description +//---------------------------------------------------------------------------- +// Input CON_SPLIT_IN Input devices linked list +// Output CON_SPLIT_OUT Output devices linked list +// StdErr CON_SPLIT_OUT Error output devices linked list +// +// Notes: +// +// Referrals: +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct _CON_SPLIT + { + CON_SPLIT_IN Input; + CON_SPLIT_OUT Output; + CON_SPLIT_OUT StdErr; + } CON_SPLIT; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: SUPPORT_RES +// +// Description: +// This structure represents Splitter supported resolutions database +// +// Fields: Name Type Description +//---------------------------------------------------------------------------- +// Columns INT32 Max number of text columns +// Rows INT32 Max number of text rows +// AllDevices BOOLEAN Flag if all devices support given resolution +// +// Notes: +// +// Referrals: +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct __SUPPORT_RES + { + INT32 Columns; + INT32 Rows; + BOOLEAN AllDevices; + } SUPPORT_RES; + +#pragma pack() + +//----------------------------------------------------------------------------------- + +SUPPORT_RES *SupportedModes; + +//virtual splitter output buffer +CHAR16 *ScreenBuffer; +CHAR16 *EndOfTheScreen; +INT32 *AttributeBuffer; +INT32 Columns; + +extern SIMPLE_TEXT_OUTPUT_MODE MasterMode; +extern EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mCSOutProtocol; +extern EFI_SIMPLE_TEXT_INPUT_PROTOCOL mCSSimpleInProtocol; +extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL mCSSimpleInExProtocol; +extern AMI_EFIKEYCODE_PROTOCOL mCSKeycodeInProtocol; +extern DLIST ConInList; +extern DLIST ConOutList; +extern DLIST ConPointerList; +extern DLIST ConInKeyNotifyList; +extern BOOLEAN StdInLocked; +extern EFI_SIMPLE_POINTER_PROTOCOL mCSSimplePointerProtocol; + +//----------------------------------------------------------------------------------- + +EFI_STATUS ConSplitterSimplePointerReset( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification ); + +EFI_STATUS ConSplitterSimplePointerGetState( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State ); + +VOID ConSplitterSimplePointerWaitForInput( + IN EFI_EVENT Event, + IN VOID *Context ); + +EFI_STATUS CSSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); + +EFI_STATUS CSStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS CSStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS CSReset( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS CSOutputString( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +EFI_STATUS CSTestString( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +EFI_STATUS CSQueryMode( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNum, + OUT UINTN *Col, + OUT UINTN *Row + ); + +EFI_STATUS CSSetMode( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNum + ); + +EFI_STATUS CSSetAttribute( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +EFI_STATUS CSClearScreen( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +EFI_STATUS CSSetCursorPosition( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + +EFI_STATUS CSEnableCursor( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +EFI_STATUS CSInReset( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN EV + ); + +EFI_STATUS CSReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +VOID CSWaitForKey( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_STATUS CSInResetEx( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN EV + ); + +EFI_STATUS CSReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ); + +EFI_STATUS +CSReadEfiKey ( + IN AMI_EFIKEYCODE_PROTOCOL *This, + OUT AMI_EFI_KEY_DATA *KeyData + ); + +EFI_STATUS CSInSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +EFI_STATUS CSInRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +); + +EFI_STATUS CSInUnRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + +VOID RestoreTheScreen( + IN EFI_HANDLE ControllerHandle, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut + ); + +VOID SaveTheScreen( + IN EFI_HANDLE ControllerHandle, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut + ); + +EFI_STATUS MemClearScreen( + VOID + ); + +VOID SaveUgaMode( + IN EFI_HANDLE ControllerHandle + ); + +VOID RestoreUgaMode( + IN EFI_HANDLE ControllerHandle + ); + +EFI_STATUS InitModesTable( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN EFI_HANDLE Handle + ); + +VOID UpdateModesTable( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN EFI_HANDLE Handle + ); + +EFI_STATUS IsModeSupported( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNum, + OUT INT32 *DeviceModeNumber + ); + +EFI_STATUS ResizeSplitterBuffer( + IN INT32 ModeNum + ); + +VOID UpdateMasterMode( + IN SIMPLE_TEXT_OUTPUT_MODE *Mode + ); + +EFI_STATUS CSInKeyboardLayoutMap( + IN OUT AMI_EFI_KEY_DATA *KeyData + ); + +VOID AdjustSupportedModes( + VOID + ); + +EFI_STATUS KeyboardLayoutMap( + IN AMI_MULTI_LANG_SUPPORT_PROTOCOL *This, + IN OUT AMI_EFI_KEY_DATA *KeyData + ); +#ifdef __cplusplus +} +#endif +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_DXE/ConSplitter/ConSplitter.cif b/Core/CORE_DXE/ConSplitter/ConSplitter.cif new file mode 100644 index 0000000..ff3fc94 --- /dev/null +++ b/Core/CORE_DXE/ConSplitter/ConSplitter.cif @@ -0,0 +1,12 @@ +<component> + name = "ConSplitter" + category = ModulePart + LocalRoot = "Core\CORE_DXE\ConSplitter\" + RefName = "ConSplitter" +[files] +"\ConSplitter.sdl" +"\ConSplit.c" +"\ConSplit.h" +"\Out.c" +"\In.c" +<endComponent> diff --git a/Core/CORE_DXE/ConSplitter/ConSplitter.sdl b/Core/CORE_DXE/ConSplitter/ConSplitter.sdl new file mode 100644 index 0000000..730b34e --- /dev/null +++ b/Core/CORE_DXE/ConSplitter/ConSplitter.sdl @@ -0,0 +1,26 @@ +TOKEN + Name = "PAUSEKEY_SUPPORT" + Value = "0" + Help = "Pause key support. ON - Pause key causes pause during POST. OFF - Pause key ignored." + TokenType = Boolean + TargetH = Yes +End + +TOKEN + Name = "REPORT_NO_CON_OUT_ERROR" + Value = "1" + TokenType = Boolean + TargetH = Yes +End + +TOKEN + Name = "REPORT_NO_CON_IN_ERROR" + Value = "1" + TokenType = Boolean + TargetH = Yes +End + +PATH + Name = "CONSOLE_SPLITTER_DIR" +End + diff --git a/Core/CORE_DXE/ConSplitter/In.c b/Core/CORE_DXE/ConSplitter/In.c new file mode 100644 index 0000000..9d8d561 --- /dev/null +++ b/Core/CORE_DXE/ConSplitter/In.c @@ -0,0 +1,1159 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/In.c 5 7/08/15 4:32a Chienhsieh $ +// +// $Revision: 5 $ +// +// $Date: 7/08/15 4:32a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/In.c $ +// +// 5 7/08/15 4:32a Chienhsieh +// Update for eip217417. +// +// 4 8/02/13 4:26a Thomaschen +// Add for EIP109384. +// [Files] ConSplit.c, ConSplit.h, In.c, CsmSimpleIn.c. +// +// 3 6/26/13 3:11a Thomaschen +// Remove EIP109384. +// +// 1 6/04/13 1:52a Thomaschen +// Fixed for EIP118202. +// +// 32 10/25/12 2:33a Deepthins +// [TAG] EIP99475 +// [Category] Improvement +// [Description] Multi language module Support in the console splitter +// +// [Files] ConSplit.c, ConSplit.h , In.c and AmiKeycode.h +// +// 31 7/20/12 10:38a Artems +// [TAG] EIP93929 +// [Description] Implement support to initialize the Keyboard in first +// call of readkeystoke in fast boot case +// [Files] In.c +// +// 30 4/11/12 5:35p Artems +// [TAG] EIPN/A +// [Category] Bug Fix +// [Symptom] Function SetState was not broadcasted to third party +// drivers +// [RootCause] Splitter uses AMI proprietary protocol to broadcast +// SetState function +// which is not installed by third party drivers +// [Solution] Modified splitter to broadcast SetState function via +// SimpleTextInEx protocol +// [Files] in.c +// +// 29 3/21/12 12:53p Artems +// EIP 83358: Fixed bug in SimplePointerGetState function, where +// EFI_SUCCESS was lost if ohter device returns DEVICE_ERROR +// +// 28 9/22/11 6:29a Rameshr +// [TAG] EIP63054 +// [Category] New Feature +// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key +// press +// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c, +// Efiusbkb.c, efiusbkb.h +// +// 27 7/21/11 3:41p Aaronp +// // [TAG] EIP65187 +// // [Category] Bug Fix +// // [Severity] Minor +// // [Symptom] unicode character was not returned when english selected +// // and alt key pressed +// // [RootCause] The EFI_HII_KEYBOARD_LAYOUT table provides the +// AltGraphic +// // and Shifted AltGraphic unicode definitions for key combinations, and +// // there are NULL values for undefined key combinations. +// // [Solution] Changed how the EFI_HII_KEYBOARD_LAYOUT table is +// consumed +// // so that the current unicode character in the AMI_EFI_KEY_DATA +// structure +// // will not be overwritten when the EFI_HII_KEYBOARD_LAYOUT has a NULL +// // value in the matching table entry. +// // [Files] In.c +// +// 25 5/05/11 4:53p Artems +// Removed unnecessary checks +// +// 24 5/05/11 3:54p Artems +// Added multi-language keyboard support +// +// 23 8/10/10 2:29p Vyacheslava +// Initialized default value of Status in the +// ConSplitterSimplePointerReset function. +// +// 22 6/23/10 3:02p Felixp +// SimplePointer splitter support is added. +// +// 21 1/18/10 3:40a Rameshr +// NumLock,Capslock,Scroll Lock LED's synced properly between Keyboard +// connect and disconnect. +// EIP 27917 +// +// 20 10/09/09 12:15p Felixp +// SetState function is updated to process all the physical devices +// despite the errors returned by some of them. +// +// 19 8/13/09 3:04p Rameshr +// When item "num-lock status" set off, Num-lock will keep open until in +// DOS. +// EIP:21757 +// +// 18 7/07/09 3:35p Artems +// Added functions headers according to code standard +// +// 17 4/30/09 5:45p Felixp +// Minor improvements on the pause key implementation. +// +// 16 3/30/09 10:24a Pats +// Issue: EIP 19547 - Pause key support needed in Aptio +// Solution: Function CsReadEfiKey modified to enter pause loop when pause +// key detected. Requires mod in Ps2Kbd.c and efiusbkb.c. +// +// 15 1/23/09 9:55a Rameshr +// Symptom:SCT failure in ReadKeystrokeEx function. +// Solution: Validated the Input parameters Keydata for the +// ReadKeystrokeEx Function. +// Eip: 19039 +// +// 14 11/17/08 10:22a Rameshraju +// Problem:SCT failure on RegisterKeyNotify, SetState and +// UnregisterKeyNotify. +// Fix : Validated the input parameters for RegisterKeyNotify, SetState +// and UnregisterKeyNotify. +// EIP:17578 +// +// 13 10/08/08 4:27p Olegi +// Implemented the Register/Unregister key notofocation function in +// SimpletextinEx protocol. +// +// 12 3/17/08 4:49p Rameshraju +// ReadEfiKey doesnt not return correct key value randomly. +// +// 11 1/31/08 12:00p Olegi +// Numlock bootup state made setup driven. +// +// 10 11/16/07 4:05p Olegi +// Modifications in CSReadKeyStroke function. +// +// 9 10/23/07 4:14p Olegi +// Modifications in CSInSetState that allow the sync between the Input +// Devices' LEDs. +// +// 8 10/16/07 10:47a Olegi +// Modification in CSReadEfiKey(). +// +// 7 9/17/07 4:04p Olegi +// Added support for AMI_EFIKEYCODE_PROTOCOL and +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. +// +// 6 9/05/07 11:13a Felixp +// SimpleTextInEx support removed. It causes problems. Support will add +// again after Core labeling. +// +// 3 3/13/06 2:37a Felixp +// +// 2 11/07/05 10:37a Felixp +// LockStdIn function of ConsoleControl protocol implemented +// +// 1 1/28/05 1:16p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 1/07/05 11:57a Felixp +// +// 2 1/03/05 5:47p Robert +// Working beta version of the consplitter +// +// 1 12/30/04 9:47a Robert +// Initial check in +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Out.c +// +// Description: File contains the Simple Text Output functionality for the +// Console Splitter Driver +// +//<AMI_FHDR_END> +//********************************************************************** + +//---------------------------------------------------------------------------- + +#include "ConSplit.h" +#include "token.h" +#include <Protocol/SimplePointer.h> + +//---------------------------------------------------------------------------- +extern EFI_HII_KEYBOARD_LAYOUT *gKeyDescriptorList; +extern EFI_KEY_TOGGLE_STATE mCSToggleState; +EFI_SIMPLE_POINTER_MODE gSimplePointerMode = { + 0x10000, + 0x10000, + 0x10000, + FALSE, + FALSE +}; + +VOID ConnectInputDevices( + VOID +); + +//---------------------------------------------------------------------------- + +EFI_SIMPLE_TEXT_INPUT_PROTOCOL mCSSimpleInProtocol = { + CSInReset, + CSReadKeyStroke, + NULL + } ; + +EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL mCSSimpleInExProtocol = { + CSInResetEx, + CSReadKeyStrokeEx, + NULL, + CSInSetState, + CSInRegisterKeyNotify, + CSInUnRegisterKeyNotify + } ; + +AMI_EFIKEYCODE_PROTOCOL mCSKeycodeInProtocol = { + CSInResetEx, + CSReadEfiKey, + NULL, + CSInSetState, + CSInRegisterKeyNotify, + CSInUnRegisterKeyNotify + } ; + +EFI_SIMPLE_POINTER_PROTOCOL mCSSimplePointerProtocol = { + ConSplitterSimplePointerReset, + ConSplitterSimplePointerGetState, + ConSplitterSimplePointerWaitForInput, + &gSimplePointerMode +}; + +//---------------------------------------------------------------------------- + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConSplitterSimplePointerReset +// +// Description: Resets the pointer device hardware. +// +// Input: +// *This - pointer to protocol instance. +// ExtendedVerification - Driver may perform diagnostics on reset. +// +// Output: +// EFI_SUCCESS - device was reset successfully +// EFI_ERROR - some of devices returned error +// +//---------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS TestStatus; + CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL; + + if (StdInLocked) + return EFI_ACCESS_DENIED; + + if (ConPointerList.pHead == NULL) + return EFI_DEVICE_ERROR; + + ConSimplePointer = OUTTER(ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER); + + // we need to loop through all the registered simple pointer devices + // and call each of their Reset function + while (ConSimplePointer != NULL) { + TestStatus = ConSimplePointer->SimplePointer->Reset(ConSimplePointer->SimplePointer, ExtendedVerification); + ConSimplePointer = OUTTER( ConSimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER ); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + return Status; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConSplitterSimplePointerGetState +// +// Description: Retrieves the current state of a pointer device. +// 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 +// +// Input: +// This - Protocol instance pointer. +// State - A pointer to the state information on the pointer device. +// +// Output: +// 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. +// +//---------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS ConSplitterSimplePointerGetState( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State ) +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_STATE CurrentState; + CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL; + BOOLEAN EfiSuccessDetected = FALSE; + BOOLEAN EfiDeviceErrorDetected = FALSE; + BOOLEAN EfiNotReadyDetected = FALSE; + + if (StdInLocked) + return EFI_ACCESS_DENIED; + + if (ConPointerList.pHead == NULL) + return EFI_DEVICE_ERROR; + + ConSimplePointer = OUTTER( ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER ); + + State->RelativeMovementX = 0; + State->RelativeMovementY = 0; + State->RelativeMovementZ = 0; + State->LeftButton = FALSE; + State->RightButton = FALSE; + + // we need to loop through all the registered simple pointer devices + while (ConSimplePointer != NULL) { + + Status = ConSimplePointer->SimplePointer->GetState(ConSimplePointer->SimplePointer, &CurrentState); + + if (!EFI_ERROR(Status)) { + + EfiSuccessDetected = TRUE; + + if (CurrentState.LeftButton) + State->LeftButton = TRUE; + + if (CurrentState.RightButton) + State->RightButton = TRUE; + + if ( CurrentState.RelativeMovementX != 0 && ConSimplePointer->SimplePointer->Mode->ResolutionX != 0 ) + State->RelativeMovementX += + (CurrentState.RelativeMovementX * (INT32)gSimplePointerMode.ResolutionX) / + (INT32)ConSimplePointer->SimplePointer->Mode->ResolutionX; + + if ( CurrentState.RelativeMovementY != 0 && ConSimplePointer->SimplePointer->Mode->ResolutionY != 0 ) + State->RelativeMovementY += + (CurrentState.RelativeMovementY * (INT32)gSimplePointerMode.ResolutionY) / + (INT32)ConSimplePointer->SimplePointer->Mode->ResolutionY; + + if ( CurrentState.RelativeMovementZ != 0 && ConSimplePointer->SimplePointer->Mode->ResolutionZ != 0 ) + State->RelativeMovementZ += + (CurrentState.RelativeMovementZ * (INT32)gSimplePointerMode.ResolutionZ) / + (INT32)ConSimplePointer->SimplePointer->Mode->ResolutionZ; + + } else if (Status == EFI_DEVICE_ERROR) { + EfiDeviceErrorDetected = TRUE; + } else { + EfiNotReadyDetected = TRUE; + } + + ConSimplePointer = OUTTER( ConSimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER ); + } + + return (EfiSuccessDetected) ? EFI_SUCCESS : (EfiDeviceErrorDetected) ? EFI_DEVICE_ERROR : EFI_NOT_READY; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ConSplitterSimplePointerWaitForInput +// +// Description: This is callback function for WaitForInputEvent to use with +// WaitForEvent() to wait for input from the pointer device. +// +// Input: +// Event - The Event assoicated with callback. +// Context - Context registered when Event was created. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID ConSplitterSimplePointerWaitForInput( + IN EFI_EVENT Event, + IN VOID *Context ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS TestStatus; + CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL; + + if (StdInLocked) + return; + + if (ConPointerList.pHead == NULL) + return; + + ConSimplePointer = OUTTER( ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER ); + + // loop through simple pointer events and check their events + // if one event has been signaled, signal my event and exit. + // we need to loop through all the registered simple pointer devices + while (ConSimplePointer != NULL) { + TestStatus = pBS->CheckEvent(ConSimplePointer->SimplePointer->WaitForInput); + ConSimplePointer = OUTTER( ConSimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER ); + + if (!EFI_ERROR(TestStatus)) + pBS->SignalEvent(Event); + } + + return; +} + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSInReset +// +// Description: +// This function resets the input device hardware. This routine is a part +// of SimpleTextIn protocol implementation. +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This - pointer to protocol instance +// IN BOOLEAN EV - flag if Extended verification has to be performed +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - device was reset successfully +// EFI_ERROR - some of devices returned error +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSInReset( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN EV +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_IN *SimpleIn; + + if (StdInLocked) return EFI_ACCESS_DENIED; + + if (ConInList.pHead == NULL) + return EFI_SUCCESS; + + SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN); + + // we need to loop through all the registered simple text out devices + // and call each of their Reset function + while ( SimpleIn != NULL) + { + TestStatus = SimpleIn->SimpleIn->Reset(SimpleIn->SimpleIn, EV); + SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + return Status; + +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSReadKeyStroke +// +// Description: +// This function reads the next keystroke from the input device. This +// routine is a part of SimpleTextIn protocol implementation +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This - pointer to protocol instance +// OUT EFI_INPUT_KEY *Key - key pressed information +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - Keystroke data successfully retrieved +// EFI_NOT_READY - There was no keystroke data available +// EFI_DEVICE_ERROR - The keystroke information was not returned +// due to hardware error +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSReadKeyStroke( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key +) +{ + EFI_STATUS Status; + AMI_EFI_KEY_DATA EfiKeyData; + + Status = CSReadEfiKey ( (AMI_EFIKEYCODE_PROTOCOL*) This, &EfiKeyData ); + if (Status == EFI_SUCCESS) { + // + // Check for the Partial Key. If found, SimpleTextIn ReadKeyStroke + // Should not return that Key has bee found. + // + if(EfiKeyData.Key.ScanCode == 00 && EfiKeyData.Key.UnicodeChar == 0 && + (EfiKeyData.KeyState.KeyToggleState & KEY_STATE_EXPOSED )) { + return EFI_NOT_READY; + } + *Key = EfiKeyData.Key; + return EFI_SUCCESS; + } + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSWaitForKey +// +// Description: +// This function is a callback for the EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event +// Checks whether the new key is available and if so - signals the event +// +// Input: +// IN EFI_EVENT Event - event to signal +// IN VOID *Context - pointer to event specific context +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID CSWaitForKey( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_IN *SimpleIn; + + if (StdInLocked) return ; + if (ConInList.pHead == NULL) return; + +// loop through simple in events and check their events +// if one event has been signaled, signal my event and exit + + SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN); + + // we need to loop through all the registered simple text out devices + // and call each of their Reset function + while ( SimpleIn != NULL) + { + TestStatus = pBS->CheckEvent(SimpleIn->SimpleIn->WaitForKey); + SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN); + + if (!EFI_ERROR(TestStatus)) + pBS->SignalEvent (Event); + } + + return; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSInResetEx +// +// Description: +// This function resets the input device hardware. This routine is a part +// of SimpleTextInEx protocol implementation +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance +// IN BOOLEAN ExtendedVerification - flag if Extended verification has to be performed +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - device was reset successfully +// EFI_ERROR - some of devices returned error +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSInResetEx( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification ) +{ + return CSInReset(0, ExtendedVerification); +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSReadKeyStrokeEx +// +// Description: +// This function reads the next keystroke from the input device. This +// routine is a part of SimpleTextInEx protocol implementation +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance +// OUT EFI_KEY_DATA *KeyData - key pressed information +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - Keystroke data successfully retrieved +// EFI_NOT_READY - There was no keystroke data available +// EFI_DEVICE_ERROR - The keystroke information was not returned +// due to hardware error +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +) +{ + EFI_STATUS Status; + AMI_EFI_KEY_DATA EfiKeyData; + + if(KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + Status = CSReadEfiKey ( (AMI_EFIKEYCODE_PROTOCOL*) This, &EfiKeyData ); + if (Status == EFI_SUCCESS) { + KeyData->Key = EfiKeyData.Key; + KeyData->KeyState = EfiKeyData.KeyState; + return EFI_SUCCESS; + } + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSReadEfiKey +// +// Description: +// This function reads the next keystroke from the input device. This +// routine is a part of AmiKeyCode protocol implementation +// +// Input: +// IN AMI_EFIKEYCODE_PROTOCOL *This - pointer to protocol instance +// OUT AMI_EFI_KEY_DATA *KeyData - key pressed information +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - Keystroke data successfully retrieved +// EFI_NOT_READY - There was no keystroke data available +// EFI_DEVICE_ERROR - The keystroke information was not returned +// due to hardware error +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSReadEfiKey ( + IN AMI_EFIKEYCODE_PROTOCOL *This, + OUT AMI_EFI_KEY_DATA *KeyData +) +{ + AMI_EFI_KEY_DATA TempKey; + EFI_STATUS Status = EFI_NOT_READY; + CON_SPLIT_IN *SimpleIn; + + if (StdInLocked) return EFI_ACCESS_DENIED; + + ConnectInputDevices(); + + if (ConInList.pHead == NULL) return EFI_NOT_READY; + + SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN); + + pBS->SetMem(KeyData, sizeof(AMI_EFI_KEY_DATA), 0); + + // we need to loop through all the registered EfiKey, SimpleInEx and + // SimpleIn devices and call each of their ReadKeyStroke function + while (SimpleIn != NULL) + { + if (SimpleIn->KeycodeInEx) { + Status = SimpleIn->KeycodeInEx->ReadEfikey(SimpleIn->KeycodeInEx, &TempKey); + } else if(SimpleIn->SimpleInEx != NULL) { + Status = SimpleIn->SimpleInEx->ReadKeyStrokeEx( + SimpleIn->SimpleInEx, (EFI_KEY_DATA*)&TempKey); + } else if(SimpleIn->SimpleIn != NULL) { + Status = SimpleIn->SimpleIn->ReadKeyStroke( + SimpleIn->SimpleIn, (EFI_INPUT_KEY*)&TempKey); + } + + // Check for the Toggle State change + if (!EFI_ERROR(Status) && (TempKey.KeyState.KeyToggleState & TOGGLE_STATE_VALID)) { + if ((TempKey.KeyState.KeyToggleState & ~KEY_STATE_EXPOSED ) != mCSToggleState) { + mCSToggleState = (TempKey.KeyState.KeyToggleState & ~KEY_STATE_EXPOSED); + CSInSetState ( (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*) This, + &mCSToggleState ); + } + } + + if (!EFI_ERROR(Status)) { + *KeyData = TempKey; + break; + } + + SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN); + } +#if PAUSEKEY_SUPPORT + if (!EFI_ERROR(Status) && TempKey.EfiKey == EfiKeyPause) { + while(TRUE) { + Status = CSReadEfiKey ( This, &TempKey ); + if ((!EFI_ERROR(Status)) && (TempKey.EfiKey != EfiKeyPause) && (TempKey.EfiKey != 0x55)) { + break; + } + } + *KeyData = TempKey; + } +#endif + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSInSetState +// +// Description: +// This function sets certain state for input device +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance +// IN EFI_KEY_TOGGLE_STATE *KeyToggleState - pointer to state to set +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - Keystroke data successfully retrieved +// EFI_UNSUPPORTED - Given state not supported +// EFI_INVALID_PARAMETER - KeyToggleState is NULL +// EFI_DEVICE_ERROR - input device not found +// EFI_ACCESS_DENIED - input device is busy +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSInSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +) +{ + EFI_STATUS Status = EFI_SUCCESS; + CON_SPLIT_IN *SimpleIn; + + if (StdInLocked) return EFI_ACCESS_DENIED; + + if (ConInList.pHead == NULL) + return EFI_UNSUPPORTED; + + if(KeyToggleState == NULL ) { + return EFI_INVALID_PARAMETER; + } + + if (!(*KeyToggleState & TOGGLE_STATE_VALID) || + ((*KeyToggleState & (~(TOGGLE_STATE_VALID | KEY_STATE_EXPOSED | + SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE)))) ) { + return EFI_UNSUPPORTED; + } + + mCSToggleState = *KeyToggleState; // Update global toggle state + + SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN); + + // we need to loop through all the registered KeycodeInEx devices + // and call each of their SetState function + while ( SimpleIn != NULL ) + { + if (SimpleIn->SimpleInEx) { + SimpleIn->SimpleInEx->SetState(SimpleIn->SimpleInEx, KeyToggleState); + } + SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN); + } + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSInKeyNotificationFunction +// +// Description: +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS +CSInKeyNotificationFunction( + IN EFI_KEY_DATA *KeyData +) +{ + EFI_STATUS Status = EFI_SUCCESS; + DLINK *ListPtr; + UINTN Index = 0; + UINTN Count = 0; + EFI_KEY_NOTIFY_FUNCTION *NotifyFunctionList = NULL; + CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL; + + if (StdInLocked) return EFI_ACCESS_DENIED; + + if (ConInKeyNotifyList.pHead == NULL) return EFI_DEVICE_ERROR; + + Status = pBS->AllocatePool(EfiBootServicesData, + ConInKeyNotifyList.Size * sizeof(EFI_KEY_NOTIFY_FUNCTION), + (VOID**)&NotifyFunctionList); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) { + CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY); + + if (!MemCmp(&(CsInKeyNotify->KeyData), KeyData, sizeof(CsInKeyNotify->KeyData))) { + NotifyFunctionList[Count++] = CsInKeyNotify->KeyNotificationFunction; + } + } + + for (Index = 0; Index < Count; Index++) { + NotifyFunctionList[Index](&(CsInKeyNotify->KeyData)); + } + + pBS->FreePool(NotifyFunctionList); + + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSInRegisterKeyNotify +// +// Description: +// This function registers a notification function for a particular +// keystroke of the input device +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance +// IN EFI_KEY_DATA *KeyData - key value +// IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction - notification function +// OUT EFI_HANDLE *NotifyHandle - returned registered handle +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - notification function registered successfully +// EFI_INVALID_PARAMETER - KeyData/KeyNotificationFunction/NotifyHandle is NULL +// EFI_DEVICE_ERROR - input device not found +// EFI_ACCESS_DENIED - input device is busy +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSInRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +) +{ + EFI_STATUS Status = EFI_SUCCESS; + DLINK *ListPtr = NULL; + CON_SPLIT_IN *ConIn = NULL; + CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL; + CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL; + + if (StdInLocked) return EFI_ACCESS_DENIED; + + if(KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL ) { + return EFI_INVALID_PARAMETER; + } + + for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) { + CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY); + + if ((!MemCmp(&CsInKeyNotify->KeyData, KeyData, sizeof(CsInKeyNotify->KeyData))) && + (CsInKeyNotify->KeyNotificationFunction == KeyNotificationFunction)) { + *NotifyHandle = (EFI_HANDLE)&(CsInKeyNotify->Link); + return EFI_SUCCESS; + } + + } + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(CON_SPLIT_IN_KEY_NOTIFY), &CsInKeyNotify); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + MemCpy(&(CsInKeyNotify->KeyData), KeyData, sizeof(CsInKeyNotify->KeyData)); + CsInKeyNotify->KeyNotificationFunction = KeyNotificationFunction; + DListAdd(&ConInKeyNotifyList, &(CsInKeyNotify->Link)); + DListInit(&(CsInKeyNotify->NotifyHandleList)); + // we need to loop through all the registered SimpleInEx + // and call each of their ReadKeyStroke function + for (ListPtr = ConInList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) { + ConIn = OUTTER(ListPtr, Link, CON_SPLIT_IN); + + if (ConIn->SimpleInEx == NULL) { + continue; + } + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(CON_SPLIT_IN_KEY_NOTIFY_HANDLE), &CsInNotifyHandle); + if (EFI_ERROR(Status)) { + break; + } + + CsInNotifyHandle->SimpleInEx = ConIn->SimpleInEx; + DListAdd(&(CsInKeyNotify->NotifyHandleList), &(CsInNotifyHandle->Link)); + + Status = ConIn->SimpleInEx->RegisterKeyNotify(ConIn->SimpleInEx, + KeyData, CSInKeyNotificationFunction, &(CsInNotifyHandle->NotifyHandle)); + if (EFI_ERROR(Status)) { + break; + } + } + + if (EFI_ERROR(Status)) { + for (ListPtr = CsInKeyNotify->NotifyHandleList.pHead; + ListPtr != NULL; ListPtr = ListPtr->pNext) { + CsInNotifyHandle = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY_HANDLE); + + CsInNotifyHandle->SimpleInEx->UnregisterKeyNotify( + CsInNotifyHandle->SimpleInEx, CsInNotifyHandle->NotifyHandle); + + DListDelete(&(CsInKeyNotify->NotifyHandleList), ListPtr); + pBS->FreePool(CsInNotifyHandle); + } + + pBS->FreePool(CsInKeyNotify); + + return Status; + } + + *NotifyHandle = (EFI_HANDLE)&(CsInKeyNotify->Link); + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSInUnRegisterKeyNotify +// +// Description: +// This function unregisters a notification function with given handle +// +// Input: +// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance +// IN EFI_HANDLE NotificationHandle - handle to unregister +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - notification function unregistered successfully +// EFI_INVALID_PARAMETER - NotificationHandle is NULL +// EFI_DEVICE_ERROR - input device not found +// EFI_ACCESS_DENIED - input device is busy +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSInUnRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +) +{ + EFI_STATUS Status = EFI_SUCCESS; + DLINK *ListPtr = NULL; + DLINK *HandleLink = NULL; + CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL; + CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL; + + if (StdInLocked) return EFI_ACCESS_DENIED; + + if (NotificationHandle == NULL ) { + return EFI_INVALID_PARAMETER; + } + + for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) { + CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY); + + if (NotificationHandle == (EFI_HANDLE)&(CsInKeyNotify->Link)) { + DListDelete(&ConInKeyNotifyList, ListPtr); + break; + } + } + + if (ListPtr == NULL) { + return EFI_INVALID_PARAMETER; + } + + // we need to loop through all the registered SimpleInEx + // and call each of their ReadKeyStroke function + + for (HandleLink = CsInKeyNotify->NotifyHandleList.pHead; HandleLink != NULL; + HandleLink = HandleLink->pNext) { + CsInNotifyHandle = OUTTER(HandleLink, Link, CON_SPLIT_IN_KEY_NOTIFY_HANDLE); + + Status = CsInNotifyHandle->SimpleInEx->UnregisterKeyNotify( + CsInNotifyHandle->SimpleInEx, CsInNotifyHandle->NotifyHandle); + + DListDelete(&(CsInKeyNotify->NotifyHandleList), HandleLink); + Status = pBS->FreePool(CsInNotifyHandle); + } + + Status = pBS->FreePool(CsInKeyNotify); + + return Status; +} + + +#if FAST_BOOT_SUPPORT +#include <Protocol/FastBootProtocol.h> +static AMI_FAST_BOOT_PROTOCOL *AmiFbProtocol = NULL; + +VOID ConnectInputDevices( + VOID +) +{ + EFI_STATUS Status; + static Executed = FALSE; + + if(Executed) + return; + + if(AmiFbProtocol == NULL) { + Status = pBS->LocateProtocol(&AmiFastBootProtocolGuid, NULL, &AmiFbProtocol); + if(EFI_ERROR(Status)) { + AmiFbProtocol = NULL; + return; + } + } + + if(AmiFbProtocol->IsRuntime()) { + AmiFbProtocol->ConnectInputDevices(); + Executed = TRUE; + } +} + +#else //#if FAST_BOOT_SUPPORT +VOID ConnectInputDevices( + VOID +){return;} +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/ConSplitter/Out.c b/Core/CORE_DXE/ConSplitter/Out.c new file mode 100644 index 0000000..d11ebc8 --- /dev/null +++ b/Core/CORE_DXE/ConSplitter/Out.c @@ -0,0 +1,1323 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/ConSplitter/Out.c 19 7/06/12 11:31a Artems $ +// +// $Revision: 19 $ +// +// $Date: 7/06/12 11:31a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/ConSplitter/Out.c $ +// +// 19 7/06/12 11:31a Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] Support for monitor native resolution +// [Files] Gc.c, Consplit.c, Out.c, Core_Dxe.sdl +// +// 18 10/27/11 12:50p Felixp +// [TAG] EIP65867 +// [Category] Improvement +// [Description] Screen content that was printed in a timer callback was +// not getting restored after OpROM +// execution. +// The previous check-in didn't address all the issue. +// This is a more sophisticated solution. +// +// 17 8/03/11 3:27p Felixp +// [TAG] EIP65867 +// [Category] Improvement +// [Description] Screen content that was printed in a timer callback was +// not getting restored after OpROM execution. +// RestoreTheScreen function is updated. +// +// 16 10/09/09 6:15p Felixp +// UGA constant replaced with GOP constant (UEFI 2.1 compatibility) +// +// 15 7/07/09 3:35p Artems +// Added functions headers according to code standard +// +// 14 6/16/09 5:49p Artems +// EIP 21415 Fixed error with CursorVisible variable +// +// 11 10/23/07 10:13a Felixp +// Bug fix: System was hanging in SCT during Simple Text Output protocol +// testing +// when "Enable Screen Ouput" SCT option was enabled. +// +// 10 7/20/07 12:16p Felixp +// Clear the screen when switching from graphics screen to text screen +// without mode switching +// +// 9 1/05/07 6:01p Artems +// +// 8 12/29/06 3:01p Felixp +// 1. Support for GraphicsOutput protocol added +// 2. Support for more then one text mode added +// +// 7 9/27/06 7:42p Felixp +// SetMode funciton of the ConsoleControl protocol is updated to restore +// default UGA mode when switching from grphics to text. +// +// 6 3/13/06 2:37a Felixp +// +// 5 12/12/05 8:36p Felixp +// RestoreTheScreen update: Restore Cursor Status +// +// 4 12/12/05 9:32a Felixp +// Support for synchronization of console devices +// (now screen is restored after legacy OpROM execution). +// +// 3 7/21/05 5:12p Robert +// +// 2 1/31/05 11:31a Robert +// +// 1 1/28/05 1:16p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 1/07/05 11:57a Felixp +// +// 2 1/03/05 5:47p Robert +// Working beta version of the consplitter +// +// 1 12/30/04 9:47a Robert +// Initial check in +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Out.c +// +// Description: File contains the Simple Text Output functionality for the +// Console Splitter Driver +// +//<AMI_FHDR_END> +//********************************************************************** + +//---------------------------------------------------------------------------- + +#include "ConSplit.h" +#include <Protocol/GraphicsOutput.h> + +//---------------------------------------------------------------------------- + +#define DefaultAttribute 0x0F +#define DefaultCursorVisible TRUE + +SUPPORT_RES *SupportedModes = NULL; + +SIMPLE_TEXT_OUTPUT_MODE MasterMode = + { + 1, // MaxMode + 0, // Current Mode + 0x0F, // Attribute + 0, // Column + 0, // Row + 1 // CursorVisible + }; + + +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mCSOutProtocol = + { + CSReset, + CSOutputString, + CSTestString, + CSQueryMode, + CSSetMode, + CSSetAttribute, + CSClearScreen, + CSSetCursorPosition, + CSEnableCursor, + &MasterMode + }; + +//****************************** Virtual ConOut **********************// +CHAR16 *ScreenBuffer = NULL; +CHAR16 *SaveScreenBuffer = NULL; +CHAR16 *EndOfTheScreen = NULL; +INT32 *AttributeBuffer = NULL; +INT32 *SaveAttributeBuffer = NULL; +INT32 Columns = 0; +BOOLEAN BlankScreen = TRUE; + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ScrollScreen +// +// Description: +// This function scrolls internal splitter buffer +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID ScrollScreen( + VOID +) +{ + INT32 i; + CHAR16 *pChar = EndOfTheScreen - Columns; + INT32 *pAttr = AttributeBuffer + (pChar-ScreenBuffer); + + pBS->CopyMem( + ScreenBuffer+Columns, ScreenBuffer, + sizeof(CHAR16)* (EndOfTheScreen - pChar) + ); + + for(i=0; i<Columns; i++) + { + *pChar++ = ' '; + *pAttr++ = MasterMode.Attribute; + } +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: MemOutputString +// +// Description: +// This function puts string into internal splitter buffer +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN CHAR16 *String - pointer to string +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS MemOutputString( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String +) +{ + INT32 Col = MasterMode.CursorColumn; + UINTN Offset = MasterMode.CursorRow * Columns; + CHAR16 *pChar = ScreenBuffer + Offset + Col; + INT32 *pAttr = AttributeBuffer + Offset + Col; + BlankScreen = FALSE; + + while(TRUE){ + switch(*String){ + case 0: + return EFI_SUCCESS; + case '\n': + if ((pChar + Columns) >= EndOfTheScreen) + ScrollScreen(); + else + { + pChar += Columns; + pAttr += Columns; + } + break; + case '\r': + pChar -= Col; + pAttr -= Col; + Col = 0; + break; + case '\b': + if (Col) + { + pChar--; + pAttr--; + Col--; + } + break; + default: + if ((pChar + 1) == EndOfTheScreen) + { + ScrollScreen(); + pChar -= Col; + pAttr -= Col; + Col = 0; + } + else + { + *pChar++ = *String; + *pAttr++ = MasterMode.Attribute; + Col++; + if (Col >= Columns) + Col = 0; + } + break; + } + String++; + } + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: RestoreTextScreen +// +// Description: +// This function restores screen after switching mode +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pScreen - pointer to protocol instance +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID RestoreTextScreen( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pScreen +) +{ + CHAR16 *pChar = ScreenBuffer, *pStr = ScreenBuffer; + INT32 Col = 0, *pAttr = AttributeBuffer, Attr; + CHAR16 c; + + if (BlankScreen) + return; + + Attr = *pAttr; + pScreen->SetCursorPosition(pScreen,0,0); + pScreen->SetAttribute(pScreen,Attr); + + for(; pChar<EndOfTheScreen; pChar++, pAttr++) + { + if (Col == Columns || *pAttr != Attr) + { + c = *pChar; + *pChar = 0; + pScreen->OutputString(pScreen, pStr); + *pChar = c; + pStr = pChar; + if (*pAttr != Attr) + { + Attr = *pAttr; + pScreen->SetAttribute(pScreen, Attr); + } + else + { + Col=1; + continue; + } + } + Col++; + } + //print last row + c = *--pChar; + *pChar = 0; + pScreen->OutputString(pScreen, pStr); + *pChar = c; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: MemClearScreen +// +// Description: +// This function clears internal splitter buffer +// +// Input: +// VOID +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS MemClearScreen( + VOID +) +{ + CHAR16 *pChar; + INT32 *pAttr; + for( pChar = ScreenBuffer, pAttr = AttributeBuffer + ; pChar < EndOfTheScreen + ; pChar++, pAttr++ ) + { + *pChar = ' '; + *pAttr = MasterMode.Attribute; + } + BlankScreen = TRUE; + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: MemReset +// +// Description: +// This function resets internal splitter buffer +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN BOOLEAN EV - extended verification flag +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS MemReset( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN EV +) +{ + return MemClearScreen(); +} + +///////////////// Uga Save/Restore +EFI_GRAPHICS_OUTPUT_BLT_PIXEL *PixelBuffer = NULL; +UINT32 GraphicsMode, TextMode = 0; + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: RestoreUgaScreen +// +// Description: +// This function restores screen after switching from text to graphics mode +// +// Input: +// IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This - pointer to protocol instance +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID RestoreUgaScreen( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop +) +{ + if (PixelBuffer){ + EFI_STATUS Status; + Status = Gop->SetMode(Gop, GraphicsMode); + if (!EFI_ERROR(Status)) + Gop->Blt( + Gop, PixelBuffer, EfiBltBufferToVideo, 0, 0, 0, 0, + Gop->Mode->Info->HorizontalResolution, + Gop->Mode->Info->VerticalResolution, 0 + ); + pBS->FreePool(PixelBuffer); + PixelBuffer = NULL; + } +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: SaveUgaScreen +// +// Description: +// This function saves graphics screen before switching to text mode +// +// Input: +// IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This - pointer to protocol instance +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID SaveUgaScreen( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop +) +{ + if (PixelBuffer) + pBS->FreePool(PixelBuffer); + + GraphicsMode=Gop->Mode->Mode; + PixelBuffer = Malloc( + Gop->Mode->Info->VerticalResolution* + Gop->Mode->Info->HorizontalResolution* + sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + + if (PixelBuffer) + { + EFI_STATUS Status=Gop->Blt( + Gop, PixelBuffer, EfiBltVideoToBltBuffer, 0, 0, 0, 0, + Gop->Mode->Info->HorizontalResolution, + Gop->Mode->Info->VerticalResolution, 0); + + if (EFI_ERROR(Status)) + { + pBS->FreePool(PixelBuffer); + PixelBuffer = NULL; + } + } +} + +static EFI_GUID guidGop = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: RestoreTextScreenDelta +// +// Description: +// This function checks to see if anything has changed on the screen since the +// graphics output device was disabled. If something has changed, then it will +// add that to the display. +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID RestoreTextScreenDelta( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pScreen +) +{ + UINT32 i; + CHAR16 StrBuffer[2] = {0, 0}; + CONST UINT32 SizeOfScreen = (UINT32)((UINT8*)EndOfTheScreen-(UINT8*)ScreenBuffer) / sizeof(CHAR16); + + + // Check for differences from the old state, one by one + // If anything is different, update the screen with Simple Out protocol + for(i = 0; i < SizeOfScreen; i++) + { + if( (*(SaveScreenBuffer+i) != *(ScreenBuffer + i)) || + (*(SaveAttributeBuffer+i) != *(AttributeBuffer + i)) ) + { + StrBuffer[0] = *(ScreenBuffer + i); + pScreen->SetCursorPosition(pScreen, i % Columns, i / Columns); + pScreen->SetAttribute(pScreen, (UINT8)*(AttributeBuffer + i) ); + pScreen->OutputString(pScreen, StrBuffer ); + } + } + +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: RestoreTheScreen +// +// Description: +// This function restores screen of the output device after switching modes +// +// Input: +// IN EFI_HANDLE ControllerHandle - handle of output device to restore +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut - pointer to protocol instance +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID RestoreTheScreen( + IN EFI_HANDLE ControllerHandle, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut +) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + + if (EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop))) + RestoreTextScreen(SimpleOut); + else + { + RestoreUgaScreen(Gop); + if(SaveScreenBuffer != NULL) + { + RestoreTextScreenDelta(SimpleOut); + pBS->FreePool(SaveScreenBuffer); + pBS->FreePool(SaveAttributeBuffer); + } + } + SimpleOut->SetAttribute(SimpleOut,MasterMode.Attribute); + SimpleOut->EnableCursor(SimpleOut,MasterMode.CursorVisible); + SimpleOut->SetCursorPosition(SimpleOut,MasterMode.CursorColumn,MasterMode.CursorRow); +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: SaveTheScreen +// +// Description: +// This function saves the screen of the output device before switching modes +// +// Input: +// IN EFI_HANDLE ControllerHandle - handle of output device to save +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut - pointer to protocol instance +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID SaveTheScreen( + IN EFI_HANDLE ControllerHandle, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + UINT32 SizeOfScreen, SizeOfAttribute; + EFI_TPL OldTpl; + + if (!EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop))) + { + + SizeOfScreen = (UINT32)((UINT8*)EndOfTheScreen-(UINT8*)ScreenBuffer); + SizeOfAttribute = (UINT32)SizeOfScreen*(sizeof(INT32)/sizeof(CHAR16)); + + // Allocate memory for saving the screen state, error out if not enough memory + SaveScreenBuffer=Malloc(SizeOfScreen); + if(SaveScreenBuffer==NULL) return; + SaveAttributeBuffer=Malloc(SizeOfAttribute); + if(SaveAttributeBuffer==NULL){ + pBS->FreePool(SaveScreenBuffer); + return; + } + // Make this high priority so that the saved text screen is exactly + // the same as graphics screen + OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL); + + // Perform using MemCpy (instead of pBS->MemCopy) to prevent TPL assert + MemCpy(SaveScreenBuffer, ScreenBuffer, SizeOfScreen); + MemCpy(SaveAttributeBuffer, AttributeBuffer, SizeOfAttribute); + + pBS->RestoreTPL(OldTpl); + SaveUgaScreen(Gop); + } +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: SaveUgaMode +// +// Description: +// This function saves the graphics mode of the output device before switching modes +// +// Input: +// IN EFI_HANDLE ControllerHandle - handle of output device to save +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID SaveUgaMode( + IN EFI_HANDLE ControllerHandle +) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + + if (EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop))) + return; + + TextMode=Gop->Mode->Mode; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: RestoreUgaMode +// +// Description: +// This function restores the graphics mode of the output device after switching modes +// +// Input: +// IN EFI_HANDLE ControllerHandle - handle of output device to restore +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID RestoreUgaMode( + IN EFI_HANDLE ControllerHandle +) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + + if (EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop))) + return; + + if (TextMode!=Gop->Mode->Mode) + { + Gop->SetMode(Gop,TextMode); + } + else + {//Just clear the screen + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Buffer = {0,0,0,0}; + Gop->Blt( Gop, &Buffer, EfiBltVideoFill,0,0,0,0, + Gop->Mode->Info->HorizontalResolution, + Gop->Mode->Info->VerticalResolution, + 0 + ); + } +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSReset +// +// Description: +// This function resets the text output device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN BOOLEAN EV - extended verification flag +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - all devices, handled by splitter were reset successfully +// EFI_DEVICE_ERROR - error occured during resetting the device +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSReset( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN EV +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their Reset function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->Reset(SimpleOut->SimpleOut, EV); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + MemReset(This,EV); + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSOutputString +// +// Description: +// This function writes a string to the output device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN CHAR16 *String - pointer to string to write +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// EFI_DEVICE_ERROR - error occured during output string +// EFI_WARN_UNKNOWN_GLYPH - some of characters were skipped during output +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSOutputString( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + MemOutputString(This,String); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their OutputString function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->OutputString(SimpleOut->SimpleOut, String); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSTestString +// +// Description: +// This function tests whether all characters in String can be drawn on device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN CHAR16 *String - pointer to string to test +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - all characters can be drawn +// EFI_UNSUPPORTED - there are characters that cannot be drawn +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSTestString( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their TestString function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->TestString(SimpleOut->SimpleOut, String); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSQueryMode +// +// Description: +// This function returns information about text mode referred by ModeNum +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN UINTN ModeNum - mode number to obtain information about +// OUT UINTN *Col - max number of columns supported in this mode +// OUT UINTN *Row - max number of rows supported in this mode +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// EFI_UNSUPPORTED - given mode unsupported +// EFI_DEVICE_ERROR - error occured during execution +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSQueryMode( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNum, + OUT UINTN *Col, + OUT UINTN *Row +) +{ + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if((ModeNum >= (UINTN)MasterMode.MaxMode) || (!SupportedModes[ModeNum].AllDevices)) + return EFI_UNSUPPORTED; + + if (SimpleOut == NULL) + { + // since we use a default text mode, return that value + *Col = 80; + *Row = 25; + + return EFI_DEVICE_ERROR; + } + + *Col = SupportedModes[ModeNum].Columns; + *Row = SupportedModes[ModeNum].Rows; + return EFI_SUCCESS; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSSetMode +// +// Description: +// This function sets text mode referred by ModeNumber +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN UINTN ModeNum - mode number to set +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// EFI_UNSUPPORTED - given mode unsupported +// EFI_DEVICE_ERROR - error occured during execution +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSSetMode( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNum +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + INT32 DeviceMode; + + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if((ModeNum >= (UINTN)MasterMode.MaxMode) || (!SupportedModes[ModeNum].AllDevices)) + return EFI_UNSUPPORTED; + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + TestStatus = ResizeSplitterBuffer((INT32)ModeNum); + if (EFI_ERROR(TestStatus)) + return TestStatus; + + MasterMode.Mode = (INT32)ModeNum; + // we need to loop through all the registered simple text out devices + // and call each of their SetMode function + while ( SimpleOut != NULL) + { + TestStatus = IsModeSupported(SimpleOut->SimpleOut, ModeNum, &DeviceMode); + + TestStatus = SimpleOut->SimpleOut->SetMode(SimpleOut->SimpleOut, DeviceMode); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + return EFI_ERROR(Status); +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSSetAttribute +// +// Description: +// This function sets the foreground color and background color for the screen +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN UINTN Attribute - attribute to set +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - attribute was changed successfully +// EFI_DEVICE_ERROR - device had an error +// EFI_UNSUPPORTED - attribute is not supported +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSSetAttribute( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their SetAttribute function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->SetAttribute(SimpleOut->SimpleOut, Attribute); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSClearScreen +// +// Description: +// This function clears screen of output device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// EFI_DEVICE_ERROR - error occured during execution +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSClearScreen( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their ClearScreen function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->ClearScreen(SimpleOut->SimpleOut); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + MemClearScreen(); + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSSetCursorPosition +// +// Description: +// This function sets cursor position of output device +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN UINTN Column - column position +// IN UINTN Row - row position +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// EFI_DEVICE_ERROR - error occured during execution +// EFI_UNSUPPORTED - given position cannot be set +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSSetCursorPosition( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row +) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their SetCursorPosition function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->SetCursorPosition(SimpleOut->SimpleOut, Column, Row); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + UpdateMasterMode(SimpleOut->SimpleOut->Mode); + + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: CSEnableCursor +// +// Description: +// This function enables / disables cursor on the screen +// +// Input: +// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance +// IN BOOLEAN Visible - if TRUE cursor will be visible, FALSE - not visible +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - function executed successfully +// EFI_DEVICE_ERROR - error occured during execution +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS CSEnableCursor( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible ) +{ + EFI_STATUS Status = EFI_SUCCESS, TestStatus; + CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT); + + if (SimpleOut == NULL) + return EFI_DEVICE_ERROR; + + // we need to loop through all the registered simple text out devices + // and call each of their SetCursorPosition function + while ( SimpleOut != NULL) + { + TestStatus = SimpleOut->SimpleOut->EnableCursor(SimpleOut->SimpleOut, Visible); + SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT); + + if (EFI_ERROR(TestStatus)) + Status = TestStatus; + } + + MasterMode.CursorVisible = Visible; + return Status; +} + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UpdateMasterMode +// +// Description: +// This function updates splitter mode to values referred by Mode +// +// Input: +// IN SIMPLE_TEXT_OUTPUT_MODE *Mode - pointer to values to be set +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +VOID UpdateMasterMode( + SIMPLE_TEXT_OUTPUT_MODE *Mode) +{ + MasterMode.Attribute = Mode->Attribute; + MasterMode.CursorColumn = Mode->CursorColumn; + MasterMode.CursorRow = Mode->CursorRow; + while(MasterMode.CursorColumn>=SupportedModes[MasterMode.Mode].Columns){ + MasterMode.CursorColumn-=SupportedModes[MasterMode.Mode].Columns; + MasterMode.CursorRow++; + }; + if (MasterMode.CursorRow>=SupportedModes[MasterMode.Mode].Rows) + MasterMode.CursorRow=SupportedModes[MasterMode.Mode].Rows-1; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |