/** @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
+Copyright (c) 2006 - 2018, 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
#include "Terminal.h"\r
\r
-STATIC\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\r
- );\r
-\r
//\r
// Globals\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
-TERMINAL_DEV gTerminalDevTemplate = {\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
0,\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
+ 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
+ return Type;\r
+}\r
+\r
+/**\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
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
\r
+ @retval EFI_SUCCESS This driver supports this device.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
+ @retval other This driver does not support this device.\r
\r
+**/\r
EFI_STATUS\r
EFIAPI\r
TerminalDriverBindingSupported (\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
+ 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
- return EFI_UNSUPPORTED;\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
-EFIAPI\r
-TerminalDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+TerminalFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
)\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
- Routine Description:\r
+/**\r
+ Stop the terminal state machine.\r
\r
- Start the controller.\r
+ @param TerminalDevice The terminal device.\r
+**/\r
+VOID\r
+StopTerminalStateMachine (\r
+ TERMINAL_DEV *TerminalDevice\r
+ )\r
+{\r
+ EFI_TPL OriginalTpl;\r
\r
- Arguments:\r
+ OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
- This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- Controller - The handle of the controller to start.\r
- RemainingDevicePath - A pointer to the remaining portion of a devcie path.\r
+ gBS->CloseEvent (TerminalDevice->TimerEvent);\r
+ gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
\r
- Returns:\r
+ gBS->RestoreTPL (OriginalTpl);\r
+}\r
\r
- EFI_SUCCESS.\r
+/**\r
+ Start the terminal state machine.\r
\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
+ Simple Text In Ex and Simple Text Out protocol, and device path protocol.\r
+ And store Console Device Environment Variables.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to bind driver to\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver is added to Controller.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
+ @retval other This driver does not support this device.\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
+ )\r
{\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
-\r
- TerminalType = FixedPcdGet8 (PcdDefaultTerminalType);\r
- // must be between PcAnsiType (0) and VTUTF8Type (3)\r
- ASSERT (TerminalType <= VTUTF8Type);\r
+ TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
+ if (TerminalDevice == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto CloseProtocols;\r
+ }\r
\r
- CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
- RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL*)DefaultNode;\r
+ if (RemainingDevicePath == NULL) {\r
+ //\r
+ // If RemainingDevicePath is NULL, use default terminal type\r
+ //\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), &gTerminalDevTemplate);\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
+ SimpleTextOutput = &TerminalDevice->SimpleTextOutput;\r
+ SimpleTextInput = &TerminalDevice->SimpleInput;\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
+ // Initialize SimpleTextOut instance\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
-\r
- //\r
- // Build the component name for the child device\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
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to stop driver on\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+ @retval EFI_SUCCESS This driver is removed Controller.\r
+ @retval other This driver could not be removed from this device.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
TerminalDriverBindingStop (\r
IN UINTN NumberOfChildren,\r
IN EFI_HANDLE *ChildHandleBuffer\r
)\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Stop a device controller.\r
-\r
- Arguments:\r
-\r
- This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- Controller - A handle to the device being stopped.\r
- NumberOfChildren - The number of child device handles in ChildHandleBuffer.\r
- ChildHandleBuffer - An array of child handles to be freed.\r
-\r
- Returns:\r
-\r
- EFI_SUCCESS - Operation successful.\r
- EFI_DEVICE_ERROR - Devices error.\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
UINTN Index;\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
-STATIC\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
- ListHead - The list head\r
+/**\r
+ Compare a device path data structure to that of all the nodes of a\r
+ second device path instance.\r
\r
-Returns:\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
- EFI_SUCCESS - Free the notify list successfully\r
- EFI_INVALID_PARAMETER - ListHead is invalid.\r
+ @retval TRUE If the Single is contained within Multi.\r
+ @retval FALSE The Single is not match within Multi.\r
\r
---*/\r
+**/\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
- gBS->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
+ Update terminal device path in Console Device Environment Variables.\r
\r
+ @param VariableName The Console Device Environment Variable.\r
+ @param ParentDevicePath The terminal device path to be updated.\r
\r
+**/\r
VOID\r
TerminalUpdateConsoleDevVariable (\r
IN CHAR16 *VariableName,\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
}\r
\r
+\r
+/**\r
+ Remove terminal device path from Console Device Environment Variables.\r
+\r
+ @param VariableName Console Device Environment Variables.\r
+ @param ParentDevicePath The terminal device path to be updated.\r
+\r
+**/\r
VOID\r
TerminalRemoveConsoleDevVariable (\r
IN CHAR16 *VariableName,\r
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
)\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Remove console device variable.\r
-\r
- Arguments:\r
-\r
- VariableName - A pointer to the variable name.\r
- ParentDevicePath - A pointer to the parent device path.\r
-\r
- Returns:\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
BOOLEAN FoundOne;\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
-VOID *\r
-TerminalGetVariableAndSize (\r
- IN CHAR16 *Name,\r
- IN EFI_GUID *VendorGuid,\r
- OUT UINTN *VariableSize\r
- )\r
-/*++\r
-\r
-Routine Description:\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
-Arguments:\r
- Name - String part of EFI variable name\r
-\r
- VendorGuid - GUID part of EFI variable name\r
-\r
- VariableSize - Returns the size of the EFI variable that was read\r
-\r
-Returns:\r
- Dynamically allocated memory that contains a copy of the EFI variable.\r
- Caller is repsoncible freeing the buffer.\r
-\r
- NULL - Variable was not read\r
-\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
+ Build terminal device path according to terminal type.\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
+ @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
+ @param ParentDevicePath Parent device path.\r
+ @param TerminalDevicePath Returned terminal device path, if building successfully.\r
\r
- *VariableSize = BufferSize;\r
- return Buffer;\r
-}\r
+ @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
+ @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.\r
+ @retval EFI_SUCCESS Build terminal device path successfully.\r
\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
+ SetDevicePathNodeLength (&Node.Header, sizeof (VENDOR_DEVICE_PATH));\r
+ CopyGuid (&Node.Guid, mTerminalType[TerminalType]);\r
\r
//\r
- // generate terminal device path node according to terminal type.\r
- //\r
- switch (TerminalType) {\r
-\r
- case PcAnsiType:\r
- CopyMem (\r
- &Node.Guid,\r
- &gEfiPcAnsiGuid,\r
- sizeof (EFI_GUID)\r
- );\r
- break;\r
-\r
- case VT100Type:\r
- CopyMem (\r
- &Node.Guid,\r
- &gEfiVT100Guid,\r
- sizeof (EFI_GUID)\r
- );\r
- break;\r
-\r
- case VT100PlusType:\r
- CopyMem (\r
- &Node.Guid,\r
- &gEfiVT100PlusGuid,\r
- sizeof (EFI_GUID)\r
- );\r
- break;\r
-\r
- case VTUTF8Type:\r
- CopyMem (\r
- &Node.Guid,\r
- &gEfiVTUTF8Guid,\r
- sizeof (EFI_GUID)\r
- );\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- break;\r
- }\r
-\r
- SetDevicePathNodeLength (\r
- &Node.Header,\r
- sizeof (VENDOR_DEVICE_PATH)\r
- );\r
- //\r
- // append the terminal node onto parent device path\r
+ // Append the terminal node onto parent device path\r
// to generate a complete terminal device path.\r
//\r
*TerminalDevicePath = AppendDevicePathNode (\r
return EFI_SUCCESS;\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
-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
-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
- @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
- @param[in] SystemTable A pointer to the EFI System Table.\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval other Some error occurs when executing this entry point.\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