Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and\r
Simple Text Output Protocol upon Serial IO Protocol.\r
\r
-Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-\r
#include "Terminal.h"\r
\r
//\r
// Globals\r
//\r
-EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {\r
TerminalDriverBindingSupported,\r
TerminalDriverBindingStart,\r
TerminalDriverBindingStop,\r
NULL\r
};\r
\r
-\r
-EFI_GUID *gTerminalType[] = {\r
+EFI_GUID *mTerminalType[] = {\r
&gEfiPcAnsiGuid,\r
&gEfiVT100Guid,\r
&gEfiVT100PlusGuid,\r
&gEfiVTUTF8Guid,\r
- &gEfiTtyTermGuid\r
+ &gEfiTtyTermGuid,\r
+ &gEdkiiLinuxTermGuid,\r
+ &gEdkiiXtermR6Guid,\r
+ &gEdkiiVT400Guid,\r
+ &gEdkiiSCOTermGuid\r
};\r
\r
+CHAR16 *mSerialConsoleNames[] = {\r
+ L"PC-ANSI Serial Console",\r
+ L"VT-100 Serial Console",\r
+ L"VT-100+ Serial Console",\r
+ L"VT-UTF8 Serial Console",\r
+ L"Tty Terminal Serial Console",\r
+ L"Linux Terminal Serial Console",\r
+ L"Xterm R6 Serial Console",\r
+ L"VT-400 Serial Console",\r
+ L"SCO Terminal Serial Console"\r
+};\r
\r
TERMINAL_DEV mTerminalDevTemplate = {\r
TERMINAL_DEV_SIGNATURE,\r
TerminalConOutEnableCursor,\r
NULL\r
},\r
- { // SimpleTextOutputMode\r
- 1, // MaxMode\r
- 0, // Mode\r
- EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
- 0, // CursorColumn\r
- 0, // CursorRow\r
- TRUE // CursorVisible\r
+ { // SimpleTextOutputMode\r
+ 1, // MaxMode\r
+ 0, // Mode\r
+ EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
+ 0, // CursorColumn\r
+ 0, // CursorRow\r
+ TRUE // CursorVisible\r
},\r
NULL, // TerminalConsoleModeData\r
- 0, // SerialInTimeOut\r
+ 0, // SerialInTimeOut\r
\r
NULL, // RawFifo\r
NULL, // UnicodeFiFo\r
INPUT_STATE_DEFAULT,\r
RESET_STATE_DEFAULT,\r
{\r
- 0,\r
- 0,\r
- 0\r
+ 0,\r
+ 0,\r
+ 0\r
},\r
0,\r
FALSE,\r
NULL // KeyNotifyProcessEvent\r
};\r
\r
-TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
- {100, 31},\r
+TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
+ { 80, 25 },\r
+ { 80, 50 },\r
+ { 100, 31 },\r
//\r
// New modes can be added here.\r
//\r
};\r
\r
+/**\r
+ Convert the GUID representation of terminal type to enum type.\r
+\r
+ @param Guid The GUID representation of terminal type.\r
+\r
+ @return The terminal type in enum type.\r
+**/\r
+TERMINAL_TYPE\r
+TerminalTypeFromGuid (\r
+ IN EFI_GUID *Guid\r
+ )\r
+{\r
+ TERMINAL_TYPE Type;\r
+\r
+ for (Type = 0; Type < ARRAY_SIZE (mTerminalType); Type++) {\r
+ if (CompareGuid (Guid, mTerminalType[Type])) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Type;\r
+}\r
+\r
/**\r
Test to see if this driver supports Controller.\r
\r
EFI_STATUS\r
EFIAPI\r
TerminalDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
EFI_STATUS Status;\r
// If RemainingDevicePath isn't the End of Device Path Node,\r
// check its validation\r
//\r
- Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
-\r
- if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
- Node->Header.SubType != MSG_VENDOR_DP ||\r
- DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
+ Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
\r
+ if ((Node->Header.Type != MESSAGING_DEVICE_PATH) ||\r
+ (Node->Header.SubType != MSG_VENDOR_DP) ||\r
+ (DevicePathNodeLength (&Node->Header) != sizeof (VENDOR_DEVICE_PATH)))\r
+ {\r
return EFI_UNSUPPORTED;\r
-\r
}\r
+\r
//\r
- // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types\r
+ // only supports PC ANSI, VT100, VT100+, VT-UTF8, TtyTerm\r
+ // Linux, XtermR6, VT400 and SCO terminal types\r
//\r
- if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
- !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
- !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
- !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid) &&\r
- !CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-\r
+ if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {\r
return EFI_UNSUPPORTED;\r
}\r
}\r
}\r
+\r
//\r
// Open the IO Abstraction(s) needed to perform the supported test\r
// The Controller must support the Serial I/O Protocol.\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiSerialIoProtocolGuid,\r
- (VOID **) &SerialIo,\r
+ (VOID **)&SerialIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
// Close the I/O Abstraction(s) used to perform the supported test\r
//\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
//\r
// Open the EFI Device Path protocol needed to perform the supported test\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
+ (VOID **)&ParentDevicePath,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
// Close protocol, don't use device path protocol in the Support() function\r
//\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
return Status;\r
}\r
\r
/**\r
- Build the terminal device path for the child device according to the\r
- terminal type.\r
+ Free notify functions list.\r
\r
- @param ParentDevicePath Parent device path.\r
- @param RemainingDevicePath A specific child device.\r
+ @param ListHead The list head\r
\r
- @return The child device path built.\r
+ @retval EFI_SUCCESS Free the notify list successfully.\r
+ @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
\r
**/\r
-EFI_DEVICE_PATH_PROTOCOL*\r
-EFIAPI\r
-BuildTerminalDevpath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
)\r
{\r
- EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
- TERMINAL_TYPE TerminalType;\r
- VENDOR_DEVICE_PATH *Node;\r
- EFI_STATUS Status;\r
-\r
- TerminalDevicePath = NULL;\r
-\r
- //\r
- // Use the RemainingDevicePath to determine the terminal type\r
- //\r
- Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
- if (Node == NULL) {\r
- TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
-\r
- } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
-\r
- TerminalType = TerminalTypePcAnsi;\r
-\r
- } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
-\r
- TerminalType = TerminalTypeVt100;\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
\r
- } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
-\r
- TerminalType = TerminalTypeVt100Plus;\r
-\r
- } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
-\r
- TerminalType = TerminalTypeVtUtf8;\r
-\r
- } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-\r
- TerminalType = TerminalTypeTtyTerm;\r
-\r
- } else {\r
- return NULL;\r
+ if (ListHead == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- //\r
- // Build the device path for the child device\r
- //\r
- Status = SetTerminalDevicePath (\r
- TerminalType,\r
- ParentDevicePath,\r
- &TerminalDevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
+ while (!IsListEmpty (ListHead)) {\r
+ NotifyNode = CR (\r
+ ListHead->ForwardLink,\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
+ NotifyEntry,\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ RemoveEntryList (ListHead->ForwardLink);\r
+ FreePool (NotifyNode);\r
}\r
- return TerminalDevicePath;\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Compare a device path data structure to that of all the nodes of a\r
- second device path instance.\r
+ Initialize all the text modes which the terminal console supports.\r
\r
- @param Multi A pointer to a multi-instance device path data structure.\r
- @param Single A pointer to a single-instance device path data structure.\r
+ It returns information for available text modes that the terminal can support.\r
\r
- @retval TRUE If the Single is contained within Multi.\r
- @retval FALSE The Single is not match within Multi.\r
+ @param[out] TextModeCount The total number of text modes that terminal console supports.\r
+\r
+ @return The buffer to the text modes column and row information.\r
+ Caller is responsible to free it when it's non-NULL.\r
\r
**/\r
-BOOLEAN\r
-MatchDevicePaths (\r
- IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
- IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+TERMINAL_CONSOLE_MODE_DATA *\r
+InitializeTerminalConsoleTextMode (\r
+ OUT INT32 *TextModeCount\r
)\r
{\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
- UINTN Size;\r
+ TERMINAL_CONSOLE_MODE_DATA *TextModeData;\r
\r
- DevicePath = Multi;\r
- DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
- //\r
- // Search for the match of 'Single' in 'Multi'\r
- //\r
- while (DevicePathInst != NULL) {\r
- //\r
- // If the single device path is found in multiple device paths,\r
- // return success\r
- //\r
- if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
- FreePool (DevicePathInst);\r
- return TRUE;\r
- }\r
+ ASSERT (TextModeCount != NULL);\r
\r
- FreePool (DevicePathInst);\r
- DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);\r
+ if (TextModeData == NULL) {\r
+ return NULL;\r
}\r
\r
- return FALSE;\r
-}\r
+ *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);\r
\r
-/**\r
- Check whether the terminal device path is in the global variable.\r
+ DEBUG_CODE_BEGIN ();\r
+ INT32 Index;\r
\r
- @param VariableName Pointer to one global variable.\r
- @param TerminalDevicePath Pointer to the terminal device's device path.\r
+ for (Index = 0; Index < *TextModeCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Terminal - Mode %d, Column = %d, Row = %d\n",\r
+ Index,\r
+ TextModeData[Index].Columns,\r
+ TextModeData[Index].Rows\r
+ ));\r
+ }\r
+\r
+ DEBUG_CODE_END ();\r
+ return TextModeData;\r
+}\r
\r
- @retval TRUE The devcie is in the global variable.\r
- @retval FALSE The devcie is not in the global variable.\r
+/**\r
+ Stop the terminal state machine.\r
\r
+ @param TerminalDevice The terminal device.\r
**/\r
-BOOLEAN\r
-IsTerminalInConsoleVariable (\r
- IN CHAR16 *VariableName,\r
- IN EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath\r
+VOID\r
+StopTerminalStateMachine (\r
+ TERMINAL_DEV *TerminalDevice\r
)\r
{\r
- EFI_DEVICE_PATH_PROTOCOL *Variable;\r
- BOOLEAN ReturnFlag;\r
+ EFI_TPL OriginalTpl;\r
\r
- //\r
- // Get global variable and its size according to the name given.\r
- //\r
- GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
- if (Variable == NULL) {\r
- return FALSE;\r
- }\r
+ OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
- //\r
- // Check whether the terminal device path is one of the variable instances.\r
- //\r
- ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
+ gBS->CloseEvent (TerminalDevice->TimerEvent);\r
+ gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
\r
- FreePool (Variable);\r
-\r
- return ReturnFlag;\r
+ gBS->RestoreTPL (OriginalTpl);\r
}\r
\r
/**\r
- Free notify functions list.\r
-\r
- @param ListHead The list head\r
-\r
- @retval EFI_SUCCESS Free the notify list successfully.\r
- @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
+ Start the terminal state machine.\r
\r
+ @param TerminalDevice The terminal device.\r
**/\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\r
+VOID\r
+StartTerminalStateMachine (\r
+ TERMINAL_DEV *TerminalDevice\r
)\r
{\r
- TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ TerminalConInTimerHandler,\r
+ TerminalDevice,\r
+ &TerminalDevice->TimerEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- if (ListHead == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- while (!IsListEmpty (ListHead)) {\r
- NotifyNode = CR (\r
- ListHead->ForwardLink,\r
- TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
- NotifyEntry,\r
- TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
- );\r
- RemoveEntryList (ListHead->ForwardLink);\r
- FreePool (NotifyNode);\r
- }\r
+ Status = gBS->SetTimer (\r
+ TerminalDevice->TimerEvent,\r
+ TimerPeriodic,\r
+ KEYBOARD_TIMER_INTERVAL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- return EFI_SUCCESS;\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &TerminalDevice->TwoSecondTimeOut\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
}\r
\r
/**\r
- Initialize all the text modes which the terminal console supports.\r
-\r
- It returns information for available text modes that the terminal can support.\r
-\r
- @param[out] TextModeCount The total number of text modes that terminal console supports.\r
- @param[out] TextModeData The buffer to the text modes column and row information.\r
- Caller is responsible to free it when it's non-NULL.\r
+ Initialize the controller name table.\r
\r
- @retval EFI_SUCCESS The supporting mode information is returned.\r
- @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @param TerminalType The terminal type.\r
+ @param ControllerNameTable The controller name table.\r
\r
+ @retval EFI_SUCCESS The controller name table is initialized successfully.\r
+ @retval others Return status of AddUnicodeString2 ().\r
**/\r
EFI_STATUS\r
-InitializeTerminalConsoleTextMode (\r
- OUT UINTN *TextModeCount,\r
- OUT TERMINAL_CONSOLE_MODE_DATA **TextModeData\r
+InitializeControllerNameTable (\r
+ TERMINAL_TYPE TerminalType,\r
+ EFI_UNICODE_STRING_TABLE **ControllerNameTable\r
)\r
{\r
- UINTN Index;\r
- UINTN Count;\r
- TERMINAL_CONSOLE_MODE_DATA *ModeBuffer;\r
- TERMINAL_CONSOLE_MODE_DATA *NewModeBuffer;\r
- UINTN ValidCount;\r
- UINTN ValidIndex;\r
- \r
- if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
+ EFI_STATUS Status;\r
+ EFI_UNICODE_STRING_TABLE *Table;\r
+\r
+ ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
+ Table = NULL;\r
+ Status = AddUnicodeString2 (\r
+ "eng",\r
+ gTerminalComponentName.SupportedLanguages,\r
+ &Table,\r
+ mSerialConsoleNames[TerminalType],\r
+ TRUE\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = AddUnicodeString2 (\r
+ "en",\r
+ gTerminalComponentName2.SupportedLanguages,\r
+ &Table,\r
+ mSerialConsoleNames[TerminalType],\r
+ FALSE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreeUnicodeStringTable (Table);\r
+ }\r
}\r
- \r
- Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
- \r
- //\r
- // Get defined mode buffer pointer.\r
- //\r
- ModeBuffer = mTerminalConsoleModeData;\r
- \r
- //\r
- // Here we make sure that the final mode exposed does not include the duplicated modes,\r
- // and does not include the invalid modes which exceed the max column and row.\r
- // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
- //\r
- NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
- ASSERT (NewModeBuffer != NULL);\r
-\r
- //\r
- // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
- //\r
- ValidCount = 0; \r
-\r
- NewModeBuffer[ValidCount].Columns = 80;\r
- NewModeBuffer[ValidCount].Rows = 25;\r
- ValidCount++;\r
\r
- NewModeBuffer[ValidCount].Columns = 80;\r
- NewModeBuffer[ValidCount].Rows = 50;\r
- ValidCount++;\r
- \r
- //\r
- // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
- //\r
- for (Index = 0; Index < Count; Index++) {\r
- if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
- //\r
- // Skip the pre-defined mode which is invalid.\r
- //\r
- continue;\r
- }\r
- for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
- if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
- (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
- //\r
- // Skip the duplicated mode.\r
- //\r
- break;\r
- }\r
- }\r
- if (ValidIndex == ValidCount) {\r
- NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
- NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows;\r
- ValidCount++;\r
- }\r
+ if (!EFI_ERROR (Status)) {\r
+ *ControllerNameTable = Table;\r
}\r
- \r
- DEBUG_CODE (\r
- for (Index = 0; Index < ValidCount; Index++) {\r
- DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
- Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows)); \r
- }\r
- );\r
- \r
- //\r
- // Return valid mode count and mode information buffer.\r
- //\r
- *TextModeCount = ValidCount;\r
- *TextModeData = NewModeBuffer;\r
- return EFI_SUCCESS;\r
+\r
+ return Status;\r
}\r
\r
/**\r
EFI_STATUS\r
EFIAPI\r
TerminalDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- VENDOR_DEVICE_PATH *Node;\r
- EFI_SERIAL_IO_MODE *Mode;\r
- UINTN SerialInTimeOut;\r
- TERMINAL_DEV *TerminalDevice;\r
- TERMINAL_TYPE TerminalType;\r
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
- UINTN EntryCount;\r
- UINTN Index;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
- EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextInput;\r
- BOOLEAN ConInSelected;\r
- BOOLEAN ConOutSelected;\r
- BOOLEAN NullRemaining;\r
- BOOLEAN SimTxtInInstalled;\r
- BOOLEAN SimTxtOutInstalled;\r
- BOOLEAN FirstEnter;\r
- UINTN ModeCount;\r
-\r
- TerminalDevice = NULL;\r
- ConInSelected = FALSE;\r
- ConOutSelected = FALSE;\r
- NullRemaining = FALSE;\r
- SimTxtInInstalled = FALSE;\r
- SimTxtOutInstalled = FALSE;\r
- FirstEnter = FALSE;\r
+ EFI_STATUS Status;\r
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Vendor;\r
+ EFI_HANDLE SerialIoHandle;\r
+ EFI_SERIAL_IO_MODE *Mode;\r
+ UINTN SerialInTimeOut;\r
+ TERMINAL_DEV *TerminalDevice;\r
+ UINT8 TerminalType;\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
+ UINTN EntryCount;\r
+ UINTN Index;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextInput;\r
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;\r
+\r
//\r
// Get the Device Path Protocol to build the device path of the child device\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
+ (VOID **)&ParentDevicePath,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+ ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));\r
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
return Status;\r
}\r
\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiSerialIoProtocolGuid,\r
- (VOID **) &SerialIo,\r
+ (VOID **)&SerialIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+ ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));\r
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
return Status;\r
}\r
\r
- if (Status != EFI_ALREADY_STARTED) {\r
+ if (!IsHotPlugDevice (ParentDevicePath)) {\r
//\r
- // the serial I/O protocol never be opened before, it is the first\r
- // time to start the serial Io controller\r
+ // if the serial device is a hot plug device, do not update the\r
+ // ConInDev, ConOutDev, and StdErrDev variables.\r
//\r
- FirstEnter = TRUE;\r
+ TerminalUpdateConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);\r
+ TerminalUpdateConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+ TerminalUpdateConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
}\r
\r
//\r
- // Serial I/O is not already open by this driver, then tag the handle\r
- // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
- // StdErrDev variables with the list of possible terminal types on this\r
- // serial port.\r
+ // Do not create any child for END remaining device path.\r
//\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiCallerIdGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Controller,\r
- &gEfiCallerIdGuid,\r
- DuplicateDevicePath (ParentDevicePath),\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {\r
+ return EFI_SUCCESS;\r
+ }\r
\r
- if (!IsHotPlugDevice (ParentDevicePath)) {\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ if (RemainingDevicePath == NULL) {\r
//\r
- // if the serial device is a hot plug device, do not update the\r
- // ConInDev, ConOutDev, and StdErrDev variables.\r
+ // If RemainingDevicePath is NULL or is the End of Device Path Node\r
//\r
- TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
- TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
- TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
+ return EFI_SUCCESS;\r
}\r
- }\r
-\r
- //\r
- // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
- //\r
- // Simple In/Out Protocol will not be installed onto the handle if the\r
- // device path to the handle is not present in the ConIn/ConOut\r
- // environment variable. But If RemainingDevicePath is NULL, then always\r
- // produce both Simple In and Simple Text Output Protocols. This is required\r
- // for the connect all sequences to make sure all possible consoles are\r
- // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
- //\r
- if (RemainingDevicePath == NULL) {\r
- NullRemaining = TRUE;\r
- }\r
\r
- DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
- if (DevicePath != NULL) {\r
- ConInSelected = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
- ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
- FreePool (DevicePath);\r
- } else {\r
- goto Error;\r
- }\r
- //\r
- // Not create the child terminal handle if both Simple In/In Ex and\r
- // Simple text Out protocols are not required to be published\r
- //\r
- if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // create the child terminal handle during first entry\r
- //\r
- if (FirstEnter) {\r
- //\r
- // First enther the start function\r
- //\r
- FirstEnter = FALSE;\r
//\r
- // Make sure a child handle does not already exist. This driver can only\r
- // produce one child per serial port.\r
+ // This driver can only produce one child per serial port.\r
+ // Change its terminal type as remaining device path requests.\r
//\r
Status = gBS->OpenProtocolInformation (\r
Controller,\r
&EntryCount\r
);\r
if (!EFI_ERROR (Status)) {\r
- Status = EFI_SUCCESS;\r
+ Status = EFI_NOT_FOUND;\r
for (Index = 0; Index < EntryCount; Index++) {\r
if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
- Status = EFI_ALREADY_STARTED;\r
+ Status = gBS->OpenProtocol (\r
+ OpenInfoBuffer[Index].ControllerHandle,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ (VOID **)&SimpleTextInput,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
+ TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid);\r
+ ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
+ if (TerminalDevice->TerminalType != TerminalType) {\r
+ Status = InitializeControllerNameTable (TerminalType, &ControllerNameTable);\r
+ if (!EFI_ERROR (Status)) {\r
+ StopTerminalStateMachine (TerminalDevice);\r
+ //\r
+ // Update the device path\r
+ //\r
+ Vendor = TerminalDevice->DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiSerialIoProtocolGuid, &Vendor, &SerialIoHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+ CopyGuid (&((VENDOR_DEVICE_PATH *)Vendor)->Guid, mTerminalType[TerminalType]);\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ TerminalDevice->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ TerminalDevice->DevicePath,\r
+ TerminalDevice->DevicePath\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ TerminalDevice->TerminalType = TerminalType;\r
+ StartTerminalStateMachine (TerminalDevice);\r
+ FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+ TerminalDevice->ControllerNameTable = ControllerNameTable;\r
+ } else {\r
+ //\r
+ // Restore the device path on failure\r
+ //\r
+ CopyGuid (&((VENDOR_DEVICE_PATH *)Vendor)->Guid, mTerminalType[TerminalDevice->TerminalType]);\r
+ FreeUnicodeStringTable (ControllerNameTable);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
}\r
}\r
\r
FreePool (OpenInfoBuffer);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
- }\r
-\r
- //\r
- // If RemainingDevicePath is NULL, use default terminal type\r
- //\r
- if (RemainingDevicePath == NULL) {\r
- TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
- //\r
- // Must be between TerminalTypePcAnsi (0) and TerminalTypeTtyTerm (4)\r
- //\r
- ASSERT (TerminalType <= TerminalTypeTtyTerm);\r
- } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node,\r
- // Use the RemainingDevicePath to determine the terminal type\r
- //\r
- Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
- if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
- TerminalType = TerminalTypePcAnsi;\r
- } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
- TerminalType = TerminalTypeVt100;\r
- } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
- TerminalType = TerminalTypeVt100Plus;\r
- } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
- TerminalType = TerminalTypeVtUtf8;\r
- } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
- TerminalType = TerminalTypeTtyTerm;\r
- } else {\r
- goto Error;\r
- }\r
- } else {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node,\r
- // skip enumerate any device and return EFI_SUCESSS\r
- //\r
- return EFI_SUCCESS;\r
}\r
\r
- //\r
- // Initialize the Terminal Dev\r
- //\r
- TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
- if (TerminalDevice == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
-\r
- TerminalDevice->TerminalType = TerminalType;\r
- TerminalDevice->SerialIo = SerialIo;\r
-\r
- InitializeListHead (&TerminalDevice->NotifyList);\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_WAIT,\r
- TPL_NOTIFY,\r
- TerminalConInWaitForKeyEx,\r
- TerminalDevice,\r
- &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_WAIT,\r
- TPL_NOTIFY,\r
- TerminalConInWaitForKey,\r
- TerminalDevice,\r
- &TerminalDevice->SimpleInput.WaitForKey\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
- //\r
- // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
- // the pre-read pending characters.\r
- //\r
- TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
- if (TerminalDevice->RawFiFo == NULL) {\r
- goto Error;\r
- }\r
- TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
- if (TerminalDevice->UnicodeFiFo == NULL) {\r
- goto Error;\r
- }\r
- TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
- if (TerminalDevice->EfiKeyFiFo == NULL) {\r
- goto Error;\r
- }\r
- TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
- if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // Set the timeout value of serial buffer for\r
- // keystroke response performance issue\r
- //\r
- Mode = TerminalDevice->SerialIo->Mode;\r
+ return Status;\r
+ }\r
\r
- SerialInTimeOut = 0;\r
- if (Mode->BaudRate != 0) {\r
- SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
- }\r
+ //\r
+ // Initialize the Terminal Dev\r
+ //\r
+ TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
+ if (TerminalDevice == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto CloseProtocols;\r
+ }\r
\r
- Status = TerminalDevice->SerialIo->SetAttributes (\r
- TerminalDevice->SerialIo,\r
- Mode->BaudRate,\r
- Mode->ReceiveFifoDepth,\r
- (UINT32) SerialInTimeOut,\r
- (EFI_PARITY_TYPE) (Mode->Parity),\r
- (UINT8) Mode->DataBits,\r
- (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // if set attributes operation fails, invalidate\r
- // the value of SerialInTimeOut,thus make it\r
- // inconsistent with the default timeout value\r
- // of serial buffer. This will invoke the recalculation\r
- // in the readkeystroke routine.\r
- //\r
- TerminalDevice->SerialInTimeOut = 0;\r
- } else {\r
- TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
- }\r
- //\r
- // Set Simple Text Output Protocol from template.\r
- //\r
- SimpleTextOutput = CopyMem (\r
- &TerminalDevice->SimpleTextOutput,\r
- &mTerminalDevTemplate.SimpleTextOutput,\r
- sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
- );\r
- SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
- \r
- Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
- TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
- \r
+ if (RemainingDevicePath == NULL) {\r
//\r
- // For terminal devices, cursor is always visible\r
+ // If RemainingDevicePath is NULL, use default terminal type\r
//\r
- TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
- Status = TerminalConOutSetAttribute (\r
- SimpleTextOutput,\r
- EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
-\r
+ TerminalDevice->TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
+ } else {\r
//\r
- // Build the component name for the child device\r
+ // End of Device Path Node is handled in above.\r
//\r
- TerminalDevice->ControllerNameTable = NULL;\r
- switch (TerminalDevice->TerminalType) {\r
- case TerminalTypePcAnsi:\r
- AddUnicodeString2 (\r
- "eng",\r
- gTerminalComponentName.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"PC-ANSI Serial Console",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gTerminalComponentName2.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"PC-ANSI Serial Console",\r
- FALSE\r
- );\r
-\r
- break;\r
-\r
- case TerminalTypeVt100:\r
- AddUnicodeString2 (\r
- "eng",\r
- gTerminalComponentName.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"VT-100 Serial Console",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gTerminalComponentName2.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"VT-100 Serial Console",\r
- FALSE\r
- );\r
-\r
- break;\r
-\r
- case TerminalTypeVt100Plus:\r
- AddUnicodeString2 (\r
- "eng",\r
- gTerminalComponentName.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"VT-100+ Serial Console",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gTerminalComponentName2.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"VT-100+ Serial Console",\r
- FALSE\r
- );\r
-\r
- break;\r
-\r
- case TerminalTypeVtUtf8:\r
- AddUnicodeString2 (\r
- "eng",\r
- gTerminalComponentName.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"VT-UTF8 Serial Console",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gTerminalComponentName2.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"VT-UTF8 Serial Console",\r
- FALSE\r
- );\r
-\r
- break;\r
-\r
- case TerminalTypeTtyTerm:\r
- AddUnicodeString2 (\r
- "eng",\r
- gTerminalComponentName.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"Tty Terminal Serial Console",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gTerminalComponentName2.SupportedLanguages,\r
- &TerminalDevice->ControllerNameTable,\r
- (CHAR16 *)L"Tty Terminal Serial Console",\r
- FALSE\r
- );\r
-\r
- break;\r
- }\r
-\r
+ ASSERT (!IsDevicePathEnd (RemainingDevicePath));\r
//\r
- // Build the device path for the child device\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
+ // Use the RemainingDevicePath to determine the terminal type\r
//\r
- Status = SetTerminalDevicePath (\r
- TerminalDevice->TerminalType,\r
- ParentDevicePath,\r
- &TerminalDevice->DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ TerminalDevice->TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid);\r
+ }\r
\r
- Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
+ ASSERT (TerminalDevice->TerminalType < ARRAY_SIZE (mTerminalType));\r
+ TerminalDevice->SerialIo = SerialIo;\r
\r
- Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
+ //\r
+ // Build the component name for the child device\r
+ //\r
+ Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeResources;\r
+ }\r
\r
- Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
+ //\r
+ // Build the device path for the child device\r
+ //\r
+ Status = SetTerminalDevicePath (TerminalDevice->TerminalType, ParentDevicePath, &TerminalDevice->DevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeResources;\r
+ }\r
\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- TerminalConInTimerHandler,\r
- TerminalDevice,\r
- &TerminalDevice->TimerEvent\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ InitializeListHead (&TerminalDevice->NotifyList);\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ TerminalConInWaitForKeyEx,\r
+ TerminalDevice,\r
+ &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- Status = gBS->SetTimer (\r
- TerminalDevice->TimerEvent,\r
- TimerPeriodic,\r
- KEYBOARD_TIMER_INTERVAL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ TerminalConInWaitForKey,\r
+ TerminalDevice,\r
+ &TerminalDevice->SimpleInput.WaitForKey\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ TerminalDevice,\r
+ &TerminalDevice->KeyNotifyProcessEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER,\r
- TPL_CALLBACK,\r
- NULL,\r
- NULL,\r
- &TerminalDevice->TwoSecondTimeOut\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
+ // the pre-read pending characters.\r
+ //\r
+ TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
+ if (TerminalDevice->RawFiFo == NULL) {\r
+ goto FreeResources;\r
+ }\r
\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- KeyNotifyProcessHandler,\r
- TerminalDevice,\r
- &TerminalDevice->KeyNotifyProcessEvent\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
+ if (TerminalDevice->UnicodeFiFo == NULL) {\r
+ goto FreeResources;\r
+ }\r
\r
- Status = gBS->InstallProtocolInterface (\r
- &TerminalDevice->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- TerminalDevice->DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+ if (TerminalDevice->EfiKeyFiFo == NULL) {\r
+ goto FreeResources;\r
+ }\r
\r
- //\r
- // Register the Parent-Child relationship via\r
- // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- (VOID **) &TerminalDevice->SerialIo,\r
- This->DriverBindingHandle,\r
- TerminalDevice->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+ if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
+ goto FreeResources;\r
}\r
\r
//\r
- // Find the child handle, and get its TerminalDevice private data\r
+ // Set the timeout value of serial buffer for keystroke response performance issue\r
//\r
- Status = gBS->OpenProtocolInformation (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- &OpenInfoBuffer,\r
- &EntryCount\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = EFI_NOT_FOUND;\r
- ASSERT (OpenInfoBuffer != NULL);\r
- for (Index = 0; Index < EntryCount; Index++) {\r
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
- //\r
- // Find the child terminal handle.\r
- // Test whether the SimpleTxtIn and SimpleTxtOut have been published\r
- //\r
- Status = gBS->OpenProtocol (\r
- OpenInfoBuffer[Index].ControllerHandle,\r
- &gEfiSimpleTextInProtocolGuid,\r
- (VOID **) &SimpleTextInput,\r
- This->DriverBindingHandle,\r
- OpenInfoBuffer[Index].ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- SimTxtInInstalled = TRUE;\r
- TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
- }\r
+ Mode = TerminalDevice->SerialIo->Mode;\r
\r
- Status = gBS->OpenProtocol (\r
- OpenInfoBuffer[Index].ControllerHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- (VOID **) &SimpleTextOutput,\r
- This->DriverBindingHandle,\r
- OpenInfoBuffer[Index].ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- SimTxtOutInstalled = TRUE;\r
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
- }\r
- Status = EFI_SUCCESS;\r
- break;\r
- }\r
- }\r
+ SerialInTimeOut = 0;\r
+ if (Mode->BaudRate != 0) {\r
+ SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN)Mode->BaudRate;\r
+ }\r
\r
- FreePool (OpenInfoBuffer);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
+ Status = TerminalDevice->SerialIo->SetAttributes (\r
+ TerminalDevice->SerialIo,\r
+ Mode->BaudRate,\r
+ Mode->ReceiveFifoDepth,\r
+ (UINT32)SerialInTimeOut,\r
+ (EFI_PARITY_TYPE)(Mode->Parity),\r
+ (UINT8)Mode->DataBits,\r
+ (EFI_STOP_BITS_TYPE)(Mode->StopBits)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // if set attributes operation fails, invalidate\r
+ // the value of SerialInTimeOut,thus make it\r
+ // inconsistent with the default timeout value\r
+ // of serial buffer. This will invoke the recalculation\r
+ // in the readkeystroke routine.\r
+ //\r
+ TerminalDevice->SerialInTimeOut = 0;\r
} else {\r
- goto ReportError;\r
+ TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
}\r
\r
- ASSERT (TerminalDevice != NULL);\r
+ SimpleTextOutput = &TerminalDevice->SimpleTextOutput;\r
+ SimpleTextInput = &TerminalDevice->SimpleInput;\r
+\r
//\r
- // Only do the reset if the device path is in the Conout variable\r
+ // Initialize SimpleTextOut instance\r
//\r
- if (ConInSelected && !SimTxtInInstalled) {\r
- Status = TerminalDevice->SimpleInput.Reset (\r
- &TerminalDevice->SimpleInput,\r
- FALSE\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Need to report Error Code first\r
- //\r
- goto ReportError;\r
- }\r
+ SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
+ TerminalDevice->TerminalConsoleModeData = InitializeTerminalConsoleTextMode (\r
+ &SimpleTextOutput->Mode->MaxMode\r
+ );\r
+ if (TerminalDevice->TerminalConsoleModeData == NULL) {\r
+ goto FreeResources;\r
}\r
\r
//\r
- // Only output the configure string to remote terminal if the device path\r
- // is in the Conout variable\r
+ // For terminal devices, cursor is always visible\r
//\r
- if (ConOutSelected && !SimTxtOutInstalled) {\r
- Status = TerminalDevice->SimpleTextOutput.SetAttribute (\r
- &TerminalDevice->SimpleTextOutput,\r
- EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
-\r
- Status = TerminalDevice->SimpleTextOutput.Reset (\r
- &TerminalDevice->SimpleTextOutput,\r
- FALSE\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
-\r
- Status = TerminalDevice->SimpleTextOutput.SetMode (\r
- &TerminalDevice->SimpleTextOutput,\r
- 0\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
+ SimpleTextOutput->Mode->CursorVisible = TRUE;\r
+ Status = SimpleTextOutput->SetAttribute (SimpleTextOutput, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SimpleTextOutput->Reset (SimpleTextOutput, FALSE);\r
+ }\r
\r
- Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
- &TerminalDevice->SimpleTextOutput,\r
- TRUE\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
}\r
\r
//\r
- // Simple In/Out Protocol will not be installed onto the handle if the\r
- // device path to the handle is not present in the ConIn/ConOut\r
- // environment variable. But If RemainingDevicePath is NULL, then always\r
- // produce both Simple In and Simple Text Output Protocols. This is required\r
- // for the connect all sequences to make sure all possible consoles are\r
- // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
+ // Initialize SimpleTextInput instance\r
//\r
- if (!SimTxtInInstalled && (ConInSelected || NullRemaining)) {\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &TerminalDevice->Handle,\r
- &gEfiSimpleTextInProtocolGuid,\r
- &TerminalDevice->SimpleInput,\r
- &gEfiSimpleTextInputExProtocolGuid,\r
- &TerminalDevice->SimpleInputEx,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ Status = SimpleTextInput->Reset (SimpleTextInput, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
}\r
\r
- if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
- Status = gBS->InstallProtocolInterface (\r
- &TerminalDevice->Handle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &TerminalDevice->SimpleTextOutput\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &TerminalDevice->Handle,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &TerminalDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &TerminalDevice->SimpleInputEx,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ &TerminalDevice->SimpleTextOutput,\r
+ &gEfiDevicePathProtocolGuid,\r
+ TerminalDevice->DevicePath,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **)&TerminalDevice->SerialIo,\r
+ This->DriverBindingHandle,\r
+ TerminalDevice->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ ASSERT_EFI_ERROR (Status);\r
+ StartTerminalStateMachine (TerminalDevice);\r
+ return Status;\r
}\r
\r
- return EFI_SUCCESS;\r
-\r
ReportError:\r
- //\r
- // Report error code before exiting\r
- //\r
- DevicePath = ParentDevicePath;\r
REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
(EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
- DevicePath\r
+ ParentDevicePath\r
);\r
\r
-Error:\r
- //\r
- // Use the Stop() function to free all resources allocated in Start()\r
- //\r
- if (TerminalDevice != NULL) {\r
+FreeResources:\r
+ ASSERT (TerminalDevice != NULL);\r
\r
- if (TerminalDevice->Handle != NULL) {\r
- This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
- } else {\r
+ if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
+ gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
+ }\r
\r
- if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
- gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
- }\r
+ if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+ gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+ }\r
\r
- if (TerminalDevice->TimerEvent != NULL) {\r
- gBS->CloseEvent (TerminalDevice->TimerEvent);\r
- }\r
+ if (TerminalDevice->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
+ }\r
\r
- if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
- gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
- }\r
+ if (TerminalDevice->RawFiFo != NULL) {\r
+ FreePool (TerminalDevice->RawFiFo);\r
+ }\r
\r
- if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
- gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
- }\r
+ if (TerminalDevice->UnicodeFiFo != NULL) {\r
+ FreePool (TerminalDevice->UnicodeFiFo);\r
+ }\r
\r
- TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
+ if (TerminalDevice->EfiKeyFiFo != NULL) {\r
+ FreePool (TerminalDevice->EfiKeyFiFo);\r
+ }\r
\r
- if (TerminalDevice->RawFiFo != NULL) {\r
- FreePool (TerminalDevice->RawFiFo);\r
- }\r
- if (TerminalDevice->UnicodeFiFo != NULL) {\r
- FreePool (TerminalDevice->UnicodeFiFo);\r
- }\r
- if (TerminalDevice->EfiKeyFiFo != NULL) {\r
- FreePool (TerminalDevice->EfiKeyFiFo);\r
- }\r
- if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {\r
- FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
- }\r
- \r
- if (TerminalDevice->ControllerNameTable != NULL) {\r
- FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
- }\r
+ if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {\r
+ FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
+ }\r
\r
- if (TerminalDevice->DevicePath != NULL) {\r
- FreePool (TerminalDevice->DevicePath);\r
- }\r
+ if (TerminalDevice->ControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+ }\r
\r
- if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
- FreePool (TerminalDevice->TerminalConsoleModeData);\r
- }\r
+ if (TerminalDevice->DevicePath != NULL) {\r
+ FreePool (TerminalDevice->DevicePath);\r
+ }\r
\r
- FreePool (TerminalDevice);\r
- }\r
+ if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
+ FreePool (TerminalDevice->TerminalConsoleModeData);\r
}\r
\r
- This->Stop (This, Controller, 0, NULL);\r
+ FreePool (TerminalDevice);\r
\r
+CloseProtocols:\r
+\r
+ //\r
+ // Remove Parent Device Path from\r
+ // the Console Device Environment Variables\r
+ //\r
+ TerminalRemoveConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);\r
+ TerminalRemoveConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+ TerminalRemoveConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
return Status;\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
TerminalDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
EFI_STATUS Status;\r
TERMINAL_DEV *TerminalDevice;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- Status = gBS->HandleProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
\r
//\r
// Complete all outstanding transactions to Controller.\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &gEfiCallerIdGuid,\r
- (VOID **) &ParentDevicePath,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **)&ParentDevicePath,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Remove Parent Device Path from\r
- // the Console Device Environment Variables\r
- //\r
- TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
- TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
- TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
-\r
- //\r
- // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
- //\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiCallerIdGuid,\r
- ParentDevicePath,\r
- NULL\r
- );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // Free the ParentDevicePath that was duplicated in Start()\r
- //\r
- if (!EFI_ERROR (Status)) {\r
- FreePool (ParentDevicePath);\r
- }\r
- }\r
+ //\r
+ // Remove Parent Device Path from\r
+ // the Console Device Environment Variables\r
+ //\r
+ TerminalRemoveConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);\r
+ TerminalRemoveConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+ TerminalRemoveConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
return EFI_SUCCESS;\r
}\r
AllChildrenStopped = TRUE;\r
\r
for (Index = 0; Index < NumberOfChildren; Index++) {\r
-\r
Status = gBS->OpenProtocol (\r
ChildHandleBuffer[Index],\r
&gEfiSimpleTextOutProtocolGuid,\r
- (VOID **) &SimpleTextOutput,\r
+ (VOID **)&SimpleTextOutput,\r
This->DriverBindingHandle,\r
ChildHandleBuffer[Index],\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
if (!EFI_ERROR (Status)) {\r
-\r
TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- ChildHandleBuffer[Index]\r
- );\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ChildHandleBuffer[Index]\r
+ );\r
\r
Status = gBS->UninstallMultipleProtocolInterfaces (\r
ChildHandleBuffer[Index],\r
);\r
if (EFI_ERROR (Status)) {\r
gBS->OpenProtocol (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- (VOID **) &SerialIo,\r
- This->DriverBindingHandle,\r
- ChildHandleBuffer[Index],\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **)&SerialIo,\r
+ This->DriverBindingHandle,\r
+ ChildHandleBuffer[Index],\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
} else {\r
-\r
- if (TerminalDevice->ControllerNameTable != NULL) {\r
- FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
- }\r
-\r
- gBS->CloseEvent (TerminalDevice->TimerEvent);\r
- gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
+ FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+ StopTerminalStateMachine (TerminalDevice);\r
gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
FreePool (TerminalDevice->DevicePath);\r
- if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
- FreePool (TerminalDevice->TerminalConsoleModeData);\r
- }\r
+ FreePool (TerminalDevice->TerminalConsoleModeData);\r
FreePool (TerminalDevice);\r
}\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Compare a device path data structure to that of all the nodes of a\r
+ second device path instance.\r
+\r
+ @param Multi A pointer to a multi-instance device path data structure.\r
+ @param Single A pointer to a single-instance device path data structure.\r
+\r
+ @retval TRUE If the Single is contained within Multi.\r
+ @retval FALSE The Single is not match within Multi.\r
+\r
+**/\r
+BOOLEAN\r
+MatchDevicePaths (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ UINTN Size;\r
+\r
+ DevicePath = Multi;\r
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ //\r
+ // Search for the match of 'Single' in 'Multi'\r
+ //\r
+ while (DevicePathInst != NULL) {\r
+ //\r
+ // If the single device path is found in multiple device paths,\r
+ // return success\r
+ //\r
+ if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+ FreePool (DevicePathInst);\r
+ return TRUE;\r
+ }\r
+\r
+ FreePool (DevicePathInst);\r
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
/**\r
Update terminal device path in Console Device Environment Variables.\r
\r
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN NameSize;\r
- UINTN VariableSize;\r
- TERMINAL_TYPE TerminalType;\r
- EFI_DEVICE_PATH_PROTOCOL *Variable;\r
- EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EDKII_SET_VARIABLE_STATUS *SetVariableStatus;\r
+ EFI_STATUS Status;\r
+ UINTN NameSize;\r
+ UINTN VariableSize;\r
+ TERMINAL_TYPE TerminalType;\r
+ EFI_DEVICE_PATH_PROTOCOL *Variable;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EDKII_SET_VARIABLE_STATUS *SetVariableStatus;\r
\r
//\r
// Get global variable and its size according to the name given.\r
//\r
- GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
- if (Variable == NULL) {\r
+ Status = GetEfiGlobalVariable2 (VariableName, (VOID **)&Variable, NULL);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ Status = EFI_SUCCESS;\r
+ Variable = NULL;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
return;\r
}\r
\r
//\r
// Append terminal device path onto the variable.\r
//\r
- for (TerminalType = TerminalTypePcAnsi; TerminalType <= TerminalTypeTtyTerm; TerminalType++) {\r
+ for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
- NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
- ASSERT (NewVariable != NULL);\r
- if (Variable != NULL) {\r
- FreePool (Variable);\r
- }\r
\r
if (TempDevicePath != NULL) {\r
+ if (!MatchDevicePaths (Variable, TempDevicePath)) {\r
+ NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
+ if (NewVariable != NULL) {\r
+ if (Variable != NULL) {\r
+ FreePool (Variable);\r
+ }\r
+\r
+ Variable = NewVariable;\r
+ }\r
+ }\r
+\r
FreePool (TempDevicePath);\r
}\r
-\r
- Variable = NewVariable;\r
}\r
\r
VariableSize = GetDevicePathSize (Variable);\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- NameSize = StrSize (VariableName);\r
+ NameSize = StrSize (VariableName);\r
SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize);\r
if (SetVariableStatus != NULL) {\r
CopyGuid (&SetVariableStatus->Guid, &gEfiGlobalVariableGuid);\r
SetVariableStatus->DataSize = VariableSize;\r
SetVariableStatus->SetStatus = Status;\r
SetVariableStatus->Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
- CopyMem (SetVariableStatus + 1, VariableName, NameSize);\r
- CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Variable, VariableSize);\r
+ CopyMem (SetVariableStatus + 1, VariableName, NameSize);\r
+ CopyMem (((UINT8 *)(SetVariableStatus + 1)) + NameSize, Variable, VariableSize);\r
\r
REPORT_STATUS_CODE_EX (\r
EFI_ERROR_CODE,\r
\r
FreePool (Variable);\r
\r
- return ;\r
+ return;\r
}\r
\r
-\r
/**\r
Remove terminal device path from Console Device Environment Variables.\r
\r
EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
\r
- Instance = NULL;\r
+ Instance = NULL;\r
\r
//\r
// Get global variable and its size according to the name given.\r
//\r
- GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
+ GetEfiGlobalVariable2 (VariableName, (VOID **)&Variable, NULL);\r
if (Variable == NULL) {\r
- return ;\r
+ return;\r
}\r
\r
- FoundOne = FALSE;\r
- OriginalVariable = Variable;\r
- NewVariable = NULL;\r
+ FoundOne = FALSE;\r
+ OriginalVariable = Variable;\r
+ NewVariable = NULL;\r
\r
//\r
// Get first device path instance from Variable\r
Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
if (Instance == NULL) {\r
FreePool (OriginalVariable);\r
- return ;\r
+ return;\r
}\r
+\r
//\r
// Loop through all the device path instances of Variable\r
//\r
// Loop through all the terminal types that this driver supports\r
//\r
Match = FALSE;\r
- for (TerminalType = TerminalTypePcAnsi; TerminalType <= TerminalTypeTtyTerm; TerminalType++) {\r
-\r
+ for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
\r
//\r
//\r
if (TempDevicePath != NULL) {\r
if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
- Match = TRUE;\r
- FoundOne = TRUE;\r
+ Match = TRUE;\r
+ FoundOne = TRUE;\r
}\r
\r
FreePool (TempDevicePath);\r
}\r
}\r
+\r
//\r
// If a match was not found, then keep the current device path instance\r
//\r
if (!Match) {\r
- SavedNewVariable = NewVariable;\r
- NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
+ SavedNewVariable = NewVariable;\r
+ NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
if (SavedNewVariable != NULL) {\r
FreePool (SavedNewVariable);\r
}\r
}\r
+\r
//\r
// Get next device path instance from Variable\r
//\r
FreePool (NewVariable);\r
}\r
\r
- return ;\r
+ return;\r
}\r
\r
/**\r
**/\r
EFI_STATUS\r
SetTerminalDevicePath (\r
- IN TERMINAL_TYPE TerminalType,\r
- IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
+ IN TERMINAL_TYPE TerminalType,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
)\r
{\r
VENDOR_DEVICE_PATH Node;\r
\r
- *TerminalDevicePath = NULL;\r
+ ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
Node.Header.Type = MESSAGING_DEVICE_PATH;\r
Node.Header.SubType = MSG_VENDOR_DP;\r
-\r
- //\r
- // Generate terminal device path node according to terminal type.\r
- //\r
- switch (TerminalType) {\r
-\r
- case TerminalTypePcAnsi:\r
- CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
- break;\r
-\r
- case TerminalTypeVt100:\r
- CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
- break;\r
-\r
- case TerminalTypeVt100Plus:\r
- CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
- break;\r
-\r
- case TerminalTypeVtUtf8:\r
- CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
- break;\r
-\r
- case TerminalTypeTtyTerm:\r
- CopyGuid (&Node.Guid, &gEfiTtyTermGuid);\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
- //\r
- SetDevicePathNodeLength (\r
- &Node.Header,\r
- sizeof (VENDOR_DEVICE_PATH)\r
- );\r
+ SetDevicePathNodeLength (&Node.Header, sizeof (VENDOR_DEVICE_PATH));\r
+ CopyGuid (&Node.Guid, mTerminalType[TerminalType]);\r
\r
//\r
// Append the terminal node onto parent device path\r
//\r
*TerminalDevicePath = AppendDevicePathNode (\r
ParentDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&Node\r
);\r
if (*TerminalDevicePath == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
**/\r
EFI_STATUS\r
EFIAPI\r
-InitializeTerminal(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+InitializeTerminal (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
//\r
// Install driver model protocol(s).\r
**/\r
BOOLEAN\r
IsHotPlugDevice (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
)\r
{\r
- EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
\r
CheckDevicePath = DevicePath;\r
while (!IsDevicePathEnd (CheckDevicePath)) {\r
// Check device whether is hot plug device or not throught Device Path\r
//\r
if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
- DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
- DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
+ ((DevicePathSubType (CheckDevicePath) == MSG_USB_DP) ||\r
+ (DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP) ||\r
+ (DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)))\r
+ {\r
//\r
// If Device is USB device\r
//\r
return TRUE;\r
}\r
+\r
if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
- (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
+ (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP))\r
+ {\r
//\r
// If Device is PCCard\r
//\r
\r
return FALSE;\r
}\r
-\r