git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2368 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			841 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			841 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
Copyright (c) 2006, Intel Corporation                                                         
 | 
						|
All rights reserved. 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.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
    ConsoleOption.c
 | 
						|
    
 | 
						|
Abstract:
 | 
						|
 | 
						|
    handles console redirection from boot manager
 | 
						|
 | 
						|
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "BootMaint.h"
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL  *
 | 
						|
DevicePathInstanceDup (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
UpdateComAttributeFromVariable (
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
ChangeTerminalDevicePath (
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
 | 
						|
  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;
 | 
						|
  UINT32                    Match;
 | 
						|
  BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | 
						|
  BM_MENU_ENTRY             *NewMenuEntry;
 | 
						|
 | 
						|
  Match = EISA_PNP_ID (0x0501);
 | 
						|
  Node  = DevicePath;
 | 
						|
  Node  = NextDevicePathNode (Node);
 | 
						|
  Com   = 0;
 | 
						|
  while (!IsDevicePathEnd (Node)) {
 | 
						|
    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
 | 
						|
      Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | 
						|
      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
 | 
						|
        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
 | 
						|
    if (NULL == NewMenuEntry) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    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)
 | 
						|
        );
 | 
						|
      //
 | 
						|
      // 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;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
ChangeVariableDevicePath (
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Node;
 | 
						|
  ACPI_HID_DEVICE_PATH      *Acpi;
 | 
						|
  UART_DEVICE_PATH          *Uart;
 | 
						|
  UINTN                     Com;
 | 
						|
  UINT32                    Match;
 | 
						|
  BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | 
						|
  BM_MENU_ENTRY             *NewMenuEntry;
 | 
						|
 | 
						|
  Match = EISA_PNP_ID (0x0501);
 | 
						|
  Node  = DevicePath;
 | 
						|
  Node  = NextDevicePathNode (Node);
 | 
						|
  Com   = 0;
 | 
						|
  while (!IsDevicePathEnd (Node)) {
 | 
						|
    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
 | 
						|
      Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | 
						|
      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
 | 
						|
        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
 | 
						|
      NewMenuEntry = BOpt_GetMenuEntry (
 | 
						|
                      &TerminalMenu,
 | 
						|
                      Com
 | 
						|
                      );
 | 
						|
      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);
 | 
						|
  }
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
IsTerminalDevicePath (
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
 | 
						|
  OUT TYPE_OF_TERMINAL         *Termi,
 | 
						|
  OUT UINTN                    *Com
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
LocateSerialIo (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Build a list containing all serial devices 
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT8                     *Ptr;
 | 
						|
  UINTN                     Index;
 | 
						|
  UINTN                     Index2;
 | 
						|
  UINTN                     NoHandles;
 | 
						|
  EFI_HANDLE                *Handles;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  ACPI_HID_DEVICE_PATH      *Acpi;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  UINT32                    Match;
 | 
						|
  EFI_SERIAL_IO_PROTOCOL    *SerialIo;
 | 
						|
  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;
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < NoHandles; Index++) {
 | 
						|
    //
 | 
						|
    // Check to see whether the handle has DevicePath Protocol installed
 | 
						|
    //
 | 
						|
    gBS->HandleProtocol (
 | 
						|
          Handles[Index],
 | 
						|
          &gEfiDevicePathProtocolGuid,
 | 
						|
          (VOID**) &DevicePath
 | 
						|
          );
 | 
						|
    Ptr = (UINT8 *) DevicePath;
 | 
						|
    while (*Ptr != END_DEVICE_PATH_TYPE) {
 | 
						|
      Ptr++;
 | 
						|
    }
 | 
						|
 | 
						|
    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
 | 
						|
    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;
 | 
						|
    Match = EISA_PNP_ID (0x0501);
 | 
						|
 | 
						|
    if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
 | 
						|
      NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
 | 
						|
      if (!NewMenuEntry) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
 | 
						|
      CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
 | 
						|
      NewTerminalContext->DevicePath = DevicePathInstanceDup (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)
 | 
						|
        );
 | 
						|
      InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
 | 
						|
      TerminalMenu.MenuNumber++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // 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) {
 | 
						|
    UpdateComAttributeFromVariable (OutDevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  if (InpDevicePath) {
 | 
						|
    UpdateComAttributeFromVariable (InpDevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  if (ErrDevicePath) {
 | 
						|
    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, &Guid[Index2], sizeof (EFI_GUID));
 | 
						|
      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
 | 
						|
      NewDevicePath = AppendDevicePathNode (
 | 
						|
                        NewTerminalContext->DevicePath,
 | 
						|
                        (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
 | 
						|
                        );
 | 
						|
      SafeFreePool (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;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
UpdateComAttributeFromVariable (
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Update Com Ports attributes from DevicePath
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  DevicePath  -   DevicePath that contains Com ports
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Node;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *SerialNode;
 | 
						|
  ACPI_HID_DEVICE_PATH      *Acpi;
 | 
						|
  UART_DEVICE_PATH          *Uart;
 | 
						|
  UART_DEVICE_PATH          *Uart1;
 | 
						|
  UINT32                    Match;
 | 
						|
  UINTN                     TerminalNumber;
 | 
						|
  BM_MENU_ENTRY             *NewMenuEntry;
 | 
						|
  BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | 
						|
  UINTN                     Index;
 | 
						|
 | 
						|
  Match           = EISA_PNP_ID (0x0501);
 | 
						|
  Node            = DevicePath;
 | 
						|
  Node            = NextDevicePathNode (Node);
 | 
						|
  TerminalNumber  = 0;
 | 
						|
  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
 | 
						|
    while (!IsDevicePathEnd (Node)) {
 | 
						|
      if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
 | 
						|
        Acpi = (ACPI_HID_DEVICE_PATH *) Node;
 | 
						|
        if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
 | 
						|
          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)
 | 
						|
          );
 | 
						|
 | 
						|
        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)
 | 
						|
              );
 | 
						|
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          SerialNode = NextDevicePathNode (SerialNode);
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // end while
 | 
						|
        //
 | 
						|
      }
 | 
						|
 | 
						|
      Node = NextDevicePathNode (Node);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // end while
 | 
						|
    //
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
DevicePathInstanceDup (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Function creates a device path data structure that identically matches the 
 | 
						|
  device path passed in.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  DevPath      - A pointer to a device path data structure.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The new copy of DevPath is created to identically match the input.  
 | 
						|
  Otherwise, NULL is returned.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Temp;
 | 
						|
  UINT8                     *Ptr;
 | 
						|
  UINTN                     Size;
 | 
						|
 | 
						|
  //
 | 
						|
  // get the size of an instance from the input
 | 
						|
  //
 | 
						|
  Temp            = DevPath;
 | 
						|
  DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);
 | 
						|
 | 
						|
  //
 | 
						|
  // Make a copy and set proper end type
 | 
						|
  //
 | 
						|
  NewDevPath = NULL;
 | 
						|
  if (Size) {
 | 
						|
    NewDevPath = AllocateZeroPool (Size);
 | 
						|
    ASSERT (NewDevPath != NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  if (NewDevPath) {
 | 
						|
    CopyMem (NewDevPath, DevicePathInst, Size);
 | 
						|
    Ptr = (UINT8 *) NewDevPath;
 | 
						|
    Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
    Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
 | 
						|
    SetDevicePathEndNode (Temp);
 | 
						|
  }
 | 
						|
 | 
						|
  return NewDevPath;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
  BM_TERMINAL_CONTEXT       *NewTerminalContext;
 | 
						|
  TYPE_OF_TERMINAL          Terminal;
 | 
						|
  BM_MENU_ENTRY             *NewTerminalMenuEntry;
 | 
						|
  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 Out Devices
 | 
						|
  //
 | 
						|
  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 = DevicePathInstanceDup (DevicePathInst);
 | 
						|
    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
 | 
						|
                                    );
 | 
						|
    NewTerminalMenuEntry  = NULL;
 | 
						|
    NewTerminalContext    = NULL;
 | 
						|
 | 
						|
    if (NewConsoleContext->IsTerminal) {
 | 
						|
      BOpt_DestroyMenuEntry (NewMenuEntry);
 | 
						|
    } else {
 | 
						|
      Index2++;
 | 
						|
      ConsoleMenu->MenuNumber++;
 | 
						|
      InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetAllConsoles (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS 
 | 
						|
  Others
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);
 | 
						|
  GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);
 | 
						|
  GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
FreeAllConsoles (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS 
 | 
						|
  Others
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BOpt_FreeMenu (&ConsoleOutMenu);
 | 
						|
  BOpt_FreeMenu (&ConsoleInpMenu);
 | 
						|
  BOpt_FreeMenu (&ConsoleErrMenu);
 | 
						|
  BOpt_FreeMenu (&TerminalMenu);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
IsTerminalDevicePath (
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
 | 
						|
  OUT TYPE_OF_TERMINAL         *Termi,
 | 
						|
  OUT UINTN                    *Com
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Test whether DevicePath is a valid Terminal
 | 
						|
 | 
						|
Arguments:
 | 
						|
  DevicePath  -   DevicePath to be checked
 | 
						|
  Termi       -   If is terminal, give its type
 | 
						|
  Com         -   If is Com Port, give its type
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  TRUE        -   If DevicePath point to a Terminal
 | 
						|
  FALSE
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT8                 *Ptr;
 | 
						|
  BOOLEAN               IsTerminal;
 | 
						|
  VENDOR_DEVICE_PATH    *Vendor;
 | 
						|
  ACPI_HID_DEVICE_PATH  *Acpi;
 | 
						|
  UINT32                Match;
 | 
						|
  EFI_GUID              TempGuid;
 | 
						|
 | 
						|
  IsTerminal = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the Device Path, should be change later!!!
 | 
						|
  //
 | 
						|
  Ptr = (UINT8 *) DevicePath;
 | 
						|
  while (*Ptr != END_DEVICE_PATH_TYPE) {
 | 
						|
    Ptr++;
 | 
						|
  }
 | 
						|
 | 
						|
  Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);
 | 
						|
  Vendor  = (VENDOR_DEVICE_PATH *) Ptr;
 | 
						|
 | 
						|
  //
 | 
						|
  // There are four kinds of Terminal types
 | 
						|
  // check to see whether this devicepath
 | 
						|
  // is one of that type
 | 
						|
  //
 | 
						|
  CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));
 | 
						|
 | 
						|
  if (CompareGuid (&TempGuid, &Guid[0])) {
 | 
						|
    *Termi      = PC_ANSI;
 | 
						|
    IsTerminal  = TRUE;
 | 
						|
  } else {
 | 
						|
    if (CompareGuid (&TempGuid, &Guid[1])) {
 | 
						|
      *Termi      = VT_100;
 | 
						|
      IsTerminal  = TRUE;
 | 
						|
    } else {
 | 
						|
      if (CompareGuid (&TempGuid, &Guid[2])) {
 | 
						|
        *Termi      = VT_100_PLUS;
 | 
						|
        IsTerminal  = TRUE;
 | 
						|
      } else {
 | 
						|
        if (CompareGuid (&TempGuid, &Guid[3])) {
 | 
						|
          *Termi      = VT_UTF8;
 | 
						|
          IsTerminal  = TRUE;
 | 
						|
        } else {
 | 
						|
          IsTerminal = FALSE;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsTerminal) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
 | 
						|
  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;
 | 
						|
  Match = EISA_PNP_ID (0x0501);
 | 
						|
  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
 | 
						|
    CopyMem (Com, &Acpi->UID, sizeof (UINT32));
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 |