]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/ConsoleOption.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / ConsoleOption.c
diff --git a/EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/ConsoleOption.c b/EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/ConsoleOption.c
new file mode 100644 (file)
index 0000000..c77fa0a
--- /dev/null
@@ -0,0 +1,840 @@
+/*++\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+    ConsoleOption.c\r
+    \r
+Abstract:\r
+\r
+    handles console redirection from boot manager\r
+\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL  *\r
+DevicePathInstanceDup (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  );\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  BOOLEAN                   ChangeTerminal\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node1;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      Uart = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      //\r
+      // Change the device path in the ComPort\r
+      //\r
+      if (ChangeTerminal) {\r
+        Node1 = NewTerminalContext->DevicePath;\r
+        Node1 = NextDevicePathNode (Node1);\r
+        while (!IsDevicePathEnd (Node1)) {\r
+          if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
+            Uart1 = (UART_DEVICE_PATH *) Node1;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+            break;\r
+          }\r
+          //\r
+          // end if\r
+          //\r
+          Node1 = NextDevicePathNode (Node1);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (\r
+                      &TerminalMenu,\r
+                      Com\r
+                      );\r
+      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      Uart                = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  );\r
+\r
+EFI_STATUS\r
+LocateSerialIo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build a list containing all serial devices \r
+  \r
+Arguments:\r
+  \r
+Returns:\r
+  \r
+--*/\r
+{\r
+  UINT8                     *Ptr;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     NoHandles;\r
+  EFI_HANDLE                *Handles;\r
+  EFI_STATUS                Status;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINT32                    Match;\r
+  EFI_SERIAL_IO_PROTOCOL    *SerialIo;\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  //\r
+  // Get all handles that have SerialIo protocol installed\r
+  //\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  TerminalMenu.MenuNumber = 0;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  NULL,\r
+                  &NoHandles,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // No serial ports present\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  for (Index = 0; Index < NoHandles; Index++) {\r
+    //\r
+    // Check to see whether the handle has DevicePath Protocol installed\r
+    //\r
+    gBS->HandleProtocol (\r
+          Handles[Index],\r
+          &gEfiDevicePathProtocolGuid,\r
+          &DevicePath\r
+          );\r
+    Ptr = (UINT8 *) DevicePath;\r
+    while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+      Ptr++;\r
+    }\r
+\r
+    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+    Match = EISA_PNP_ID (0x0501);\r
+\r
+    if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
+      if (!NewMenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
+      NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);\r
+      //\r
+      // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
+      // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
+      // datahub which is not completed, so a searching for end of device path will enter a\r
+      // dead-loop.\r
+      //\r
+      NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
+      if (NULL == NewMenuEntry->DisplayString) {\r
+        NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
+      }\r
+\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      gBS->HandleProtocol (\r
+            Handles[Index],\r
+            &gEfiSerialIoProtocolGuid,\r
+            &SerialIo\r
+            );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->BaudRate,\r
+        &SerialIo->Mode->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->DataBits,\r
+        &SerialIo->Mode->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->Parity,\r
+        &SerialIo->Mode->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->StopBits,\r
+        &SerialIo->Mode->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
+      TerminalMenu.MenuNumber++;\r
+    }\r
+  }\r
+  //\r
+  // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
+  //\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath) {\r
+    UpdateComAttributeFromVariable (OutDevicePath);\r
+  }\r
+\r
+  if (InpDevicePath) {\r
+    UpdateComAttributeFromVariable (InpDevicePath);\r
+  }\r
+\r
+  if (ErrDevicePath) {\r
+    UpdateComAttributeFromVariable (ErrDevicePath);\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->TerminalType  = 0;\r
+    NewTerminalContext->IsConIn       = FALSE;\r
+    NewTerminalContext->IsConOut      = FALSE;\r
+    NewTerminalContext->IsStdErr      = FALSE;\r
+\r
+    Vendor.Header.Type                = MESSAGING_DEVICE_PATH;\r
+    Vendor.Header.SubType             = MSG_VENDOR_DP;\r
+\r
+    for (Index2 = 0; Index2 < 4; Index2++) {\r
+      CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      NewDevicePath = AppendDevicePathNode (\r
+                        NewTerminalContext->DevicePath,\r
+                        (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                        );\r
+      SafeFreePool (NewMenuEntry->HelpString);\r
+      //\r
+      // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
+      // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
+      //\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConOut      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConIn       = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsStdErr      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Update Com Ports attributes from DevicePath\r
+  \r
+Arguments:\r
+  DevicePath  -   DevicePath that contains Com ports\r
+  \r
+Returns:\r
+  \r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *SerialNode;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINT32                    Match;\r
+  UINTN                     TerminalNumber;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  UINTN                     Index;\r
+\r
+  Match           = EISA_PNP_ID (0x0501);\r
+  Node            = DevicePath;\r
+  Node            = NextDevicePathNode (Node);\r
+  TerminalNumber  = 0;\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    while (!IsDevicePathEnd (Node)) {\r
+      if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+        Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+        if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+          CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
+        }\r
+      }\r
+\r
+      if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+        Uart          = (UART_DEVICE_PATH *) Node;\r
+        NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
+        if (NULL == NewMenuEntry) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+        CopyMem (\r
+          &NewTerminalContext->BaudRate,\r
+          &Uart->BaudRate,\r
+          sizeof (UINT64)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->DataBits,\r
+          &Uart->DataBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->Parity,\r
+          &Uart->Parity,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->StopBits,\r
+          &Uart->StopBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        SerialNode  = NewTerminalContext->DevicePath;\r
+        SerialNode  = NextDevicePathNode (SerialNode);\r
+        while (!IsDevicePathEnd (SerialNode)) {\r
+          if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
+            //\r
+            // Update following device paths according to\r
+            // previous acquired uart attributes\r
+            //\r
+            Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            break;\r
+          }\r
+\r
+          SerialNode = NextDevicePathNode (SerialNode);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+      }\r
+\r
+      Node = NextDevicePathNode (Node);\r
+    }\r
+    //\r
+    // end while\r
+    //\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+DevicePathInstanceDup (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function creates a device path data structure that identically matches the \r
+  device path passed in.\r
+\r
+Arguments:\r
+  DevPath      - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+  The new copy of DevPath is created to identically match the input.  \r
+  Otherwise, NULL is returned.\r
+\r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Temp;\r
+  UINT8                     *Ptr;\r
+  UINTN                     Size;\r
+\r
+  //\r
+  // get the size of an instance from the input\r
+  //\r
+  Temp            = DevPath;\r
+  DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);\r
+\r
+  //\r
+  // Make a copy and set proper end type\r
+  //\r
+  NewDevPath = NULL;\r
+  if (Size) {\r
+    NewDevPath = AllocateZeroPool (Size);\r
+    ASSERT (NewDevPath != NULL);\r
+  }\r
+\r
+  if (NewDevPath) {\r
+    CopyMem (NewDevPath, DevicePathInst, Size);\r
+    Ptr = (UINT8 *) NewDevPath;\r
+    Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+    Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    SetDevicePathEndNode (Temp);\r
+  }\r
+\r
+  return NewDevPath;\r
+}\r
+\r
+EFI_STATUS\r
+GetConsoleMenu (\r
+  IN UINTN              ConsoleMenuType\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *AllDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *MultiDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+  UINTN                     AllCount;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  TYPE_OF_TERMINAL          Terminal;\r
+  BM_MENU_ENTRY             *NewTerminalMenuEntry;\r
+  UINTN                     Com;\r
+  BM_MENU_OPTION            *ConsoleMenu;\r
+\r
+  DevicePath    = NULL;\r
+  AllDevicePath = NULL;\r
+  AllCount      = 0;\r
+  switch (ConsoleMenuType) {\r
+  case BM_CONSOLE_IN_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleInpMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConIn",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConInDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleOutMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleErrMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ErrOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ErrOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (NULL == AllDevicePath) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  InitializeListHead (&ConsoleMenu->Head);\r
+\r
+  AllCount                = EfiDevicePathInstanceCount (AllDevicePath);\r
+  ConsoleMenu->MenuNumber = 0;\r
+  //\r
+  // Following is menu building up for Console Out Devices\r
+  //\r
+  MultiDevicePath = AllDevicePath;\r
+  Index2          = 0;\r
+  for (Index = 0; Index < AllCount; Index++) {\r
+    DevicePathInst  = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
+\r
+    NewMenuEntry    = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewConsoleContext             = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewMenuEntry->OptionNumber    = Index2;\r
+\r
+    NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);\r
+    NewMenuEntry->DisplayString   = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
+    if (NULL == NewMenuEntry->DisplayString) {\r
+      NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
+    }\r
+\r
+    NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
+                                      NewConsoleContext->DevicePath,\r
+                                      &Terminal,\r
+                                      &Com\r
+                                      );\r
+\r
+    NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
+                                    DevicePath,\r
+                                    NewConsoleContext->DevicePath\r
+                                    );\r
+    NewTerminalMenuEntry  = NULL;\r
+    NewTerminalContext    = NULL;\r
+\r
+    if (NewConsoleContext->IsTerminal) {\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    } else {\r
+      Index2++;\r
+      ConsoleMenu->MenuNumber++;\r
+      InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetAllConsoles (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+  EFI_SUCCESS \r
+  Others\r
+  \r
+--*/\r
+{\r
+  GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+  EFI_SUCCESS \r
+  Others\r
+  \r
+--*/\r
+{\r
+  BOpt_FreeMenu (&ConsoleOutMenu);\r
+  BOpt_FreeMenu (&ConsoleInpMenu);\r
+  BOpt_FreeMenu (&ConsoleErrMenu);\r
+  BOpt_FreeMenu (&TerminalMenu);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Test whether DevicePath is a valid Terminal\r
+\r
+Arguments:\r
+  DevicePath  -   DevicePath to be checked\r
+  Termi       -   If is terminal, give its type\r
+  Com         -   If is Com Port, give its type\r
+  \r
+Returns:\r
+  TRUE        -   If DevicePath point to a Terminal\r
+  FALSE\r
+  \r
+--*/\r
+{\r
+  UINT8                 *Ptr;\r
+  BOOLEAN               IsTerminal;\r
+  VENDOR_DEVICE_PATH    *Vendor;\r
+  ACPI_HID_DEVICE_PATH  *Acpi;\r
+  UINT32                Match;\r
+  EFI_GUID              TempGuid;\r
+\r
+  IsTerminal = FALSE;\r
+\r
+  //\r
+  // Parse the Device Path, should be change later!!!\r
+  //\r
+  Ptr = (UINT8 *) DevicePath;\r
+  while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+    Ptr++;\r
+  }\r
+\r
+  Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
+  Vendor  = (VENDOR_DEVICE_PATH *) Ptr;\r
+\r
+  //\r
+  // There are four kinds of Terminal types\r
+  // check to see whether this devicepath\r
+  // is one of that type\r
+  //\r
+  CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
+\r
+  if (CompareGuid (&TempGuid, &Guid[0])) {\r
+    *Termi      = PC_ANSI;\r
+    IsTerminal  = TRUE;\r
+  } else {\r
+    if (CompareGuid (&TempGuid, &Guid[1])) {\r
+      *Termi      = VT_100;\r
+      IsTerminal  = TRUE;\r
+    } else {\r
+      if (CompareGuid (&TempGuid, &Guid[2])) {\r
+        *Termi      = VT_100_PLUS;\r
+        IsTerminal  = TRUE;\r
+      } else {\r
+        if (CompareGuid (&TempGuid, &Guid[3])) {\r
+          *Termi      = VT_UTF8;\r
+          IsTerminal  = TRUE;\r
+        } else {\r
+          IsTerminal = FALSE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (!IsTerminal) {\r
+    return FALSE;\r
+  }\r
+\r
+  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+  Match = EISA_PNP_ID (0x0501);\r
+  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+    CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
+  } else {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r