mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-25 17:23:53 +02:00 
			
		
		
		
	Cc: Jeff Fan <jeff.fan@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
		
			
				
	
	
		
			1199 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1199 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   handles console redirection from boot manager
 | |
| 
 | |
| Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "BootMaint.h"
 | |
| 
 | |
| UART_FLOW_CONTROL_DEVICE_PATH mFlowControlDevicePath =
 | |
| {
 | |
|   {
 | |
|     MESSAGING_DEVICE_PATH,
 | |
|     MSG_VENDOR_DP,
 | |
|     {
 | |
|       (UINT8)(sizeof(UART_FLOW_CONTROL_DEVICE_PATH)),
 | |
|       (UINT8)((sizeof(UART_FLOW_CONTROL_DEVICE_PATH)) >> 8)
 | |
|     }
 | |
|   },
 | |
|   DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL,
 | |
|   UART_FLOW_CONTROL_HARDWARE
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Check the device path node whether it's the Flow Control node or not.
 | |
| 
 | |
|   @param[in] FlowControl    The device path node to be checked.
 | |
|   
 | |
|   @retval TRUE              It's the Flow Control node.
 | |
|   @retval FALSE             It's not.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsUartFlowControlNode (
 | |
|   IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
 | |
|   )
 | |
| {
 | |
|   return (BOOLEAN) (
 | |
|            (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
 | |
|            (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
 | |
|            (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
 | |
|            );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether the device path node is ISA Serial Node.
 | |
| 
 | |
|   @param Acpi           Device path node to be checked
 | |
| 
 | |
|   @retval TRUE          It's ISA Serial Node.
 | |
|   @retval FALSE         It's NOT ISA Serial Node.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsIsaSerialNode (
 | |
|   IN ACPI_HID_DEVICE_PATH *Acpi
 | |
|   )
 | |
| {
 | |
|   return (BOOLEAN) (
 | |
|       (DevicePathType (Acpi) == ACPI_DEVICE_PATH) &&
 | |
|       (DevicePathSubType (Acpi) == ACPI_DP) &&
 | |
|       (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501))
 | |
|       );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update Com Ports attributes from DevicePath
 | |
| 
 | |
|   @param DevicePath      DevicePath that contains Com ports
 | |
| 
 | |
|   @retval EFI_SUCCESS   The update is successful.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| UpdateComAttributeFromVariable (
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Update the multi-instance device path of Terminal Device based on
 | |
|   the global TerminalMenu. If ChangeTernimal is TRUE, the terminal 
 | |
|   device path in the Terminal Device in TerminalMenu is also updated.
 | |
| 
 | |
|   @param DevicePath      The multi-instance device path.
 | |
|   @param ChangeTerminal  TRUE, then device path in the Terminal Device 
 | |
|                          in TerminalMenu is also updated; FALSE, no update.
 | |
| 
 | |
|   @return EFI_SUCCESS    The function completes successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| ChangeTerminalDevicePath (
 | |
|   IN OUT    EFI_DEVICE_PATH_PROTOCOL  **DevicePath,
 | |
|   IN        BOOLEAN                   ChangeTerminal
 | |
|   )
 | |
| {
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *Node;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *Node1;
 | |
|   ACPI_HID_DEVICE_PATH      *Acpi;
 | |
|   UART_DEVICE_PATH          *Uart;
 | |
|   UART_DEVICE_PATH          *Uart1;
 | |
|   UINTN                     Com;
 | |
|   BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | |
|   BM_MENU_ENTRY             *NewMenuEntry;
 | |
|   UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
 | |
| 
 | |
|   Node  = *DevicePath;
 | |
|   Node  = NextDevicePathNode (Node);
 | |
|   Com   = 0;
 | |
|   while (!IsDevicePathEnd (Node)) {
 | |
|     Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | |
|     if (IsIsaSerialNode (Acpi)) {
 | |
|       CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
 | |
|     }
 | |
| 
 | |
|     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
 | |
| 
 | |
|     NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|     if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
 | |
|       Uart = (UART_DEVICE_PATH *) Node;
 | |
|       CopyMem (
 | |
|         &Uart->BaudRate,
 | |
|         &NewTerminalContext->BaudRate,
 | |
|         sizeof (UINT64)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &Uart->DataBits,
 | |
|         &NewTerminalContext->DataBits,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &Uart->Parity,
 | |
|         &NewTerminalContext->Parity,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &Uart->StopBits,
 | |
|         &NewTerminalContext->StopBits,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node);
 | |
|       if (IsUartFlowControlNode (FlowControlNode)) {
 | |
|         FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl;
 | |
|       } else {
 | |
|         //
 | |
|         // Append the Flow control device node when user enable flow control.
 | |
|         //
 | |
|         if (NewTerminalContext->FlowControl != 0) {
 | |
|           mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl;
 | |
|           *DevicePath = AppendDevicePathNode (
 | |
|                                        *DevicePath,
 | |
|                                        (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath)
 | |
|                                        );
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Change the device path in the ComPort
 | |
|       //
 | |
|       if (ChangeTerminal) {
 | |
|         Node1 = NewTerminalContext->DevicePath;
 | |
|         Node1 = NextDevicePathNode (Node1);
 | |
|         while (!IsDevicePathEnd (Node1)) {
 | |
|           if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {
 | |
|             Uart1 = (UART_DEVICE_PATH *) Node1;
 | |
|             CopyMem (
 | |
|               &Uart1->BaudRate,
 | |
|               &NewTerminalContext->BaudRate,
 | |
|               sizeof (UINT64)
 | |
|               );
 | |
| 
 | |
|             CopyMem (
 | |
|               &Uart1->DataBits,
 | |
|               &NewTerminalContext->DataBits,
 | |
|               sizeof (UINT8)
 | |
|               );
 | |
| 
 | |
|             CopyMem (
 | |
|               &Uart1->Parity,
 | |
|               &NewTerminalContext->Parity,
 | |
|               sizeof (UINT8)
 | |
|               );
 | |
| 
 | |
|             CopyMem (
 | |
|               &Uart1->StopBits,
 | |
|               &NewTerminalContext->StopBits,
 | |
|               sizeof (UINT8)
 | |
|               );
 | |
|             break;
 | |
|           }
 | |
|           //
 | |
|           // end if
 | |
|           //
 | |
|           Node1 = NextDevicePathNode (Node1);
 | |
|         }
 | |
|         //
 | |
|         // end while
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Node = NextDevicePathNode (Node);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update the device path that describing a terminal device
 | |
|   based on the new BaudRate, Data Bits, parity and Stop Bits
 | |
|   set.
 | |
| 
 | |
|   @param DevicePath terminal device's path
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ChangeVariableDevicePath (
 | |
|   IN OUT EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | |
|   )
 | |
| {
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *Node;
 | |
|   ACPI_HID_DEVICE_PATH      *Acpi;
 | |
|   UART_DEVICE_PATH          *Uart;
 | |
|   UINTN                     Com;
 | |
|   BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | |
|   BM_MENU_ENTRY             *NewMenuEntry;
 | |
| 
 | |
|   Node  = DevicePath;
 | |
|   Node  = NextDevicePathNode (Node);
 | |
|   Com   = 0;
 | |
|   while (!IsDevicePathEnd (Node)) {
 | |
|     Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | |
|     if (IsIsaSerialNode (Acpi)) {
 | |
|       CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
 | |
|     }
 | |
| 
 | |
|     if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
 | |
|       NewMenuEntry = BOpt_GetMenuEntry (
 | |
|                       &TerminalMenu,
 | |
|                       Com
 | |
|                       );
 | |
|       ASSERT (NewMenuEntry != NULL);
 | |
|       NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|       Uart                = (UART_DEVICE_PATH *) Node;
 | |
|       CopyMem (
 | |
|         &Uart->BaudRate,
 | |
|         &NewTerminalContext->BaudRate,
 | |
|         sizeof (UINT64)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &Uart->DataBits,
 | |
|         &NewTerminalContext->DataBits,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &Uart->Parity,
 | |
|         &NewTerminalContext->Parity,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &Uart->StopBits,
 | |
|         &NewTerminalContext->StopBits,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     Node = NextDevicePathNode (Node);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieve ACPI UID of UART from device path
 | |
| 
 | |
|   @param Handle          The handle for the UART device.
 | |
|   @param AcpiUid         The ACPI UID on output.
 | |
| 
 | |
|   @retval  TRUE   Find valid UID from device path
 | |
|   @retval  FALSE  Can't find
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| RetrieveUartUid (
 | |
|   IN EFI_HANDLE   Handle,
 | |
|   IN OUT UINT32   *AcpiUid
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   ACPI_HID_DEVICE_PATH      *Acpi;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
| 
 | |
|   Status = gBS->HandleProtocol (
 | |
|                   Handle,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   (VOID **) &DevicePath
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   Acpi = NULL;
 | |
|   for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
 | |
|     if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) {
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // Acpi points to the node before the Uart node
 | |
|     //
 | |
|     Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
 | |
|   }
 | |
| 
 | |
|   if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
 | |
|     if (AcpiUid != NULL) {
 | |
|       CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32));
 | |
|     }
 | |
|     return TRUE;
 | |
|   } else {
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Sort Uart handles array with Acpi->UID from low to high.
 | |
| 
 | |
|   @param Handles         EFI_SERIAL_IO_PROTOCOL handle buffer
 | |
|   @param NoHandles       EFI_SERIAL_IO_PROTOCOL handle count
 | |
| **/
 | |
| VOID
 | |
| SortedUartHandle (
 | |
|   IN  EFI_HANDLE *Handles,
 | |
|   IN  UINTN      NoHandles
 | |
|   )
 | |
| {
 | |
|   UINTN       Index1;
 | |
|   UINTN       Index2;
 | |
|   UINTN       Position;
 | |
|   UINT32      AcpiUid1;
 | |
|   UINT32      AcpiUid2;
 | |
|   UINT32      TempAcpiUid;
 | |
|   EFI_HANDLE  TempHandle;
 | |
| 
 | |
|   for (Index1 = 0; Index1 < NoHandles-1; Index1++) {
 | |
|     if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {
 | |
|       continue;
 | |
|     }
 | |
|     TempHandle  = Handles[Index1];
 | |
|     Position    = Index1;
 | |
|     TempAcpiUid = AcpiUid1;
 | |
| 
 | |
|     for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {
 | |
|       if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {
 | |
|         continue;
 | |
|       }
 | |
|       if (AcpiUid2 < TempAcpiUid) {
 | |
|         TempAcpiUid = AcpiUid2;
 | |
|         TempHandle  = Handles[Index2];
 | |
|         Position    = Index2;
 | |
|       }
 | |
|     }
 | |
|     Handles[Position] = Handles[Index1];
 | |
|     Handles[Index1]   = TempHandle;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Test whether DevicePath is a valid Terminal
 | |
| 
 | |
| 
 | |
|   @param DevicePath      DevicePath to be checked
 | |
|   @param Termi           If DevicePath is valid Terminal, terminal type is returned.
 | |
|   @param Com             If DevicePath is valid Terminal, Com Port type is returned.
 | |
| 
 | |
|   @retval  TRUE         If DevicePath point to a Terminal.
 | |
|   @retval  FALSE        If DevicePath does not point to a Terminal.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTerminalDevicePath (
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
 | |
|   OUT TYPE_OF_TERMINAL         *Termi,
 | |
|   OUT UINTN                    *Com
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Build a list containing all serial devices.
 | |
| 
 | |
| 
 | |
|   @retval EFI_SUCCESS The function complete successfully.
 | |
|   @retval EFI_UNSUPPORTED No serial ports present.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LocateSerialIo (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINTN                     Index;
 | |
|   UINTN                     Index2;
 | |
|   UINTN                     NoHandles;
 | |
|   EFI_HANDLE                *Handles;
 | |
|   EFI_STATUS                Status;
 | |
|   ACPI_HID_DEVICE_PATH      *Acpi;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
|   EFI_SERIAL_IO_PROTOCOL    *SerialIo;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *Node;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;
 | |
|   BM_MENU_ENTRY             *NewMenuEntry;
 | |
|   BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
 | |
|   VENDOR_DEVICE_PATH        Vendor;
 | |
|   UINT32                    FlowControl;
 | |
|   //
 | |
|   // Get all handles that have SerialIo protocol installed
 | |
|   //
 | |
|   InitializeListHead (&TerminalMenu.Head);
 | |
|   TerminalMenu.MenuNumber = 0;
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiSerialIoProtocolGuid,
 | |
|                   NULL,
 | |
|                   &NoHandles,
 | |
|                   &Handles
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // No serial ports present
 | |
|     //
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Sort Uart handles array with Acpi->UID from low to high
 | |
|   // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
 | |
|   //
 | |
|   SortedUartHandle (Handles, NoHandles);
 | |
| 
 | |
|   for (Index = 0; Index < NoHandles; Index++) {
 | |
|     //
 | |
|     // Check to see whether the handle has DevicePath Protocol installed
 | |
|     //
 | |
|     gBS->HandleProtocol (
 | |
|           Handles[Index],
 | |
|           &gEfiDevicePathProtocolGuid,
 | |
|           (VOID **) &DevicePath
 | |
|           );
 | |
| 
 | |
|     Acpi = NULL;
 | |
|     for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
 | |
|       if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
 | |
|         break;
 | |
|       }
 | |
|       //
 | |
|       // Acpi points to the node before Uart node
 | |
|       //
 | |
|       Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | |
|     }
 | |
| 
 | |
|     if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
 | |
|       NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
 | |
|       if (NewMenuEntry == NULL) {
 | |
|         FreePool (Handles);
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|       CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
 | |
|       NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath);
 | |
|       //
 | |
|       // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
 | |
|       // coz' the misc data for each platform is not correct, actually it's the device path stored in
 | |
|       // datahub which is not completed, so a searching for end of device path will enter a
 | |
|       // dead-loop.
 | |
|       //
 | |
|       NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);
 | |
|       if (NULL == NewMenuEntry->DisplayString) {
 | |
|         NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);
 | |
|       }
 | |
| 
 | |
|       NewMenuEntry->HelpString = NULL;
 | |
| 
 | |
|       gBS->HandleProtocol (
 | |
|             Handles[Index],
 | |
|             &gEfiSerialIoProtocolGuid,
 | |
|             (VOID **) &SerialIo
 | |
|             );
 | |
| 
 | |
|       CopyMem (
 | |
|         &NewTerminalContext->BaudRate,
 | |
|         &SerialIo->Mode->BaudRate,
 | |
|         sizeof (UINT64)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &NewTerminalContext->DataBits,
 | |
|         &SerialIo->Mode->DataBits,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &NewTerminalContext->Parity,
 | |
|         &SerialIo->Mode->Parity,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       CopyMem (
 | |
|         &NewTerminalContext->StopBits,
 | |
|         &SerialIo->Mode->StopBits,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
| 
 | |
|       NewTerminalContext->FlowControl = 0;
 | |
|       SerialIo->GetControl(SerialIo, &FlowControl);
 | |
|       if ((FlowControl & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) != 0) {
 | |
|         NewTerminalContext->FlowControl = UART_FLOW_CONTROL_HARDWARE;
 | |
|       }
 | |
| 
 | |
|       InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
 | |
|       TerminalMenu.MenuNumber++;
 | |
|     }
 | |
|   }
 | |
|   if (Handles != NULL) {
 | |
|     FreePool (Handles);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
 | |
|   //
 | |
|   OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
 | |
|   InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
 | |
|   ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
 | |
|   if (OutDevicePath != NULL) {
 | |
|     UpdateComAttributeFromVariable (OutDevicePath);
 | |
|   }
 | |
| 
 | |
|   if (InpDevicePath != NULL) {
 | |
|     UpdateComAttributeFromVariable (InpDevicePath);
 | |
|   }
 | |
| 
 | |
|   if (ErrDevicePath != NULL) {
 | |
|     UpdateComAttributeFromVariable (ErrDevicePath);
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
 | |
|     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
 | |
|     if (NULL == NewMenuEntry) {
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | |
| 
 | |
|     NewTerminalContext->TerminalType  = 0;
 | |
|     NewTerminalContext->IsConIn       = FALSE;
 | |
|     NewTerminalContext->IsConOut      = FALSE;
 | |
|     NewTerminalContext->IsStdErr      = FALSE;
 | |
| 
 | |
|     Vendor.Header.Type                = MESSAGING_DEVICE_PATH;
 | |
|     Vendor.Header.SubType             = MSG_VENDOR_DP;
 | |
| 
 | |
|     for (Index2 = 0; Index2 < 4; Index2++) {
 | |
|       CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID));
 | |
|       SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
 | |
|       NewDevicePath = AppendDevicePathNode (
 | |
|                         NewTerminalContext->DevicePath,
 | |
|                         (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
 | |
|                         );
 | |
|       if (NewMenuEntry->HelpString != NULL) {
 | |
|         FreePool (NewMenuEntry->HelpString);
 | |
|       }
 | |
|       //
 | |
|       // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
 | |
|       // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
 | |
|       //
 | |
|       NewMenuEntry->HelpString = NULL;
 | |
| 
 | |
|       if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {
 | |
|         NewTerminalContext->IsConOut      = TRUE;
 | |
|         NewTerminalContext->TerminalType  = (UINT8) Index2;
 | |
|       }
 | |
| 
 | |
|       if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {
 | |
|         NewTerminalContext->IsConIn       = TRUE;
 | |
|         NewTerminalContext->TerminalType  = (UINT8) Index2;
 | |
|       }
 | |
| 
 | |
|       if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {
 | |
|         NewTerminalContext->IsStdErr      = TRUE;
 | |
|         NewTerminalContext->TerminalType  = (UINT8) Index2;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update Com Ports attributes from DevicePath
 | |
| 
 | |
|   @param DevicePath      DevicePath that contains Com ports
 | |
| 
 | |
|   @retval EFI_SUCCESS   The update is successful.
 | |
|   @retval EFI_NOT_FOUND Can not find specific menu entry
 | |
| **/
 | |
| EFI_STATUS
 | |
| UpdateComAttributeFromVariable (
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | |
|   )
 | |
| {
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *Node;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *SerialNode;
 | |
|   ACPI_HID_DEVICE_PATH      *Acpi;
 | |
|   UART_DEVICE_PATH          *Uart;
 | |
|   UART_DEVICE_PATH          *Uart1;
 | |
|   UINTN                     TerminalNumber;
 | |
|   BM_MENU_ENTRY             *NewMenuEntry;
 | |
|   BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | |
|   UINTN                     Index;
 | |
|   UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
 | |
|   BOOLEAN                   HasFlowControlNode;
 | |
| 
 | |
|   HasFlowControlNode = FALSE;
 | |
|   Node            = DevicePath;
 | |
|   Node            = NextDevicePathNode (Node);
 | |
|   TerminalNumber  = 0;
 | |
|   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
 | |
|     while (!IsDevicePathEnd (Node)) {
 | |
|       Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | |
|       if (IsIsaSerialNode (Acpi)) {
 | |
|         CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));
 | |
|       }
 | |
| 
 | |
|       if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
 | |
|         Uart          = (UART_DEVICE_PATH *) Node;
 | |
|         NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);
 | |
|         if (NULL == NewMenuEntry) {
 | |
|           return EFI_NOT_FOUND;
 | |
|         }
 | |
| 
 | |
|         NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|         CopyMem (
 | |
|           &NewTerminalContext->BaudRate,
 | |
|           &Uart->BaudRate,
 | |
|           sizeof (UINT64)
 | |
|           );
 | |
| 
 | |
|         CopyMem (
 | |
|           &NewTerminalContext->DataBits,
 | |
|           &Uart->DataBits,
 | |
|           sizeof (UINT8)
 | |
|           );
 | |
| 
 | |
|         CopyMem (
 | |
|           &NewTerminalContext->Parity,
 | |
|           &Uart->Parity,
 | |
|           sizeof (UINT8)
 | |
|           );
 | |
| 
 | |
|         CopyMem (
 | |
|           &NewTerminalContext->StopBits,
 | |
|           &Uart->StopBits,
 | |
|           sizeof (UINT8)
 | |
|           );
 | |
| 
 | |
|         FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node);
 | |
|         if (IsUartFlowControlNode (FlowControlNode)) {
 | |
|           HasFlowControlNode = TRUE;
 | |
|           NewTerminalContext->FlowControl = (UINT8) ReadUnaligned32 (&FlowControlNode->FlowControlMap);
 | |
|         } else if (NewTerminalContext->FlowControl != 0) {
 | |
|           //
 | |
|           // No Flow Control device path node, assumption no Flow control
 | |
|           //
 | |
|           NewTerminalContext->FlowControl = 0;
 | |
|         }
 | |
| 
 | |
|         SerialNode  = NewTerminalContext->DevicePath;
 | |
|         SerialNode  = NextDevicePathNode (SerialNode);
 | |
|         while (!IsDevicePathEnd (SerialNode)) {
 | |
|           if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {
 | |
|             //
 | |
|             // Update following device paths according to
 | |
|             // previous acquired uart attributes
 | |
|             //
 | |
|             Uart1 = (UART_DEVICE_PATH *) SerialNode;
 | |
|             CopyMem (
 | |
|               &Uart1->BaudRate,
 | |
|               &NewTerminalContext->BaudRate,
 | |
|               sizeof (UINT64)
 | |
|               );
 | |
| 
 | |
|             CopyMem (
 | |
|               &Uart1->DataBits,
 | |
|               &NewTerminalContext->DataBits,
 | |
|               sizeof (UINT8)
 | |
|               );
 | |
|             CopyMem (
 | |
|               &Uart1->Parity,
 | |
|               &NewTerminalContext->Parity,
 | |
|               sizeof (UINT8)
 | |
|               );
 | |
|             CopyMem (
 | |
|               &Uart1->StopBits,
 | |
|               &NewTerminalContext->StopBits,
 | |
|               sizeof (UINT8)
 | |
|               );
 | |
| 
 | |
|             FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (SerialNode);
 | |
|             if (IsUartFlowControlNode (FlowControlNode)) {
 | |
|               FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl;
 | |
|             } else {
 | |
|               if (HasFlowControlNode) {
 | |
|                 mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl;
 | |
|                 NewTerminalContext->DevicePath = AppendDevicePathNode (
 | |
|                                              NewTerminalContext->DevicePath,
 | |
|                                              (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath)
 | |
|                                              );
 | |
|               }
 | |
|             }
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           SerialNode = NextDevicePathNode (SerialNode);
 | |
|         }
 | |
|         //
 | |
|         // end while
 | |
|         //
 | |
|       }
 | |
| 
 | |
|       Node = NextDevicePathNode (Node);
 | |
|     }
 | |
|     //
 | |
|     // end while
 | |
|     //
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Build up Console Menu based on types passed in. The type can
 | |
|   be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
 | |
|   and BM_CONSOLE_ERR_CONTEXT_SELECT.
 | |
| 
 | |
|   @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
 | |
|                          and BM_CONSOLE_ERR_CONTEXT_SELECT.
 | |
| 
 | |
|   @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined.
 | |
|   @retval EFI_NOT_FOUND   If the EFI Variable defined in UEFI spec with name "ConOutDev", 
 | |
|                           "ConInDev" or "ConErrDev" doesn't exists.
 | |
|   @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations.
 | |
|   @retval EFI_SUCCESS          Function completes successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| GetConsoleMenu (
 | |
|   IN UINTN              ConsoleMenuType
 | |
|   )
 | |
| {
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *AllDevicePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *MultiDevicePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
 | |
|   UINTN                     Size;
 | |
|   UINTN                     AllCount;
 | |
|   UINTN                     Index;
 | |
|   UINTN                     Index2;
 | |
|   BM_MENU_ENTRY             *NewMenuEntry;
 | |
|   BM_CONSOLE_CONTEXT        *NewConsoleContext;
 | |
|   TYPE_OF_TERMINAL          Terminal;
 | |
|   UINTN                     Com;
 | |
|   BM_MENU_OPTION            *ConsoleMenu;
 | |
| 
 | |
|   DevicePath    = NULL;
 | |
|   AllDevicePath = NULL;
 | |
|   AllCount      = 0;
 | |
|   switch (ConsoleMenuType) {
 | |
|   case BM_CONSOLE_IN_CONTEXT_SELECT:
 | |
|     ConsoleMenu = &ConsoleInpMenu;
 | |
|     DevicePath = EfiLibGetVariable (
 | |
|                   L"ConIn",
 | |
|                   &gEfiGlobalVariableGuid
 | |
|                   );
 | |
| 
 | |
|     AllDevicePath = EfiLibGetVariable (
 | |
|                       L"ConInDev",
 | |
|                       &gEfiGlobalVariableGuid
 | |
|                       );
 | |
|     break;
 | |
| 
 | |
|   case BM_CONSOLE_OUT_CONTEXT_SELECT:
 | |
|     ConsoleMenu = &ConsoleOutMenu;
 | |
|     DevicePath = EfiLibGetVariable (
 | |
|                   L"ConOut",
 | |
|                   &gEfiGlobalVariableGuid
 | |
|                   );
 | |
| 
 | |
|     AllDevicePath = EfiLibGetVariable (
 | |
|                       L"ConOutDev",
 | |
|                       &gEfiGlobalVariableGuid
 | |
|                       );
 | |
|     break;
 | |
| 
 | |
|   case BM_CONSOLE_ERR_CONTEXT_SELECT:
 | |
|     ConsoleMenu = &ConsoleErrMenu;
 | |
|     DevicePath = EfiLibGetVariable (
 | |
|                   L"ErrOut",
 | |
|                   &gEfiGlobalVariableGuid
 | |
|                   );
 | |
| 
 | |
|     AllDevicePath = EfiLibGetVariable (
 | |
|                       L"ErrOutDev",
 | |
|                       &gEfiGlobalVariableGuid
 | |
|                       );
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (NULL == AllDevicePath) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   InitializeListHead (&ConsoleMenu->Head);
 | |
| 
 | |
|   AllCount                = EfiDevicePathInstanceCount (AllDevicePath);
 | |
|   ConsoleMenu->MenuNumber = 0;
 | |
|   //
 | |
|   // Following is menu building up for Console Devices selected.
 | |
|   //
 | |
|   MultiDevicePath = AllDevicePath;
 | |
|   Index2          = 0;
 | |
|   for (Index = 0; Index < AllCount; Index++) {
 | |
|     DevicePathInst  = GetNextDevicePathInstance (&MultiDevicePath, &Size);
 | |
| 
 | |
|     NewMenuEntry    = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);
 | |
|     if (NULL == NewMenuEntry) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     NewConsoleContext             = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|     NewMenuEntry->OptionNumber    = Index2;
 | |
| 
 | |
|     NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst);
 | |
|     ASSERT (NewConsoleContext->DevicePath != NULL);
 | |
|     NewMenuEntry->DisplayString   = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);
 | |
|     if (NULL == NewMenuEntry->DisplayString) {
 | |
|       NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);
 | |
|     }
 | |
| 
 | |
|     NewConsoleContext->IsTerminal = IsTerminalDevicePath (
 | |
|                                       NewConsoleContext->DevicePath,
 | |
|                                       &Terminal,
 | |
|                                       &Com
 | |
|                                       );
 | |
| 
 | |
|     NewConsoleContext->IsActive = BdsLibMatchDevicePaths (
 | |
|                                     DevicePath,
 | |
|                                     NewConsoleContext->DevicePath
 | |
|                                     );
 | |
| 
 | |
|     if (NewConsoleContext->IsTerminal) {
 | |
|       BOpt_DestroyMenuEntry (NewMenuEntry);
 | |
|     } else {
 | |
|       Index2++;
 | |
|       ConsoleMenu->MenuNumber++;
 | |
|       InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
 | |
| 
 | |
|   @retval EFI_SUCCESS    The function always complete successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| GetAllConsoles (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);
 | |
|   GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);
 | |
|   GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
 | |
| 
 | |
|   @retval EFI_SUCCESS    The function always complete successfully.
 | |
| **/
 | |
| EFI_STATUS
 | |
| FreeAllConsoles (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   BOpt_FreeMenu (&ConsoleOutMenu);
 | |
|   BOpt_FreeMenu (&ConsoleInpMenu);
 | |
|   BOpt_FreeMenu (&ConsoleErrMenu);
 | |
|   BOpt_FreeMenu (&TerminalMenu);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Test whether DevicePath is a valid Terminal
 | |
| 
 | |
| 
 | |
|   @param DevicePath      DevicePath to be checked
 | |
|   @param Termi           If DevicePath is valid Terminal, terminal type is returned.
 | |
|   @param Com             If DevicePath is valid Terminal, Com Port type is returned.
 | |
| 
 | |
|   @retval  TRUE         If DevicePath point to a Terminal.
 | |
|   @retval  FALSE        If DevicePath does not point to a Terminal.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTerminalDevicePath (
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
 | |
|   OUT TYPE_OF_TERMINAL         *Termi,
 | |
|   OUT UINTN                    *Com
 | |
|   )
 | |
| {
 | |
|   BOOLEAN                   IsTerminal;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *Node;
 | |
|   VENDOR_DEVICE_PATH        *Vendor;
 | |
|   UART_DEVICE_PATH          *Uart;
 | |
|   ACPI_HID_DEVICE_PATH      *Acpi;
 | |
| 
 | |
|   IsTerminal = FALSE;
 | |
| 
 | |
|   Uart   = NULL;
 | |
|   Vendor = NULL;
 | |
|   Acpi   = NULL;
 | |
|   for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
 | |
|     //
 | |
|     // Vendor points to the node before the End node
 | |
|     //
 | |
|     Vendor = (VENDOR_DEVICE_PATH *) Node;
 | |
| 
 | |
|     if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
 | |
|       Uart = (UART_DEVICE_PATH *) Node;
 | |
|     }
 | |
| 
 | |
|     if (Uart == NULL) {
 | |
|       //
 | |
|       // Acpi points to the node before the UART node
 | |
|       //
 | |
|       Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Vendor == NULL ||
 | |
|       DevicePathType (Vendor) != MESSAGING_DEVICE_PATH ||
 | |
|       DevicePathSubType (Vendor) != MSG_VENDOR_DP ||
 | |
|       Uart == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // There are four kinds of Terminal types
 | |
|   // check to see whether this devicepath
 | |
|   // is one of that type
 | |
|   //
 | |
|   if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[0])) {
 | |
|     *Termi      = TerminalTypePcAnsi;
 | |
|     IsTerminal  = TRUE;
 | |
|   } else {
 | |
|     if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[1])) {
 | |
|       *Termi      = TerminalTypeVt100;
 | |
|       IsTerminal  = TRUE;
 | |
|     } else {
 | |
|       if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[2])) {
 | |
|         *Termi      = TerminalTypeVt100Plus;
 | |
|         IsTerminal  = TRUE;
 | |
|       } else {
 | |
|         if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[3])) {
 | |
|           *Termi      = TerminalTypeVtUtf8;
 | |
|           IsTerminal  = TRUE;
 | |
|         } else {
 | |
|           IsTerminal = FALSE;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!IsTerminal) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
 | |
|     CopyMem (Com, &Acpi->UID, sizeof (UINT32));
 | |
|   } else {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get mode number according to column and row
 | |
| 
 | |
|   @param CallbackData    The BMM context data.
 | |
| **/
 | |
| VOID
 | |
| GetConsoleOutMode (
 | |
|   IN  BMM_CALLBACK_DATA    *CallbackData
 | |
|   )
 | |
| {
 | |
|   UINTN                         Col;
 | |
|   UINTN                         Row;
 | |
|   UINTN                         CurrentCol;
 | |
|   UINTN                         CurrentRow;
 | |
|   UINTN                         Mode;
 | |
|   UINTN                         MaxMode;
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
 | |
| 
 | |
|   ConOut   = gST->ConOut;
 | |
|   MaxMode  = (UINTN) (ConOut->Mode->MaxMode);
 | |
| 
 | |
|   CurrentCol = PcdGet32 (PcdSetupConOutColumn);
 | |
|   CurrentRow = PcdGet32 (PcdSetupConOutRow);
 | |
|   for (Mode = 0; Mode < MaxMode; Mode++) {
 | |
|     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
 | |
|     if (!EFI_ERROR(Status)) {
 | |
|       if (CurrentCol == Col && CurrentRow == Row) {
 | |
|         CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER]
 | |
|   in BMM_FAKE_NV_DATA structure.
 | |
| 
 | |
|   @param CallbackData    The BMM context data.
 | |
| 
 | |
| **/  
 | |
| VOID  
 | |
| GetConsoleInCheck (
 | |
|   IN  BMM_CALLBACK_DATA    *CallbackData
 | |
|   )
 | |
| {
 | |
|   UINT16              Index;
 | |
|   BM_MENU_ENTRY       *NewMenuEntry; 
 | |
|   UINT8               *ConInCheck;
 | |
|   BM_CONSOLE_CONTEXT  *NewConsoleContext;
 | |
|   
 | |
|   ASSERT (CallbackData != NULL);
 | |
|     
 | |
|   ConInCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
 | |
|   for (Index = 0; ((Index < ConsoleInpMenu.MenuNumber) && \
 | |
|        (Index < MAX_MENU_NUMBER)) ; Index++) {  
 | |
|     NewMenuEntry      = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
 | |
|     NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;  
 | |
|     ConInCheck[Index] = NewConsoleContext->IsActive;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER]
 | |
|   in BMM_FAKE_NV_DATA structure.
 | |
| 
 | |
|   @param CallbackData    The BMM context data.
 | |
| 
 | |
| **/      
 | |
| VOID    
 | |
| GetConsoleOutCheck (
 | |
|   IN  BMM_CALLBACK_DATA    *CallbackData
 | |
|   )
 | |
| {
 | |
|   UINT16              Index;
 | |
|   BM_MENU_ENTRY       *NewMenuEntry; 
 | |
|   UINT8               *ConOutCheck;
 | |
|   BM_CONSOLE_CONTEXT  *NewConsoleContext;
 | |
|   
 | |
|   ASSERT (CallbackData != NULL);
 | |
|   ConOutCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
 | |
|   for (Index = 0; ((Index < ConsoleOutMenu.MenuNumber) && \
 | |
|        (Index < MAX_MENU_NUMBER)) ; Index++) {  
 | |
|     NewMenuEntry      = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
 | |
|     NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;  
 | |
|     ConOutCheck[Index] = NewConsoleContext->IsActive;
 | |
|   }
 | |
| }
 | |
|   
 | |
| /**
 | |
| 
 | |
|   Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER]
 | |
|   in BMM_FAKE_NV_DATA structure.
 | |
| 
 | |
|   @param CallbackData    The BMM context data.
 | |
| 
 | |
| **/        
 | |
| VOID  
 | |
| GetConsoleErrCheck (
 | |
|   IN  BMM_CALLBACK_DATA    *CallbackData
 | |
|   )
 | |
| {
 | |
|   UINT16              Index;
 | |
|   BM_MENU_ENTRY       *NewMenuEntry; 
 | |
|   UINT8               *ConErrCheck;
 | |
|   BM_CONSOLE_CONTEXT  *NewConsoleContext;
 | |
|   
 | |
|   ASSERT (CallbackData != NULL);
 | |
|   ConErrCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
 | |
|   for (Index = 0; ((Index < ConsoleErrMenu.MenuNumber) && \
 | |
|        (Index < MAX_MENU_NUMBER)) ; Index++) {  
 | |
|     NewMenuEntry      = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
 | |
|     NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;  
 | |
|     ConErrCheck[Index] = NewConsoleContext->IsActive;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type)
 | |
|   to BMM_FAKE_NV_DATA structure.
 | |
| 
 | |
|   @param CallbackData    The BMM context data.
 | |
| 
 | |
| **/        
 | |
| VOID  
 | |
| GetTerminalAttribute (
 | |
|   IN  BMM_CALLBACK_DATA    *CallbackData
 | |
|   )
 | |
| {
 | |
|   BMM_FAKE_NV_DATA     *CurrentFakeNVMap;
 | |
|   BM_MENU_ENTRY        *NewMenuEntry;
 | |
|   BM_TERMINAL_CONTEXT  *NewTerminalContext;    
 | |
|   UINT16               TerminalIndex;  
 | |
|   UINT8                AttributeIndex;
 | |
| 
 | |
|   ASSERT (CallbackData != NULL);
 | |
|   
 | |
|   CurrentFakeNVMap = &CallbackData->BmmFakeNvData;     
 | |
|   for (TerminalIndex = 0; ((TerminalIndex < TerminalMenu.MenuNumber) && \
 | |
|        (TerminalIndex < MAX_MENU_NUMBER)); TerminalIndex++) {  
 | |
|     NewMenuEntry        = BOpt_GetMenuEntry (&TerminalMenu, TerminalIndex);
 | |
|     NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|     for (AttributeIndex = 0; AttributeIndex < sizeof (BaudRateList) / sizeof (BaudRateList [0]); AttributeIndex++) {
 | |
|       if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[AttributeIndex].Value)) {
 | |
|         NewTerminalContext->BaudRateIndex = AttributeIndex;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     for (AttributeIndex = 0; AttributeIndex < ARRAY_SIZE (DataBitsList); AttributeIndex++) {
 | |
|       if (NewTerminalContext->DataBits == (UINT64) (DataBitsList[AttributeIndex].Value)) {
 | |
|         NewTerminalContext->DataBitsIndex = AttributeIndex;
 | |
|         break;
 | |
|       }
 | |
|     }    
 | |
|     
 | |
|     for (AttributeIndex = 0; AttributeIndex < ARRAY_SIZE (ParityList); AttributeIndex++) {
 | |
|       if (NewTerminalContext->Parity == (UINT64) (ParityList[AttributeIndex].Value)) {
 | |
|         NewTerminalContext->ParityIndex = AttributeIndex;
 | |
|         break;
 | |
|       }
 | |
|     }            
 | |
|     
 | |
|     for (AttributeIndex = 0; AttributeIndex < ARRAY_SIZE (StopBitsList); AttributeIndex++) {
 | |
|       if (NewTerminalContext->StopBits == (UINT64) (StopBitsList[AttributeIndex].Value)) {
 | |
|         NewTerminalContext->StopBitsIndex = AttributeIndex;
 | |
|         break;
 | |
|       }
 | |
|     }        
 | |
|     CurrentFakeNVMap->COMBaudRate[TerminalIndex]     = NewTerminalContext->BaudRateIndex;
 | |
|     CurrentFakeNVMap->COMDataRate[TerminalIndex]     = NewTerminalContext->DataBitsIndex;
 | |
|     CurrentFakeNVMap->COMStopBits[TerminalIndex]     = NewTerminalContext->StopBitsIndex;
 | |
|     CurrentFakeNVMap->COMParity[TerminalIndex]       = NewTerminalContext->ParityIndex; 
 | |
|     CurrentFakeNVMap->COMTerminalType[TerminalIndex] = NewTerminalContext->TerminalType;
 | |
|     CurrentFakeNVMap->COMFlowControl[TerminalIndex]  = NewTerminalContext->FlowControl;
 | |
|   } 
 | |
| }
 | |
| 
 |