/** @file\r
- Produces Simple Text Input Protocl, Simple Text Input Extended Protocol and\r
+ 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 - 2008, Intel Corporation. <BR>\r
-All rights reserved. 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
\r
-EFI_GUID *gTerminalType[] = {\r
+EFI_GUID *mTerminalType[] = {\r
&gEfiPcAnsiGuid,\r
&gEfiVT100Guid,\r
&gEfiVT100PlusGuid,\r
- &gEfiVTUTF8Guid\r
+ &gEfiVTUTF8Guid,\r
+ &gEfiTtyTermGuid\r
};\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
+};\r
+\r
TERMINAL_DEV mTerminalDevTemplate = {\r
TERMINAL_DEV_SIGNATURE,\r
NULL,\r
},\r
{ // SimpleTextOutputMode\r
1, // MaxMode\r
- 0, // Mode?\r
+ 0, // Mode\r
EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
0, // CursorColumn\r
0, // CursorRow\r
TRUE // CursorVisible\r
},\r
- 0,\r
- {\r
- 0,\r
- 0,\r
- { 0 }\r
- },\r
- {\r
- 0,\r
- 0,\r
- { 0 }\r
- },\r
- {\r
- 0,\r
- 0,\r
- { {0} }\r
- },\r
+ NULL, // TerminalConsoleModeData\r
+ 0, // SerialInTimeOut\r
+\r
+ NULL, // RawFifo\r
+ NULL, // UnicodeFiFo\r
+ NULL, // EfiKeyFiFo\r
+ NULL, // EfiKeyFiFoForNotify\r
+\r
NULL, // ControllerNameTable\r
- NULL,\r
+ NULL, // TimerEvent\r
+ NULL, // TwoSecondTimeOut\r
INPUT_STATE_DEFAULT,\r
RESET_STATE_DEFAULT,\r
+ {\r
+ 0,\r
+ 0,\r
+ 0\r
+ },\r
+ 0,\r
FALSE,\r
{ // SimpleTextInputEx\r
TerminalConInResetEx,\r
TerminalConInRegisterKeyNotify,\r
TerminalConInUnregisterKeyNotify,\r
},\r
- {\r
+ { // NotifyList\r
NULL,\r
NULL,\r
- }\r
+ },\r
+ NULL // KeyNotifyProcessEvent\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
+ //\r
+};\r
\r
/**\r
- Free notify functions list.\r
-\r
- @param ListHead The list head\r
+ Convert the GUID representation of terminal type to enum type.\r
\r
- @retval EFI_SUCCESS Free the notify list successfully.\r
- @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
+ @param Guid The GUID representation of terminal type.\r
\r
+ @return The terminal type in enum type.\r
**/\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\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
+ return Type;\r
+}\r
\r
/**\r
- Test to see if this driver supports Controller. \r
+ Test to see if this driver supports Controller.\r
\r
@param This Protocol instance pointer.\r
@param Controller Handle of device to test\r
// device path that describes a terminal communications protocol.\r
//\r
if (RemainingDevicePath != NULL) {\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
-\r
- return EFI_UNSUPPORTED;\r
-\r
- }\r
//\r
- // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types\r
+ // Check if RemainingDevicePath is the End of Device Path Node,\r
+ // if yes, go on checking other conditions\r
//\r
- if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
- !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
- !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
- !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
+ if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+ //\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
+ // check its validation\r
+ //\r
+ Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
\r
- return EFI_UNSUPPORTED;\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
+ // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types\r
+ //\r
+ if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {\r
+ return EFI_UNSUPPORTED;\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
+ // This driver is a bus driver with at most 1 child device, so it is\r
+ // ok for it to be already started.\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &SerialIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
return Status;\r
}\r
\r
+ //\r
+ // Close the I/O Abstraction(s) used to perform the supported test\r
+ //\r
gBS->CloseProtocol (\r
Controller,\r
- &gEfiDevicePathProtocolGuid,\r
+ &gEfiSerialIoProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
\r
//\r
- // The Controller must support the Serial I/O Protocol.\r
- // This driver is a bus driver with at most 1 child device, so it is\r
- // ok for it to be already started.\r
+ // Open the EFI Device Path protocol needed to perform the supported test\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- (VOID **) &SerialIo,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ParentDevicePath,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
//\r
- // Close the I/O Abstraction(s) used to perform the supported test\r
+ // Close protocol, don't use device path protocol in the Support() function\r
//\r
gBS->CloseProtocol (\r
Controller,\r
- &gEfiSerialIoProtocolGuid,\r
+ &gEfiDevicePathProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
return Status;\r
}\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
+\r
+**/\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ )\r
+{\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\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
+\r
+ return EFI_SUCCESS;\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
+\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
+TERMINAL_CONSOLE_MODE_DATA *\r
+InitializeTerminalConsoleTextMode (\r
+ OUT INT32 *TextModeCount\r
+)\r
+{\r
+ TERMINAL_CONSOLE_MODE_DATA *TextModeData;\r
+\r
+ ASSERT (TextModeCount != NULL);\r
+\r
+ TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);\r
+ if (TextModeData == NULL) {\r
+ return NULL;\r
+ }\r
+ *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);\r
+\r
+ DEBUG_CODE (\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
+ 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
+ Initialize the controller name table.\r
+\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
+InitializeControllerNameTable (\r
+ TERMINAL_TYPE TerminalType,\r
+ EFI_UNICODE_STRING_TABLE **ControllerNameTable\r
+)\r
+{\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
+ if (!EFI_ERROR (Status)) {\r
+ *ControllerNameTable = Table;\r
+ }\r
+ return Status;\r
+}\r
+\r
/**\r
Start this driver on Controller by opening a Serial IO protocol,\r
reading Device Path, and creating a child handle with a Simple Text In,\r
EFI_STATUS Status;\r
EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- VENDOR_DEVICE_PATH *Node;\r
- VENDOR_DEVICE_PATH *DefaultNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *Vendor;\r
+ EFI_HANDLE SerialIoHandle;\r
EFI_SERIAL_IO_MODE *Mode;\r
UINTN SerialInTimeOut;\r
TERMINAL_DEV *TerminalDevice;\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
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;\r
\r
- TerminalDevice = NULL;\r
- DefaultNode = NULL;\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
- // If 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
+ // if the serial device is a hot plug device, do not update the\r
+ // ConInDev, ConOutDev, and StdErrDev variables.\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
- //\r
- // if the serial device is a hot plug device, do not update the\r
- // ConInDev, ConOutDev, and StdErrDev variables.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
- TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
- TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
- }\r
- }\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
- // Make sure a child handle does not already exist. This driver can only\r
- // produce one child per serial port.\r
+ // Do not create any child for END remaining device path.\r
//\r
- Status = gBS->OpenProtocolInformation (\r
- Controller,\r
- &gEfiSerialIoProtocolGuid,\r
- &OpenInfoBuffer,\r
- &EntryCount\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = EFI_SUCCESS;\r
- for (Index = 0; Index < EntryCount; Index++) {\r
- if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {\r
- Status = EFI_ALREADY_STARTED;\r
- }\r
+ if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+\r
+ if (RemainingDevicePath == NULL) {\r
+ //\r
+ // If RemainingDevicePath is NULL or is the End of Device Path Node\r
+ //\r
+ return EFI_SUCCESS;\r
}\r
\r
- FreePool (OpenInfoBuffer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ //\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
+ &gEfiSerialIoProtocolGuid,\r
+ &OpenInfoBuffer,\r
+ &EntryCount\r
+ );\r
+ if (!EFI_ERROR (Status)) {\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 = 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
+ FreePool (OpenInfoBuffer);\r
}\r
+ return Status;\r
}\r
+\r
//\r
- // If RemainingDevicePath is NULL, then create default device path node\r
+ // Initialize the Terminal Dev\r
//\r
- if (RemainingDevicePath == NULL) {\r
- DefaultNode = AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH));\r
- if (DefaultNode == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
+ TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
+ if (TerminalDevice == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto CloseProtocols;\r
+ }\r
\r
- TerminalType = FixedPcdGet8 (PcdDefaultTerminalType);\r
+ if (RemainingDevicePath == NULL) {\r
//\r
- // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)\r
+ // If RemainingDevicePath is NULL, use default terminal type\r
//\r
- ASSERT (TerminalType <= VTUTF8TYPE);\r
-\r
- CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
- RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DefaultNode;\r
+ TerminalDevice->TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
} else {\r
//\r
+ // End of Device Path Node is handled in above.\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
- Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
- if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
- TerminalType = PCANSITYPE;\r
- } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
- TerminalType = VT100TYPE;\r
- } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
- TerminalType = VT100PLUSTYPE;\r
- } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
- TerminalType = VTUTF8TYPE;\r
- } else {\r
- goto Error;\r
- }\r
+ TerminalDevice->TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid);\r
}\r
+ ASSERT (TerminalDevice->TerminalType < ARRAY_SIZE (mTerminalType));\r
+ TerminalDevice->SerialIo = SerialIo;\r
\r
//\r
- // Initialize the Terminal Dev\r
+ // Build the component name for the child device\r
//\r
- TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
- if (TerminalDevice == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
+ Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeResources;\r
}\r
\r
- TerminalDevice->TerminalType = TerminalType;\r
- TerminalDevice->SerialIo = SerialIo;\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
InitializeListHead (&TerminalDevice->NotifyList);\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_WAIT,\r
TPL_NOTIFY,\r
TerminalConInWaitForKeyEx,\r
- &TerminalDevice->SimpleInputEx,\r
+ TerminalDevice,\r
&TerminalDevice->SimpleInputEx.WaitForKeyEx\r
);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
+ ASSERT_EFI_ERROR (Status);\r
\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_WAIT,\r
TPL_NOTIFY,\r
TerminalConInWaitForKey,\r
- &TerminalDevice->SimpleInput,\r
+ TerminalDevice,\r
&TerminalDevice->SimpleInput.WaitForKey\r
);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\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
//\r
- // initialize the FIFO buffer used for accommodating\r
- // the pre-read pending characters\r
+ // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
+ // the pre-read pending characters.\r
//\r
- InitializeRawFiFo (TerminalDevice);\r
- InitializeUnicodeFiFo (TerminalDevice);\r
- InitializeEfiKeyFiFo (TerminalDevice);\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
- // Set the timeout value of serial buffer for\r
- // keystroke response performance issue\r
+ // Set the timeout value of serial buffer for keystroke response performance issue\r
//\r
- Mode = TerminalDevice->SerialIo->Mode;\r
+ Mode = TerminalDevice->SerialIo->Mode;\r
\r
SerialInTimeOut = 0;\r
if (Mode->BaudRate != 0) {\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
+ 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
} else {\r
TerminalDevice->SerialInTimeOut = SerialInTimeOut;\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
- DevicePath = TerminalDevice->DevicePath;\r
-\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
- //\r
- // Simple Text Output Protocol\r
- //\r
- TerminalDevice->SimpleTextOutput.Reset = TerminalConOutReset;\r
- TerminalDevice->SimpleTextOutput.OutputString = TerminalConOutOutputString;\r
- TerminalDevice->SimpleTextOutput.TestString = TerminalConOutTestString;\r
- TerminalDevice->SimpleTextOutput.QueryMode = TerminalConOutQueryMode;\r
- TerminalDevice->SimpleTextOutput.SetMode = TerminalConOutSetMode;\r
- TerminalDevice->SimpleTextOutput.SetAttribute = TerminalConOutSetAttribute;\r
- TerminalDevice->SimpleTextOutput.ClearScreen = TerminalConOutClearScreen;\r
- TerminalDevice->SimpleTextOutput.SetCursorPosition = TerminalConOutSetCursorPosition;\r
- TerminalDevice->SimpleTextOutput.EnableCursor = TerminalConOutEnableCursor;\r
- TerminalDevice->SimpleTextOutput.Mode = &TerminalDevice->SimpleTextOutputMode;\r
-\r
- TerminalDevice->SimpleTextOutputMode.MaxMode = 3;\r
- //\r
- // For terminal devices, cursor is always visible\r
- //\r
- TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\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
\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER,\r
- TPL_CALLBACK,\r
- NULL,\r
- NULL,\r
- &TerminalDevice->TwoSecondTimeOut\r
- );\r
+ SimpleTextOutput = &TerminalDevice->SimpleTextOutput;\r
+ SimpleTextInput = &TerminalDevice->SimpleInput;\r
\r
//\r
- // Build the component name for the child device\r
+ // Initialize SimpleTextOut instance\r
//\r
- TerminalDevice->ControllerNameTable = NULL;\r
- switch (TerminalDevice->TerminalType) {\r
- case PCANSITYPE:\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 VT100TYPE:\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 VT100PLUSTYPE:\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 VTUTF8TYPE:\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
- //\r
- // Install protocol interfaces for the serial device.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &TerminalDevice->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- TerminalDevice->DevicePath,\r
- &gEfiSimpleTextInProtocolGuid,\r
- &TerminalDevice->SimpleInput,\r
- &gEfiSimpleTextInputExProtocolGuid,\r
- &TerminalDevice->SimpleInputEx,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &TerminalDevice->SimpleTextOutput,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\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
- // if the serial device is a hot plug device, attaches the HotPlugGuid\r
- // onto the terminal device handle.\r
+ // For terminal devices, cursor is always visible\r
//\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\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 = gBS->InstallMultipleProtocolInterfaces (\r
- &TerminalDevice->Handle,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
+ Status = SimpleTextOutput->Reset (SimpleTextOutput, FALSE);\r
}\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
+ }\r
+\r
//\r
- // Register the Parent-Child relationship via\r
- // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ // Initialize SimpleTextInput instance\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
+ Status = SimpleTextInput->Reset (SimpleTextInput, FALSE);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ReportError;\r
}\r
\r
- if (DefaultNode != NULL) {\r
- FreePool (DefaultNode);\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
+ 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
REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
- DevicePath\r
+ (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\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
+FreeResources:\r
+ ASSERT (TerminalDevice != NULL);\r
\r
- if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
- gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\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->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
- FreePool (TerminalDevice);\r
- }\r
- }\r
+CloseProtocols:\r
\r
- if (DefaultNode != NULL) {\r
- FreePool (DefaultNode);\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
/**\r
Stop this driver on Controller by closing Simple Text In, Simple Text\r
In Ex, Simple Text Out protocol, and removing parent device path from\r
- Console Device Environment Variables. \r
+ Console Device Environment Variables.\r
\r
@param This Protocol instance pointer.\r
@param Controller Handle of device to stop driver on\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
- Status = gBS->OpenProtocol (\r
- ChildHandleBuffer[Index],\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- ChildHandleBuffer[Index],\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
- } else {\r
- Status = EFI_SUCCESS;\r
- }\r
-\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
+ FreePool (TerminalDevice->TerminalConsoleModeData);\r
FreePool (TerminalDevice);\r
}\r
}\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
- Free notify functions list.\r
+ Compare a device path data structure to that of all the nodes of a\r
+ second device path instance.\r
\r
- @param ListHead The list head\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 EFI_SUCCESS Free the notify list successfully.\r
- @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
+ @retval TRUE If the Single is contained within Multi.\r
+ @retval FALSE The Single is not match within Multi.\r
\r
**/\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\r
+BOOLEAN\r
+MatchDevicePaths (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
)\r
{\r
- TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ UINTN Size;\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
+ 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 EFI_SUCCESS;\r
+ return FALSE;\r
}\r
\r
-\r
/**\r
Update terminal device path in Console Device Environment Variables.\r
\r
@param VariableName The Console Device Environment Variable.\r
- @param ParentDevicePath The terminal devcie path to be updated.\r
-\r
- @return None.\r
+ @param ParentDevicePath The terminal device path to be updated.\r
\r
**/\r
VOID\r
)\r
{\r
EFI_STATUS Status;\r
+ UINTN NameSize;\r
UINTN VariableSize;\r
- UINT8 TerminalType;\r
+ TERMINAL_TYPE TerminalType;\r
EFI_DEVICE_PATH_PROTOCOL *Variable;\r
EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
-\r
- Variable = NULL;\r
+ EDKII_SET_VARIABLE_STATUS *SetVariableStatus;\r
\r
//\r
// Get global variable and its size according to the name given.\r
//\r
- Variable = TerminalGetVariableAndSize (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- &VariableSize\r
- );\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
// Append terminal device path onto the variable.\r
//\r
- for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
+ for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
- NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\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
VariableSize,\r
Variable\r
);\r
- ASSERT_EFI_ERROR (Status);\r
+\r
+ if (EFI_ERROR (Status)) {\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->NameSize = NameSize;\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
+\r
+ REPORT_STATUS_CODE_EX (\r
+ EFI_ERROR_CODE,\r
+ PcdGet32 (PcdErrorCodeSetVariable),\r
+ 0,\r
+ NULL,\r
+ &gEdkiiStatusCodeDataTypeVariableGuid,\r
+ SetVariableStatus,\r
+ sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize\r
+ );\r
+\r
+ FreePool (SetVariableStatus);\r
+ }\r
+ }\r
+\r
FreePool (Variable);\r
\r
return ;\r
Remove terminal device path from Console Device Environment Variables.\r
\r
@param VariableName Console Device Environment Variables.\r
- @param ParentDevicePath The terminal devcie path to be updated.\r
-\r
- @return None.\r
+ @param ParentDevicePath The terminal device path to be updated.\r
\r
**/\r
VOID\r
BOOLEAN Match;\r
UINTN VariableSize;\r
UINTN InstanceSize;\r
- UINT8 TerminalType;\r
+ TERMINAL_TYPE TerminalType;\r
EFI_DEVICE_PATH_PROTOCOL *Instance;\r
EFI_DEVICE_PATH_PROTOCOL *Variable;\r
EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;\r
EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
\r
- Variable = NULL;\r
Instance = NULL;\r
\r
//\r
// Get global variable and its size according to the name given.\r
//\r
- Variable = TerminalGetVariableAndSize (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- &VariableSize\r
- );\r
+ GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
if (Variable == NULL) {\r
return ;\r
}\r
// Loop through all the terminal types that this driver supports\r
//\r
Match = FALSE;\r
- for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
+ for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
\r
SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
\r
//\r
- // Compare the genterated device path to the current device path instance\r
+ // Compare the generated device path to the current device path instance\r
//\r
if (TempDevicePath != NULL) {\r
if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
VariableSize,\r
NewVariable\r
);\r
+ //\r
+ // Shrinking variable with existing variable driver implementation shouldn't fail.\r
+ //\r
ASSERT_EFI_ERROR (Status);\r
}\r
\r
return ;\r
}\r
\r
-\r
-/**\r
- Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
- buffer, and the size of the buffer. On failure return NULL.\r
-\r
- @param Name String part of EFI variable name\r
- @param VendorGuid GUID part of EFI variable name\r
- @param VariableSize Returns the size of the EFI variable that was read\r
-\r
- @return Dynamically allocated memory that contains a copy of the EFI variable.\r
- Caller is repsoncible freeing the buffer. If variable was not read, \r
- NULL regturned.\r
-\r
-**/\r
-VOID *\r
-TerminalGetVariableAndSize (\r
- IN CHAR16 *Name,\r
- IN EFI_GUID *VendorGuid,\r
- OUT UINTN *VariableSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
- VOID *Buffer;\r
-\r
- Buffer = NULL;\r
-\r
- //\r
- // Pass in a small size buffer to find the actual variable size.\r
- //\r
- BufferSize = 1;\r
- Buffer = AllocatePool (BufferSize);\r
- if (Buffer == NULL) {\r
- *VariableSize = 0;\r
- return NULL;\r
- }\r
-\r
- Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
-\r
- if (Status == EFI_SUCCESS) {\r
- *VariableSize = BufferSize;\r
- return Buffer;\r
-\r
- } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
- //\r
- // Allocate the buffer to return\r
- //\r
- FreePool (Buffer);\r
- Buffer = AllocatePool (BufferSize);\r
- if (Buffer == NULL) {\r
- *VariableSize = 0;\r
- return NULL;\r
- }\r
- //\r
- // Read variable into the allocated buffer.\r
- //\r
- Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- BufferSize = 0;\r
- FreePool (Buffer);\r
- Buffer = NULL;\r
- }\r
- } else {\r
- //\r
- // Variable not found or other errors met.\r
- //\r
- BufferSize = 0;\r
- FreePool (Buffer);\r
- Buffer = NULL;\r
- }\r
-\r
- *VariableSize = BufferSize;\r
- return Buffer;\r
-}\r
-\r
/**\r
- Build termial device path according to terminal type.\r
+ Build terminal device path according to terminal type.\r
\r
@param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
- @param ParentDevicePath Parent devcie path.\r
+ @param ParentDevicePath Parent device path.\r
@param TerminalDevicePath Returned terminal device path, if building successfully.\r
\r
@retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
**/\r
EFI_STATUS\r
SetTerminalDevicePath (\r
- IN UINT8 TerminalType,\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 PCANSITYPE:\r
- CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
- break;\r
-\r
- case VT100TYPE:\r
- CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
- break;\r
-\r
- case VT100PLUSTYPE:\r
- CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
- break;\r
-\r
- case VTUTF8TYPE:\r
- CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\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
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Initialize the Raw Data FIFO.\r
-\r
- @param TerminalDevice The terminal device.\r
-\r
- @return None.\r
-\r
-**/\r
-VOID\r
-InitializeRawFiFo (\r
- IN TERMINAL_DEV *TerminalDevice\r
- )\r
-{\r
- //\r
- // Make the raw fifo empty.\r
- //\r
- TerminalDevice->RawFiFo.Head = TerminalDevice->RawFiFo.Tail;\r
-}\r
-\r
-/**\r
- Initialize the Unicode FIFO.\r
-\r
- @param TerminalDevice The terminal device.\r
-\r
- @return None.\r
-\r
-**/\r
-VOID\r
-InitializeUnicodeFiFo (\r
- IN TERMINAL_DEV *TerminalDevice\r
- )\r
-{\r
- //\r
- // Make the unicode fifo empty\r
- //\r
- TerminalDevice->UnicodeFiFo.Head = TerminalDevice->UnicodeFiFo.Tail;\r
-}\r
-\r
-/**\r
- Initialize the EFI Key FIFO.\r
-\r
- @param TerminalDevice The terminal device.\r
-\r
- @return None.\r
-\r
-**/\r
-VOID\r
-InitializeEfiKeyFiFo (\r
- IN TERMINAL_DEV *TerminalDevice\r
- )\r
-{\r
- //\r
- // Make the efi key fifo empty\r
- //\r
- TerminalDevice->EfiKeyFiFo.Head = TerminalDevice->EfiKeyFiFo.Tail;\r
-}\r
-\r
-\r
/**\r
The user Entry Point for module Terminal. The user code starts with this function.\r
\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
-\r
return Status;\r
}\r
+\r
+/**\r
+ Check if the device supports hot-plug through its device path.\r
+\r
+ This function could be updated to check more types of Hot Plug devices.\r
+ Currently, it checks USB and PCCard device.\r
+\r
+ @param DevicePath Pointer to device's device path.\r
+\r
+ @retval TRUE The devcie is a hot-plug device\r
+ @retval FALSE The devcie is not a hot-plug device.\r
+\r
+**/\r
+BOOLEAN\r
+IsHotPlugDevice (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
+\r
+ CheckDevicePath = DevicePath;\r
+ while (!IsDevicePathEnd (CheckDevicePath)) {\r
+ //\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
+ //\r
+ // If Device is USB device\r
+ //\r
+ return TRUE;\r
+ }\r
+ if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
+ (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
+ //\r
+ // If Device is PCCard\r
+ //\r
+ return TRUE;\r
+ }\r
+\r
+ CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r