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 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
};\r
\r
TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
+ {80, 25},\r
+ {80, 50},\r
{100, 31},\r
//\r
// New modes can be added here.\r
return Status;\r
}\r
\r
-/**\r
- Build the terminal device path for the child device according to the\r
- terminal type.\r
-\r
- @param ParentDevicePath Parent device path.\r
- @param RemainingDevicePath A specific child device.\r
-\r
- @return The child device path built.\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
- )\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
-\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
- }\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
- }\r
- return TerminalDevicePath;\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
- Check whether the terminal device path is in the global variable.\r
-\r
- @param VariableName Pointer to one global variable.\r
- @param TerminalDevicePath Pointer to the terminal device's device path.\r
-\r
- @retval TRUE The devcie is in the global variable.\r
- @retval FALSE The devcie is not in the global variable.\r
-\r
-**/\r
-BOOLEAN\r
-IsTerminalInConsoleVariable (\r
- IN CHAR16 *VariableName,\r
- IN EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *Variable;\r
- BOOLEAN ReturnFlag;\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
-\r
- //\r
- // Check whether the terminal device path is one of the variable instances.\r
- //\r
- ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
-\r
- FreePool (Variable);\r
-\r
- return ReturnFlag;\r
-}\r
\r
/**\r
Free notify functions list.\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
\r
- @retval EFI_SUCCESS The supporting mode information is returned.\r
- @retval EFI_INVALID_PARAMETER The parameters are invalid.\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
-EFI_STATUS\r
+TERMINAL_CONSOLE_MODE_DATA *\r
InitializeTerminalConsoleTextMode (\r
- OUT UINTN *TextModeCount,\r
- OUT TERMINAL_CONSOLE_MODE_DATA **TextModeData\r
- )\r
+ OUT INT32 *TextModeCount\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
- }\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
+ TERMINAL_CONSOLE_MODE_DATA *TextModeData;\r
\r
- NewModeBuffer[ValidCount].Columns = 80;\r
- NewModeBuffer[ValidCount].Rows = 25;\r
- ValidCount++;\r
+ ASSERT (TextModeCount != NULL);\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
+ TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);\r
+ if (TextModeData == NULL) {\r
+ return NULL;\r
}\r
- \r
+ *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);\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
+ INT32 Index;\r
+ for (Index = 0; Index < *TextModeCount; Index++) {\r
+ DEBUG ((DEBUG_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n",\r
+ Index, TextModeData[Index].Columns, TextModeData[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
+ return TextModeData;\r
+}\r
+\r
+/**\r
+ Stop the terminal state machine.\r
+\r
+ @param TerminalDevice The terminal device.\r
+**/\r
+VOID\r
+StopTerminalStateMachine (\r
+ TERMINAL_DEV *TerminalDevice\r
+ )\r
+{\r
+ EFI_TPL OriginalTpl;\r
+\r
+ OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ gBS->CloseEvent (TerminalDevice->TimerEvent);\r
+ gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
+\r
+ gBS->RestoreTPL (OriginalTpl);\r
+}\r
+\r
+/**\r
+ Start the terminal state machine.\r
+\r
+ @param TerminalDevice The terminal device.\r
+**/\r
+VOID\r
+StartTerminalStateMachine (\r
+ TERMINAL_DEV *TerminalDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\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
+ Status = gBS->SetTimer (\r
+ TerminalDevice->TimerEvent,\r
+ TimerPeriodic,\r
+ KEYBOARD_TIMER_INTERVAL\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
\r
/**\r
EFI_STATUS Status;\r
EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- VENDOR_DEVICE_PATH *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *Vendor;\r
+ EFI_HANDLE SerialIoHandle;\r
EFI_SERIAL_IO_MODE *Mode;\r
UINTN SerialInTimeOut;\r
TERMINAL_DEV *TerminalDevice;\r
- TERMINAL_TYPE TerminalType;\r
+ UINT8 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_UNICODE_STRING_TABLE *ControllerNameTable;\r
+\r
//\r
// Get the Device Path Protocol to build the device path of the child device\r
//\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
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
+\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
+ break;\r
}\r
}\r
-\r
FreePool (OpenInfoBuffer);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
}\r
+ return Status;\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 CloseProtocols;\r
+ }\r
\r
+ if (RemainingDevicePath == NULL) {\r
//\r
// If RemainingDevicePath is NULL, use default terminal type\r
//\r
- if (RemainingDevicePath == NULL) {\r
- TerminalType = PcdGet8 (PcdDefaultTerminalType);\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
- TerminalType = TerminalTypeFromGuid (&Node->Guid);\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
- ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
-\r
+ TerminalDevice->TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
+ } else {\r
//\r
- // Initialize the Terminal Dev\r
+ // End of Device Path Node is handled in above.\r
//\r
- TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
- if (TerminalDevice == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
+ ASSERT (!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
+ TerminalDevice->TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid);\r
+ }\r
+ ASSERT (TerminalDevice->TerminalType < ARRAY_SIZE (mTerminalType));\r
+ TerminalDevice->SerialIo = SerialIo;\r
\r
- TerminalDevice->TerminalType = TerminalType;\r
- TerminalDevice->SerialIo = SerialIo;\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
- 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
+ // 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_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
+ 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
- //\r
- // Set the timeout value of serial buffer for\r
- // keystroke response performance issue\r
- //\r
- Mode = TerminalDevice->SerialIo->Mode;\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
- SerialInTimeOut = 0;\r
- if (Mode->BaudRate != 0) {\r
- SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\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
- //\r
- // For terminal devices, cursor is always visible\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
- //\r
- // Build the component name for the child device\r
- //\r
- Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // Build the device path for the child device\r
- //\r
- Status = SetTerminalDevicePath (\r
- TerminalDevice->TerminalType,\r
- ParentDevicePath,\r
- &TerminalDevice->DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
-\r
- Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\r
- }\r
-\r
- Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- goto ReportError;\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
-\r
- Status = gBS->SetTimer (\r
- TerminalDevice->TimerEvent,\r
- TimerPeriodic,\r
- KEYBOARD_TIMER_INTERVAL\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
- 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->InstallProtocolInterface (\r
- &TerminalDevice->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- TerminalDevice->DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\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
- }\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
+ TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
+ if (TerminalDevice->UnicodeFiFo == NULL) {\r
+ goto FreeResources;\r
+ }\r
+ TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+ if (TerminalDevice->EfiKeyFiFo == NULL) {\r
+ goto FreeResources;\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
-\r
- Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
- &TerminalDevice->SimpleTextOutput,\r
- TRUE\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
+ 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, &TerminalDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid, &TerminalDevice->SimpleInputEx,\r
+ &gEfiSimpleTextOutProtocolGuid, &TerminalDevice->SimpleTextOutput,\r
+ &gEfiDevicePathProtocolGuid, 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
-\r
- if (TerminalDevice->Handle != NULL) {\r
- This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
- } else {\r
-\r
- if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
- gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
- }\r
+FreeResources:\r
+ ASSERT (TerminalDevice != NULL);\r
\r
- if (TerminalDevice->TimerEvent != NULL) {\r
- gBS->CloseEvent (TerminalDevice->TimerEvent);\r
- }\r
+ if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
+ gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
+ }\r
+ if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+ gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\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
+ 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->SimpleInputEx.WaitForKeyEx != NULL) {\r
- gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
- }\r
+ if (TerminalDevice->ControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+ }\r
\r
- TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
+ if (TerminalDevice->DevicePath != NULL) {\r
+ FreePool (TerminalDevice->DevicePath);\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->TerminalConsoleModeData != NULL) {\r
+ FreePool (TerminalDevice->TerminalConsoleModeData);\r
+ }\r
\r
- if (TerminalDevice->DevicePath != NULL) {\r
- FreePool (TerminalDevice->DevicePath);\r
- }\r
+ FreePool (TerminalDevice);\r
\r
- if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
- FreePool (TerminalDevice->TerminalConsoleModeData);\r
- }\r
+CloseProtocols:\r
\r
- FreePool (TerminalDevice);\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
- This->Stop (This, Controller, 0, NULL);\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
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
+ &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
);\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
//\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
+ if (EFI_ERROR (Status)) {\r
return;\r
}\r
\r
//\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
+ Variable = NewVariable;\r
+ }\r
+ }\r
+\r
FreePool (TempDevicePath);\r
}\r
\r
- Variable = NewVariable;\r
}\r
\r
VariableSize = GetDevicePathSize (Variable);\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