]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
MdeModulePkg/TerminalDxe: Separate state machine start/stop logic
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
index 6fde3b2c7aa9c337c8b560bfd753c31386671fe1..b8dcf0c472bd2670d1f5d8a4e51618833418558d 100644 (file)
@@ -2,7 +2,7 @@
   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 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -29,7 +29,7 @@ EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {
 };\r
 \r
 \r
-EFI_GUID  *gTerminalType[] = {\r
+EFI_GUID  *mTerminalType[] = {\r
   &gEfiPcAnsiGuid,\r
   &gEfiVT100Guid,\r
   &gEfiVT100PlusGuid,\r
@@ -38,6 +38,14 @@ EFI_GUID  *gTerminalType[] = {
 };\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
@@ -75,6 +83,7 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   NULL, // RawFifo\r
   NULL, // UnicodeFiFo\r
   NULL, // EfiKeyFiFo\r
+  NULL, // EfiKeyFiFoForNotify\r
 \r
   NULL, // ControllerNameTable\r
   NULL, // TimerEvent\r
@@ -99,16 +108,41 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   {   // 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
@@ -161,12 +195,7 @@ TerminalDriverBindingSupported (
       //\r
       // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types\r
       //\r
-      if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-\r
+      if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {\r
         return EFI_UNSUPPORTED;\r
       }\r
     }\r
@@ -253,7 +282,7 @@ BuildTerminalDevpath  (
   )\r
 {\r
   EFI_DEVICE_PATH_PROTOCOL          *TerminalDevicePath;\r
-  UINT8                             TerminalType;\r
+  TERMINAL_TYPE                     TerminalType;\r
   VENDOR_DEVICE_PATH                *Node;\r
   EFI_STATUS                        Status;\r
 \r
@@ -268,23 +297,23 @@ BuildTerminalDevpath  (
 \r
   } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
 \r
-    TerminalType = PCANSITYPE;\r
+    TerminalType = TerminalTypePcAnsi;\r
 \r
   } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
 \r
-    TerminalType = VT100TYPE;\r
+    TerminalType = TerminalTypeVt100;\r
 \r
   } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
 \r
-    TerminalType = VT100PLUSTYPE;\r
+    TerminalType = TerminalTypeVt100Plus;\r
 \r
   } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
 \r
-    TerminalType = VTUTF8TYPE;\r
+    TerminalType = TerminalTypeVtUtf8;\r
 \r
   } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
 \r
-    TerminalType = TTYTERMTYPE;\r
+    TerminalType = TerminalTypeTtyTerm;\r
 \r
   } else {\r
     return NULL;\r
@@ -423,97 +452,141 @@ TerminalFreeNotifyList (
   It returns information for available text modes that the terminal can support.\r
 \r
   @param[out] TextModeCount      The total number of text modes that terminal console supports.\r
-  @param[out] TextModeData       The buffer to the text modes column and row information.\r
-                                 Caller is responsible to free it when it's non-NULL.\r
 \r
-  @retval EFI_SUCCESS            The supporting mode information is returned.\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
+  @return   The buffer to the text modes column and row information.\r
+            Caller is responsible to free it when it's non-NULL.\r
 \r
 **/\r
-EFI_STATUS\r
+TERMINAL_CONSOLE_MODE_DATA *\r
 InitializeTerminalConsoleTextMode (\r
-  OUT UINTN                         *TextModeCount,\r
-  OUT TERMINAL_CONSOLE_MODE_DATA    **TextModeData\r
-  )\r
+  OUT INT32                         *TextModeCount\r
+)\r
 {\r
-  UINTN                       Index;\r
-  UINTN                       Count;\r
-  TERMINAL_CONSOLE_MODE_DATA  *ModeBuffer;\r
-  TERMINAL_CONSOLE_MODE_DATA  *NewModeBuffer;\r
-  UINTN                       ValidCount;\r
-  UINTN                       ValidIndex;\r
-  \r
-  if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  \r
-  Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
-  \r
-  //\r
-  // Get defined mode buffer pointer.\r
-  //\r
-  ModeBuffer = mTerminalConsoleModeData;\r
-    \r
+  TERMINAL_CONSOLE_MODE_DATA  *TextModeData;\r
+\r
+  ASSERT (TextModeCount != NULL);\r
+\r
   //\r
   // Here we make sure that the final mode exposed does not include the duplicated modes,\r
   // and does not include the invalid modes which exceed the max column and row.\r
   // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
   //\r
-  NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
-  ASSERT (NewModeBuffer != NULL);\r
+  TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);\r
+  if (TextModeData == NULL) {\r
+    return NULL;\r
+  }\r
+  *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);\r
 \r
-  //\r
-  // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
-  //\r
-  ValidCount = 0;  \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
-  NewModeBuffer[ValidCount].Columns = 80;\r
-  NewModeBuffer[ValidCount].Rows    = 25;\r
-  ValidCount++;\r
+/**\r
+  Stop the terminal state machine.\r
 \r
-  NewModeBuffer[ValidCount].Columns = 80;\r
-  NewModeBuffer[ValidCount].Rows    = 50;\r
-  ValidCount++;\r
-  \r
-  //\r
-  // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
-  //\r
-  for (Index = 0; Index < Count; Index++) {\r
-    if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
-      //\r
-      // Skip the pre-defined mode which is invalid.\r
-      //\r
-      continue;\r
-    }\r
-    for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
-      if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
-          (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
-        //\r
-        // Skip the duplicated mode.\r
-        //\r
-        break;\r
-      }\r
-    }\r
-    if (ValidIndex == ValidCount) {\r
-      NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
-      NewModeBuffer[ValidCount].Rows    = ModeBuffer[Index].Rows;\r
-      ValidCount++;\r
+  @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
\r
-  DEBUG_CODE (\r
-    for (Index = 0; Index < ValidCount; Index++) {\r
-      DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
-                           Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows));  \r
-    }\r
-  );\r
-  \r
-  //\r
-  // Return valid mode count and mode information buffer.\r
-  //\r
-  *TextModeCount = ValidCount;\r
-  *TextModeData  = NewModeBuffer;\r
-  return EFI_SUCCESS;\r
+  if (!EFI_ERROR (Status)) {\r
+    *ControllerNameTable = Table;\r
+  }\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -547,7 +620,7 @@ TerminalDriverBindingStart (
   EFI_SERIAL_IO_MODE                  *Mode;\r
   UINTN                               SerialInTimeOut;\r
   TERMINAL_DEV                        *TerminalDevice;\r
-  UINT8                               TerminalType;\r
+  TERMINAL_TYPE                       TerminalType;\r
   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
   UINTN                               EntryCount;\r
   UINTN                               Index;\r
@@ -560,7 +633,6 @@ TerminalDriverBindingStart (
   BOOLEAN                             SimTxtInInstalled;\r
   BOOLEAN                             SimTxtOutInstalled;\r
   BOOLEAN                             FirstEnter;\r
-  UINTN                               ModeCount;\r
 \r
   TerminalDevice     = NULL;\r
   ConInSelected      = FALSE;\r
@@ -678,7 +750,7 @@ TerminalDriverBindingStart (
   //\r
   if (FirstEnter) {\r
     //\r
-    // First enther the start funciton\r
+    // First enther the start function\r
     //\r
     FirstEnter = FALSE;\r
     //\r
@@ -710,29 +782,13 @@ TerminalDriverBindingStart (
     //\r
     if (RemainingDevicePath == NULL) {\r
       TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
-      //\r
-      // Must be between PCANSITYPE (0) and TTYTERMTYPE (4)\r
-      //\r
-      ASSERT (TerminalType <= TTYTERMTYPE);\r
     } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
       //\r
       // If RemainingDevicePath isn't the End of Device Path Node,\r
       // Use the RemainingDevicePath to determine the terminal type\r
       //\r
       Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
-      if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
-        TerminalType = 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 if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-        TerminalType = TTYTERMTYPE;\r
-      } else {\r
-        goto Error;\r
-      }\r
+      TerminalType = TerminalTypeFromGuid (&Node->Guid);\r
     } else {\r
       //\r
       // If RemainingDevicePath is the End of Device Path Node,\r
@@ -741,6 +797,8 @@ TerminalDriverBindingStart (
       return EFI_SUCCESS;\r
     }\r
 \r
+    ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
+\r
     //\r
     // Initialize the Terminal Dev\r
     //\r
@@ -791,6 +849,10 @@ TerminalDriverBindingStart (
     if (TerminalDevice->EfiKeyFiFo == NULL) {\r
       goto Error;\r
     }\r
+    TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+    if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
+      goto Error;\r
+    }\r
 \r
     //\r
     // Set the timeout value of serial buffer for\r
@@ -834,12 +896,13 @@ TerminalDriverBindingStart (
                          );\r
     SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
     \r
-    Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
-    if (EFI_ERROR (Status)) {\r
+    TerminalDevice->TerminalConsoleModeData = InitializeTerminalConsoleTextMode (\r
+                                                &SimpleTextOutput->Mode->MaxMode\r
+                                                );\r
+    if (TerminalDevice->TerminalConsoleModeData == NULL) {\r
       goto ReportError;\r
     }\r
-    TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
-    \r
+\r
     //\r
     // For terminal devices, cursor is always visible\r
     //\r
@@ -855,97 +918,9 @@ TerminalDriverBindingStart (
     //\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
-    case TTYTERMTYPE:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"Tty Terminal Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"Tty Terminal Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
+    Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
     }\r
 \r
     //\r
@@ -975,28 +950,14 @@ TerminalDriverBindingStart (
       goto ReportError;\r
     }\r
 \r
-    Status = gBS->CreateEvent (\r
-                    EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                    TPL_NOTIFY,\r
-                    TerminalConInTimerHandler,\r
-                    TerminalDevice,\r
-                    &TerminalDevice->TimerEvent\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
-\r
-    Status = gBS->SetTimer (\r
-                    TerminalDevice->TimerEvent,\r
-                    TimerPeriodic,\r
-                    KEYBOARD_TIMER_INTERVAL\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
+    StartTerminalStateMachine (TerminalDevice);\r
 \r
     Status = gBS->CreateEvent (\r
-                    EVT_TIMER,\r
+                    EVT_NOTIFY_SIGNAL,\r
                     TPL_CALLBACK,\r
-                    NULL,\r
-                    NULL,\r
-                    &TerminalDevice->TwoSecondTimeOut\r
+                    KeyNotifyProcessHandler,\r
+                    TerminalDevice,\r
+                    &TerminalDevice->KeyNotifyProcessEvent\r
                     );\r
     ASSERT_EFI_ERROR (Status);\r
 \r
@@ -1222,7 +1183,10 @@ Error:
       if (TerminalDevice->EfiKeyFiFo != NULL) {\r
         FreePool (TerminalDevice->EfiKeyFiFo);\r
       }\r
-\r
+      if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {\r
+        FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
+      }\r
+  \r
       if (TerminalDevice->ControllerNameTable != NULL) {\r
         FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
       }\r
@@ -1396,10 +1360,10 @@ TerminalDriverBindingStop (
           FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
         }\r
 \r
-        gBS->CloseEvent (TerminalDevice->TimerEvent);\r
-        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
+        StopTerminalStateMachine (TerminalDevice);\r
         gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
         gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+        gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
         TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
         FreePool (TerminalDevice->DevicePath);\r
         if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
@@ -1437,7 +1401,7 @@ TerminalUpdateConsoleDevVariable (
   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
@@ -1454,7 +1418,7 @@ TerminalUpdateConsoleDevVariable (
   //\r
   // Append terminal device path onto the variable.\r
   //\r
-  for (TerminalType = PCANSITYPE; TerminalType <= TTYTERMTYPE; TerminalType++) {\r
+  for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
     SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
     NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
     ASSERT (NewVariable != NULL);\r
@@ -1529,7 +1493,7 @@ TerminalRemoveConsoleDevVariable (
   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
@@ -1567,7 +1531,7 @@ TerminalRemoveConsoleDevVariable (
     // Loop through all the terminal types that this driver supports\r
     //\r
     Match = FALSE;\r
-    for (TerminalType = PCANSITYPE; TerminalType <= TTYTERMTYPE; TerminalType++) {\r
+    for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
 \r
       SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
 \r
@@ -1639,53 +1603,18 @@ TerminalRemoveConsoleDevVariable (
 **/\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
-  case TTYTERMTYPE:\r
-    CopyGuid (&Node.Guid, &gEfiTtyTermGuid);\r
-    break;\r
-\r
-  default:\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  //\r
-  // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
-  //\r
-  SetDevicePathNodeLength (\r
-    &Node.Header,\r
-    sizeof (VENDOR_DEVICE_PATH)\r
-    );\r
+  SetDevicePathNodeLength (&Node, sizeof (VENDOR_DEVICE_PATH));\r
+  CopyGuid (&Node.Guid, mTerminalType[TerminalType]);\r
 \r
   //\r
   // Append the terminal node onto parent device path\r