]> 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 cf7f4e6ebc13a363dcfa2eea1875f138ffae05cc..b8dcf0c472bd2670d1f5d8a4e51618833418558d 100644 (file)
@@ -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
@@ -105,12 +113,36 @@ TERMINAL_DEV  mTerminalDevTemplate = {
 };\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
@@ -163,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
@@ -425,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
@@ -562,7 +633,6 @@ TerminalDriverBindingStart (
   BOOLEAN                             SimTxtInInstalled;\r
   BOOLEAN                             SimTxtOutInstalled;\r
   BOOLEAN                             FirstEnter;\r
-  UINTN                               ModeCount;\r
 \r
   TerminalDevice     = NULL;\r
   ConInSelected      = FALSE;\r
@@ -712,29 +782,13 @@ TerminalDriverBindingStart (
     //\r
     if (RemainingDevicePath == NULL) {\r
       TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
-      //\r
-      // Must be between TerminalTypePcAnsi (0) and TerminalTypeTtyTerm (4)\r
-      //\r
-      ASSERT (TerminalType <= TerminalTypeTtyTerm);\r
     } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
       //\r
       // If RemainingDevicePath isn't the End of Device Path Node,\r
       // Use the RemainingDevicePath to determine the terminal type\r
       //\r
       Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
-      if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
-        TerminalType = TerminalTypePcAnsi;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
-        TerminalType = TerminalTypeVt100;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
-        TerminalType = TerminalTypeVt100Plus;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
-        TerminalType = TerminalTypeVtUtf8;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-        TerminalType = TerminalTypeTtyTerm;\r
-      } else {\r
-        goto Error;\r
-      }\r
+      TerminalType = TerminalTypeFromGuid (&Node->Guid);\r
     } else {\r
       //\r
       // If RemainingDevicePath is the End of Device Path Node,\r
@@ -743,6 +797,8 @@ TerminalDriverBindingStart (
       return EFI_SUCCESS;\r
     }\r
 \r
+    ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
+\r
     //\r
     // Initialize the Terminal Dev\r
     //\r
@@ -840,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
@@ -861,97 +918,9 @@ TerminalDriverBindingStart (
     //\r
     // Build the component name for the child device\r
     //\r
-    TerminalDevice->ControllerNameTable = NULL;\r
-    switch (TerminalDevice->TerminalType) {\r
-    case TerminalTypePcAnsi:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"PC-ANSI Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"PC-ANSI Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case TerminalTypeVt100:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100 Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100 Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case TerminalTypeVt100Plus:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100+ Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100+ Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case TerminalTypeVtUtf8:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-UTF8 Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-UTF8 Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case TerminalTypeTtyTerm:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"Tty Terminal Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"Tty Terminal Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
+    Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
     }\r
 \r
     //\r
@@ -981,30 +950,7 @@ 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
-\r
-    Status = gBS->CreateEvent (\r
-                    EVT_TIMER,\r
-                    TPL_CALLBACK,\r
-                    NULL,\r
-                    NULL,\r
-                    &TerminalDevice->TwoSecondTimeOut\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
+    StartTerminalStateMachine (TerminalDevice);\r
 \r
     Status = gBS->CreateEvent (\r
                     EVT_NOTIFY_SIGNAL,\r
@@ -1414,8 +1360,7 @@ 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
@@ -1473,7 +1418,7 @@ TerminalUpdateConsoleDevVariable (
   //\r
   // Append terminal device path onto the variable.\r
   //\r
-  for (TerminalType = TerminalTypePcAnsi; TerminalType <= TerminalTypeTtyTerm; TerminalType++) {\r
+  for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
     SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
     NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
     ASSERT (NewVariable != NULL);\r
@@ -1586,7 +1531,7 @@ TerminalRemoveConsoleDevVariable (
     // Loop through all the terminal types that this driver supports\r
     //\r
     Match = FALSE;\r
-    for (TerminalType = TerminalTypePcAnsi; TerminalType <= TerminalTypeTtyTerm; TerminalType++) {\r
+    for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
 \r
       SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
 \r
@@ -1665,46 +1610,11 @@ SetTerminalDevicePath (
 {\r
   VENDOR_DEVICE_PATH  Node;\r
 \r
-  *TerminalDevicePath = NULL;\r
+  ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
   Node.Header.Type    = MESSAGING_DEVICE_PATH;\r
   Node.Header.SubType = MSG_VENDOR_DP;\r
-\r
-  //\r
-  // Generate terminal device path node according to terminal type.\r
-  //\r
-  switch (TerminalType) {\r
-\r
-  case TerminalTypePcAnsi:\r
-    CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
-    break;\r
-\r
-  case TerminalTypeVt100:\r
-    CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
-    break;\r
-\r
-  case TerminalTypeVt100Plus:\r
-    CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
-    break;\r
-\r
-  case TerminalTypeVtUtf8:\r
-    CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
-    break;\r
-\r
-  case TerminalTypeTtyTerm:\r
-    CopyGuid (&Node.Guid, &gEfiTtyTermGuid);\r
-    break;\r
-\r
-  default:\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  //\r
-  // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
-  //\r
-  SetDevicePathNodeLength (\r
-    &Node.Header,\r
-    sizeof (VENDOR_DEVICE_PATH)\r
-    );\r
+  SetDevicePathNodeLength (&Node, sizeof (VENDOR_DEVICE_PATH));\r
+  CopyGuid (&Node.Guid, mTerminalType[TerminalType]);\r
 \r
   //\r
   // Append the terminal node onto parent device path\r