git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1215 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1215 lines
		
	
	
		
			34 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:
 | 
						|
 | 
						|
    Terminal.c
 | 
						|
    
 | 
						|
Abstract: 
 | 
						|
 | 
						|
Revision History:
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
 | 
						|
#include "Terminal.h"
 | 
						|
#include <Common/StatusCode.h>
 | 
						|
 | 
						|
//
 | 
						|
// Function Prototypes
 | 
						|
//
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalDriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalDriverBindingStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN  EFI_HANDLE                     Controller,
 | 
						|
  IN  UINTN                          NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                     *ChildHandleBuffer
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Globals
 | 
						|
//
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {
 | 
						|
  TerminalDriverBindingSupported,
 | 
						|
  TerminalDriverBindingStart,
 | 
						|
  TerminalDriverBindingStop,
 | 
						|
  0x10,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalDriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
 | 
						|
  EFI_SERIAL_IO_PROTOCOL    *SerialIo;
 | 
						|
  VENDOR_DEVICE_PATH        *Node;
 | 
						|
 | 
						|
  //
 | 
						|
  // If remaining device path is not NULL, then make sure it is a
 | 
						|
  // device path that describes a terminal communications protocol.
 | 
						|
  //
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
 | 
						|
    Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;
 | 
						|
 | 
						|
    if (Node->Header.Type != MESSAGING_DEVICE_PATH ||
 | 
						|
        Node->Header.SubType != MSG_VENDOR_DP ||
 | 
						|
        DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {
 | 
						|
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
 | 
						|
    //
 | 
						|
    if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&
 | 
						|
        !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&
 | 
						|
        !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&
 | 
						|
        !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {
 | 
						|
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed to perform the supported test
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &ParentDevicePath,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Controller,
 | 
						|
        &gEfiDevicePathProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Controller
 | 
						|
        );
 | 
						|
 | 
						|
  //
 | 
						|
  // The Controller must support the Serial I/O Protocol.
 | 
						|
  // This driver is a bus driver with at most 1 child device, so it is
 | 
						|
  // ok for it to be already started.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSerialIoProtocolGuid,
 | 
						|
                  (VOID **) &SerialIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Close the I/O Abstraction(s) used to perform the supported test
 | 
						|
  //
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Controller,
 | 
						|
        &gEfiSerialIoProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Controller
 | 
						|
        );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
    Start the controller.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
 | 
						|
    This                - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | 
						|
    Controller          - The handle of the controller to start.
 | 
						|
    RemainingDevicePath - A pointer to the remaining portion of a devcie path.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
    EFI_SUCCESS.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_SERIAL_IO_PROTOCOL              *SerialIo;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
 | 
						|
  VENDOR_DEVICE_PATH                  *Node;
 | 
						|
  VENDOR_DEVICE_PATH                  *DefaultNode;
 | 
						|
  EFI_SERIAL_IO_MODE                  *Mode;
 | 
						|
  UINTN                               SerialInTimeOut;
 | 
						|
  TERMINAL_DEV                        *TerminalDevice;
 | 
						|
  UINT8                               TerminalType;
 | 
						|
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
 | 
						|
  UINTN                               EntryCount;
 | 
						|
  UINTN                               Index;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
 | 
						|
 | 
						|
  TerminalDevice = NULL;
 | 
						|
  DefaultNode    = NULL;
 | 
						|
  //
 | 
						|
  // Get the Device Path Protocol to build the device path of the child device
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &ParentDevicePath,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Report that the remote terminal is being enabled
 | 
						|
  //
 | 
						|
  DevicePath = ParentDevicePath;
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_ENABLE,
 | 
						|
    DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the Serial I/O Protocol BY_DRIVER.  It might already be started.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSerialIoProtocolGuid,
 | 
						|
                  (VOID **) &SerialIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Status != EFI_ALREADY_STARTED) {
 | 
						|
    //
 | 
						|
    // If Serial I/O is not already open by this driver, then tag the handle
 | 
						|
    // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
 | 
						|
    // StdErrDev variables with the list of possible terminal types on this
 | 
						|
    // serial port.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiCallerIdGuid,
 | 
						|
                    NULL,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller,
 | 
						|
                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                      &Controller,
 | 
						|
                      &gEfiCallerIdGuid,
 | 
						|
                      DuplicateDevicePath (ParentDevicePath),
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        goto Error;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // if the serial device is a hot plug device, do not update the
 | 
						|
      // ConInDev, ConOutDev, and StdErrDev variables.
 | 
						|
      //
 | 
						|
      Status = gBS->OpenProtocol (
 | 
						|
                      Controller,
 | 
						|
                      &gEfiHotPlugDeviceGuid,
 | 
						|
                      NULL,
 | 
						|
                      This->DriverBindingHandle,
 | 
						|
                      Controller,
 | 
						|
                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        TerminalUpdateConsoleDevVariable ((CHAR16 *)VarConsoleInpDev, ParentDevicePath);
 | 
						|
        TerminalUpdateConsoleDevVariable ((CHAR16 *)VarConsoleOutDev, ParentDevicePath);
 | 
						|
        TerminalUpdateConsoleDevVariable ((CHAR16 *)VarErrorOutDev, ParentDevicePath);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Make sure a child handle does not already exist.  This driver can only
 | 
						|
  // produce one child per serial port.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocolInformation (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSerialIoProtocolGuid,
 | 
						|
                  &OpenInfoBuffer,
 | 
						|
                  &EntryCount
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
    for (Index = 0; Index < EntryCount; Index++) {
 | 
						|
      if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
 | 
						|
        Status = EFI_ALREADY_STARTED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->FreePool (OpenInfoBuffer);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If RemainingDevicePath is NULL, then create default device path node
 | 
						|
  //
 | 
						|
  if (RemainingDevicePath == NULL) {
 | 
						|
    DefaultNode = AllocatePool (sizeof (VENDOR_DEVICE_PATH));
 | 
						|
    if (DefaultNode == NULL) {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
    
 | 
						|
    CopyMem (&DefaultNode->Guid, &gEfiPcAnsiGuid, sizeof (EFI_GUID));
 | 
						|
    RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL*) DefaultNode;
 | 
						|
  }  
 | 
						|
  //
 | 
						|
  // Use the RemainingDevicePath to determine the terminal type
 | 
						|
  //
 | 
						|
  Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;
 | 
						|
 | 
						|
  if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {
 | 
						|
 | 
						|
    TerminalType = PcAnsiType;
 | 
						|
 | 
						|
  } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {
 | 
						|
 | 
						|
    TerminalType = VT100Type;
 | 
						|
 | 
						|
  } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {
 | 
						|
 | 
						|
    TerminalType = VT100PlusType;
 | 
						|
 | 
						|
  } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {
 | 
						|
 | 
						|
    TerminalType = VTUTF8Type;
 | 
						|
 | 
						|
  } else {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize the Terminal Dev
 | 
						|
  //
 | 
						|
  TerminalDevice = AllocatePool (sizeof (TERMINAL_DEV));
 | 
						|
  if (TerminalDevice == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (TerminalDevice, sizeof (TERMINAL_DEV));
 | 
						|
 | 
						|
  TerminalDevice->Signature     = TERMINAL_DEV_SIGNATURE;
 | 
						|
 | 
						|
  TerminalDevice->TerminalType  = TerminalType;
 | 
						|
 | 
						|
  TerminalDevice->SerialIo      = SerialIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Simple Input Protocol
 | 
						|
  //
 | 
						|
  TerminalDevice->SimpleInput.Reset         = TerminalConInReset;
 | 
						|
  TerminalDevice->SimpleInput.ReadKeyStroke = TerminalConInReadKeyStroke;
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EFI_EVENT_NOTIFY_WAIT,
 | 
						|
                  EFI_TPL_NOTIFY,
 | 
						|
                  TerminalConInWaitForKey,
 | 
						|
                  &TerminalDevice->SimpleInput,
 | 
						|
                  &TerminalDevice->SimpleInput.WaitForKey
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // initialize the FIFO buffer used for accommodating
 | 
						|
  // the pre-read pending characters
 | 
						|
  //
 | 
						|
  InitializeRawFiFo (TerminalDevice);
 | 
						|
  InitializeUnicodeFiFo (TerminalDevice);
 | 
						|
  InitializeEfiKeyFiFo (TerminalDevice);
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the timeout value of serial buffer for
 | 
						|
  // keystroke response performance issue
 | 
						|
  //
 | 
						|
  Mode            = TerminalDevice->SerialIo->Mode;
 | 
						|
 | 
						|
  SerialInTimeOut = 0;
 | 
						|
  if (Mode->BaudRate != 0) {
 | 
						|
    SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = TerminalDevice->SerialIo->SetAttributes (
 | 
						|
                                      TerminalDevice->SerialIo,
 | 
						|
                                      Mode->BaudRate,
 | 
						|
                                      Mode->ReceiveFifoDepth,
 | 
						|
                                      (UINT32) SerialInTimeOut,
 | 
						|
                                      Mode->Parity,
 | 
						|
                                      (UINT8) Mode->DataBits,
 | 
						|
                                      Mode->StopBits
 | 
						|
                                      );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // if set attributes operation fails, invalidate
 | 
						|
    // the value of SerialInTimeOut,thus make it
 | 
						|
    // inconsistent with the default timeout value
 | 
						|
    // of serial buffer. This will invoke the recalculation
 | 
						|
    // in the readkeystroke routine.
 | 
						|
    //
 | 
						|
    TerminalDevice->SerialInTimeOut = 0;
 | 
						|
  } else {
 | 
						|
    TerminalDevice->SerialInTimeOut = SerialInTimeOut;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Build the device path for the child device
 | 
						|
  //
 | 
						|
  Status = SetTerminalDevicePath (
 | 
						|
            TerminalDevice->TerminalType,
 | 
						|
            ParentDevicePath,
 | 
						|
            &TerminalDevice->DevicePath
 | 
						|
            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  DevicePath = TerminalDevice->DevicePath;
 | 
						|
 | 
						|
  Status = TerminalDevice->SimpleInput.Reset (
 | 
						|
                                        &TerminalDevice->SimpleInput,
 | 
						|
                                        FALSE
 | 
						|
                                        );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Need to report Error Code first
 | 
						|
    //
 | 
						|
    goto ReportError;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Simple Text Output Protocol
 | 
						|
  //
 | 
						|
  TerminalDevice->SimpleTextOutput.Reset              = TerminalConOutReset;
 | 
						|
  TerminalDevice->SimpleTextOutput.OutputString       = TerminalConOutOutputString;
 | 
						|
  TerminalDevice->SimpleTextOutput.TestString         = TerminalConOutTestString;
 | 
						|
  TerminalDevice->SimpleTextOutput.QueryMode          = TerminalConOutQueryMode;
 | 
						|
  TerminalDevice->SimpleTextOutput.SetMode            = TerminalConOutSetMode;
 | 
						|
  TerminalDevice->SimpleTextOutput.SetAttribute       = TerminalConOutSetAttribute;
 | 
						|
  TerminalDevice->SimpleTextOutput.ClearScreen        = TerminalConOutClearScreen;
 | 
						|
  TerminalDevice->SimpleTextOutput.SetCursorPosition  = TerminalConOutSetCursorPosition;
 | 
						|
  TerminalDevice->SimpleTextOutput.EnableCursor       = TerminalConOutEnableCursor;
 | 
						|
  TerminalDevice->SimpleTextOutput.Mode               = &TerminalDevice->SimpleTextOutputMode;
 | 
						|
 | 
						|
  TerminalDevice->SimpleTextOutputMode.MaxMode        = 1;
 | 
						|
  //
 | 
						|
  // For terminal devices, cursor is always visible
 | 
						|
  //
 | 
						|
  TerminalDevice->SimpleTextOutputMode.CursorVisible  = TRUE;
 | 
						|
  TerminalDevice->SimpleTextOutputMode.Attribute      = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK);
 | 
						|
 | 
						|
  Status = TerminalDevice->SimpleTextOutput.Reset (
 | 
						|
                                              &TerminalDevice->SimpleTextOutput,
 | 
						|
                                              FALSE
 | 
						|
                                              );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ReportError;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = TerminalDevice->SimpleTextOutput.SetMode (
 | 
						|
                                              &TerminalDevice->SimpleTextOutput,
 | 
						|
                                              0
 | 
						|
                                              );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ReportError;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = TerminalDevice->SimpleTextOutput.EnableCursor (
 | 
						|
                                              &TerminalDevice->SimpleTextOutput,
 | 
						|
                                              TRUE
 | 
						|
                                              );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ReportError;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  //
 | 
						|
  //
 | 
						|
  TerminalDevice->InputState  = INPUT_STATE_DEFAULT;
 | 
						|
  TerminalDevice->ResetState  = RESET_STATE_DEFAULT;
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EFI_EVENT_TIMER,
 | 
						|
                  EFI_TPL_CALLBACK,
 | 
						|
                  NULL,
 | 
						|
                  NULL,
 | 
						|
                  &TerminalDevice->TwoSecondTimeOut
 | 
						|
                  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Build the component name for the child device
 | 
						|
  //
 | 
						|
  TerminalDevice->ControllerNameTable = NULL;
 | 
						|
  switch (TerminalDevice->TerminalType) {
 | 
						|
  case PcAnsiType:
 | 
						|
    AddUnicodeString (
 | 
						|
      "eng",
 | 
						|
      gTerminalComponentName.SupportedLanguages,
 | 
						|
      &TerminalDevice->ControllerNameTable,
 | 
						|
      (CHAR16 *)L"PC-ANSI Serial Console"
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  case VT100Type:
 | 
						|
    AddUnicodeString (
 | 
						|
      "eng",
 | 
						|
      gTerminalComponentName.SupportedLanguages,
 | 
						|
      &TerminalDevice->ControllerNameTable,
 | 
						|
      (CHAR16 *)L"VT-100 Serial Console"
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  case VT100PlusType:
 | 
						|
    AddUnicodeString (
 | 
						|
      "eng",
 | 
						|
      gTerminalComponentName.SupportedLanguages,
 | 
						|
      &TerminalDevice->ControllerNameTable,
 | 
						|
      (CHAR16 *)L"VT-100+ Serial Console"
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  case VTUTF8Type:
 | 
						|
    AddUnicodeString (
 | 
						|
      "eng",
 | 
						|
      gTerminalComponentName.SupportedLanguages,
 | 
						|
      &TerminalDevice->ControllerNameTable,
 | 
						|
      (CHAR16 *)L"VT-UTF8 Serial Console"
 | 
						|
      );
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Install protocol interfaces for the serial device.
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &TerminalDevice->Handle,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  TerminalDevice->DevicePath,
 | 
						|
                  &gEfiSimpleTextInProtocolGuid,
 | 
						|
                  &TerminalDevice->SimpleInput,
 | 
						|
                  &gEfiSimpleTextOutProtocolGuid,
 | 
						|
                  &TerminalDevice->SimpleTextOutput,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // if the serial device is a hot plug device, attaches the HotPlugGuid
 | 
						|
  // onto the terminal device handle.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiHotPlugDeviceGuid,
 | 
						|
                  NULL,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                    &TerminalDevice->Handle,
 | 
						|
                    &gEfiHotPlugDeviceGuid,
 | 
						|
                    NULL,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Register the Parent-Child relationship via
 | 
						|
  // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSerialIoProtocolGuid,
 | 
						|
                  (VOID **) &TerminalDevice->SerialIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  TerminalDevice->Handle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DefaultNode != NULL) {
 | 
						|
    gBS->FreePool (DefaultNode);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ReportError:
 | 
						|
  //
 | 
						|
  // Report error code before exiting
 | 
						|
  //
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
    EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
 | 
						|
    DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
Error:
 | 
						|
  //
 | 
						|
  // Use the Stop() function to free all resources allocated in Start()
 | 
						|
  //
 | 
						|
  if (TerminalDevice != NULL) {
 | 
						|
 | 
						|
    if (TerminalDevice->Handle != NULL) {
 | 
						|
      This->Stop (This, Controller, 1, &TerminalDevice->Handle);
 | 
						|
    } else {
 | 
						|
 | 
						|
      if (TerminalDevice->TwoSecondTimeOut != NULL) {
 | 
						|
        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
 | 
						|
      }
 | 
						|
 | 
						|
      if (TerminalDevice->SimpleInput.WaitForKey != NULL) {
 | 
						|
        gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
 | 
						|
      }
 | 
						|
 | 
						|
      if (TerminalDevice->ControllerNameTable != NULL) {
 | 
						|
        FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
 | 
						|
      }
 | 
						|
 | 
						|
      if (TerminalDevice->DevicePath != NULL) {
 | 
						|
        gBS->FreePool (TerminalDevice->DevicePath);
 | 
						|
      }
 | 
						|
 | 
						|
      gBS->FreePool (TerminalDevice);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (DefaultNode != NULL) {
 | 
						|
    gBS->FreePool (DefaultNode);
 | 
						|
  }
 | 
						|
  
 | 
						|
  This->Stop (This, Controller, 0, NULL);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalDriverBindingStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
 | 
						|
  IN  EFI_HANDLE                    Controller,
 | 
						|
  IN  UINTN                         NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                    *ChildHandleBuffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
    Stop a device controller.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
 | 
						|
    This              - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | 
						|
    Controller        - A handle to the device being stopped.
 | 
						|
    NumberOfChildren  - The number of child device handles in ChildHandleBuffer.
 | 
						|
    ChildHandleBuffer - An array of child handles to be freed.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
    EFI_SUCCESS      - Operation successful.
 | 
						|
    EFI_DEVICE_ERROR - Devices error.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  UINTN                         Index;
 | 
						|
  BOOLEAN                       AllChildrenStopped;
 | 
						|
  EFI_SIMPLE_TEXT_OUT_PROTOCOL  *SimpleTextOutput;
 | 
						|
  TERMINAL_DEV                  *TerminalDevice;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *ParentDevicePath;
 | 
						|
  EFI_SERIAL_IO_PROTOCOL        *SerialIo;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &DevicePath
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Report that the remote terminal is being disabled
 | 
						|
  //
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_DISABLE,
 | 
						|
    DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Complete all outstanding transactions to Controller.
 | 
						|
  // Don't allow any new transaction to Controller to be started.
 | 
						|
  //
 | 
						|
  if (NumberOfChildren == 0) {
 | 
						|
    //
 | 
						|
    // Close the bus driver
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiCallerIdGuid,
 | 
						|
                    (VOID **) &ParentDevicePath,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Remove Parent Device Path from
 | 
						|
      // the Console Device Environment Variables
 | 
						|
      //
 | 
						|
      TerminalRemoveConsoleDevVariable ((CHAR16 *)VarConsoleInpDev, ParentDevicePath);
 | 
						|
      TerminalRemoveConsoleDevVariable ((CHAR16 *)VarConsoleOutDev, ParentDevicePath);
 | 
						|
      TerminalRemoveConsoleDevVariable ((CHAR16 *)VarErrorOutDev, ParentDevicePath);
 | 
						|
 | 
						|
      //
 | 
						|
      // Uninstall the Terminal Driver's GUID Tag from the Serial controller
 | 
						|
      //
 | 
						|
      Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                      Controller,
 | 
						|
                      &gEfiCallerIdGuid,
 | 
						|
                      ParentDevicePath,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
 | 
						|
      //
 | 
						|
      // Free the ParentDevicePath that was duplicated in Start()
 | 
						|
      //
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        gBS->FreePool (ParentDevicePath);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Controller,
 | 
						|
          &gEfiSerialIoProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Controller
 | 
						|
          );
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Controller,
 | 
						|
          &gEfiDevicePathProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Controller
 | 
						|
          );
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  AllChildrenStopped = TRUE;
 | 
						|
 | 
						|
  for (Index = 0; Index < NumberOfChildren; Index++) {
 | 
						|
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    ChildHandleBuffer[Index],
 | 
						|
                    &gEfiSimpleTextOutProtocolGuid,
 | 
						|
                    (VOID **) &SimpleTextOutput,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    ChildHandleBuffer[Index],
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
 | 
						|
      TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);
 | 
						|
 | 
						|
      gBS->CloseProtocol (
 | 
						|
            Controller,
 | 
						|
            &gEfiSerialIoProtocolGuid,
 | 
						|
            This->DriverBindingHandle,
 | 
						|
            ChildHandleBuffer[Index]
 | 
						|
            );
 | 
						|
 | 
						|
      Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                      ChildHandleBuffer[Index],
 | 
						|
                      &gEfiSimpleTextInProtocolGuid,
 | 
						|
                      &TerminalDevice->SimpleInput,
 | 
						|
                      &gEfiSimpleTextOutProtocolGuid,
 | 
						|
                      &TerminalDevice->SimpleTextOutput,
 | 
						|
                      &gEfiDevicePathProtocolGuid,
 | 
						|
                      TerminalDevice->DevicePath,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        gBS->OpenProtocol (
 | 
						|
              Controller,
 | 
						|
              &gEfiSerialIoProtocolGuid,
 | 
						|
              (VOID **) &SerialIo,
 | 
						|
              This->DriverBindingHandle,
 | 
						|
              ChildHandleBuffer[Index],
 | 
						|
              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
              );
 | 
						|
      } else {
 | 
						|
 | 
						|
        if (TerminalDevice->ControllerNameTable != NULL) {
 | 
						|
          FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
 | 
						|
        }
 | 
						|
 | 
						|
        Status = gBS->OpenProtocol (
 | 
						|
                        ChildHandleBuffer[Index],
 | 
						|
                        &gEfiHotPlugDeviceGuid,
 | 
						|
                        NULL,
 | 
						|
                        This->DriverBindingHandle,
 | 
						|
                        Controller,
 | 
						|
                        EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                        );
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                          ChildHandleBuffer[Index],
 | 
						|
                          &gEfiHotPlugDeviceGuid,
 | 
						|
                          NULL,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
        } else {
 | 
						|
          Status = EFI_SUCCESS;
 | 
						|
        }
 | 
						|
 | 
						|
        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
 | 
						|
        gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
 | 
						|
        gBS->FreePool (TerminalDevice->DevicePath);
 | 
						|
        gBS->FreePool (TerminalDevice);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      AllChildrenStopped = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!AllChildrenStopped) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
TerminalUpdateConsoleDevVariable (
 | 
						|
  IN CHAR16                    *VariableName,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  UINTN                     VariableSize;
 | 
						|
  UINT8                     TerminalType;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Variable;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewVariable;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
 | 
						|
 | 
						|
  Variable = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get global variable and its size according to the name given.
 | 
						|
  //
 | 
						|
  Variable = TerminalGetVariableAndSize (
 | 
						|
              VariableName,
 | 
						|
              &gEfiGlobalVariableGuid,
 | 
						|
              &VariableSize
 | 
						|
              );
 | 
						|
  //
 | 
						|
  // Append terminal device path onto the variable.
 | 
						|
  //
 | 
						|
  for (TerminalType = PcAnsiType; TerminalType <= VTUTF8Type; TerminalType++) {
 | 
						|
    SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);
 | 
						|
    NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);
 | 
						|
    if (Variable != NULL) {
 | 
						|
      gBS->FreePool (Variable);
 | 
						|
    }
 | 
						|
 | 
						|
    if (TempDevicePath != NULL) {
 | 
						|
      gBS->FreePool (TempDevicePath);
 | 
						|
    }
 | 
						|
 | 
						|
    Variable = NewVariable;
 | 
						|
  }
 | 
						|
 | 
						|
  VariableSize = GetDevicePathSize (Variable);
 | 
						|
 | 
						|
  Status = gRT->SetVariable (
 | 
						|
                  VariableName,
 | 
						|
                  &gEfiGlobalVariableGuid,
 | 
						|
                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
 | 
						|
                  VariableSize,
 | 
						|
                  Variable
 | 
						|
                  );
 | 
						|
  gBS->FreePool (Variable);
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
TerminalRemoveConsoleDevVariable (
 | 
						|
  IN CHAR16                    *VariableName,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Remove console device variable.
 | 
						|
    
 | 
						|
  Arguments:
 | 
						|
 | 
						|
    VariableName     - A pointer to the variable name.
 | 
						|
    ParentDevicePath - A pointer to the parent device path.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  BOOLEAN                   FoundOne;
 | 
						|
  BOOLEAN                   Match;
 | 
						|
  UINTN                     VariableSize;
 | 
						|
  UINTN                     InstanceSize;
 | 
						|
  UINT8                     TerminalType;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Instance;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Variable;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *OriginalVariable;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewVariable;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *SavedNewVariable;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
 | 
						|
 | 
						|
  Variable  = NULL;
 | 
						|
  Instance  = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get global variable and its size according to the name given.
 | 
						|
  //
 | 
						|
  Variable = TerminalGetVariableAndSize (
 | 
						|
              VariableName,
 | 
						|
              &gEfiGlobalVariableGuid,
 | 
						|
              &VariableSize
 | 
						|
              );
 | 
						|
  if (Variable == NULL) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  FoundOne          = FALSE;
 | 
						|
  OriginalVariable  = Variable;
 | 
						|
  NewVariable       = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get first device path instance from Variable
 | 
						|
  //
 | 
						|
  Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);
 | 
						|
  if (Instance == NULL) {
 | 
						|
    gBS->FreePool (OriginalVariable);
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Loop through all the device path instances of Variable
 | 
						|
  //
 | 
						|
  do {
 | 
						|
    //
 | 
						|
    // Loop through all the terminal types that this driver supports
 | 
						|
    //
 | 
						|
    Match = FALSE;
 | 
						|
    for (TerminalType = PcAnsiType; TerminalType <= VTUTF8Type; TerminalType++) {
 | 
						|
 | 
						|
      SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);
 | 
						|
 | 
						|
      //
 | 
						|
      // Compare the genterated device path to the current device path instance
 | 
						|
      //
 | 
						|
      if (TempDevicePath != NULL) {
 | 
						|
        if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {
 | 
						|
          Match     = TRUE;
 | 
						|
          FoundOne  = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        gBS->FreePool (TempDevicePath);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If a match was not found, then keep the current device path instance
 | 
						|
    //
 | 
						|
    if (!Match) {
 | 
						|
      SavedNewVariable  = NewVariable;
 | 
						|
      NewVariable       = AppendDevicePathInstance (NewVariable, Instance);
 | 
						|
      if (SavedNewVariable != NULL) {
 | 
						|
        gBS->FreePool (SavedNewVariable);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get next device path instance from Variable
 | 
						|
    //
 | 
						|
    gBS->FreePool (Instance);
 | 
						|
    Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);
 | 
						|
  } while (Instance != NULL);
 | 
						|
 | 
						|
  gBS->FreePool (OriginalVariable);
 | 
						|
 | 
						|
  if (FoundOne) {
 | 
						|
    VariableSize = GetDevicePathSize (NewVariable);
 | 
						|
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    VariableName,
 | 
						|
                    &gEfiGlobalVariableGuid,
 | 
						|
                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
 | 
						|
                    VariableSize,
 | 
						|
                    NewVariable
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  if (NewVariable != NULL) {
 | 
						|
    gBS->FreePool (NewVariable);
 | 
						|
  }
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
VOID *
 | 
						|
TerminalGetVariableAndSize (
 | 
						|
  IN  CHAR16              *Name,
 | 
						|
  IN  EFI_GUID            *VendorGuid,
 | 
						|
  OUT UINTN               *VariableSize
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
 | 
						|
  buffer, and the size of the buffer. On failure return NULL.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Name       - String part of EFI variable name
 | 
						|
 | 
						|
  VendorGuid - GUID part of EFI variable name
 | 
						|
 | 
						|
  VariableSize - Returns the size of the EFI variable that was read
 | 
						|
 | 
						|
Returns:
 | 
						|
  Dynamically allocated memory that contains a copy of the EFI variable.
 | 
						|
  Caller is repsoncible freeing the buffer.
 | 
						|
 | 
						|
  NULL - Variable was not read
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       BufferSize;
 | 
						|
  VOID        *Buffer;
 | 
						|
 | 
						|
  Buffer = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Pass in a small size buffer to find the actual variable size.
 | 
						|
  //
 | 
						|
  BufferSize  = 1;
 | 
						|
  Buffer      = AllocatePool (BufferSize);
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    *VariableSize = 0;
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    *VariableSize = BufferSize;
 | 
						|
    return Buffer;
 | 
						|
 | 
						|
  } else if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
    //
 | 
						|
    // Allocate the buffer to return
 | 
						|
    //
 | 
						|
    gBS->FreePool (Buffer);
 | 
						|
    Buffer = AllocatePool (BufferSize);
 | 
						|
    if (Buffer == NULL) {
 | 
						|
      *VariableSize = 0;
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Read variable into the allocated buffer.
 | 
						|
    //
 | 
						|
    Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      BufferSize = 0;
 | 
						|
      gBS->FreePool (Buffer);
 | 
						|
      Buffer = NULL;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Variable not found or other errors met.
 | 
						|
    //
 | 
						|
    BufferSize = 0;
 | 
						|
    gBS->FreePool (Buffer);
 | 
						|
    Buffer = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  *VariableSize = BufferSize;
 | 
						|
  return Buffer;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
SetTerminalDevicePath (
 | 
						|
  IN  UINT8                       TerminalType,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL    *ParentDevicePath,
 | 
						|
  OUT EFI_DEVICE_PATH_PROTOCOL    **TerminalDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  VENDOR_DEVICE_PATH  Node;
 | 
						|
 | 
						|
  *TerminalDevicePath = NULL;
 | 
						|
  Node.Header.Type    = MESSAGING_DEVICE_PATH;
 | 
						|
  Node.Header.SubType = MSG_VENDOR_DP;
 | 
						|
 | 
						|
  //
 | 
						|
  // generate terminal device path node according to terminal type.
 | 
						|
  //
 | 
						|
  switch (TerminalType) {
 | 
						|
 | 
						|
  case PcAnsiType:
 | 
						|
    CopyMem (
 | 
						|
      &Node.Guid,
 | 
						|
      &gEfiPcAnsiGuid,
 | 
						|
      sizeof (EFI_GUID)
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  case VT100Type:
 | 
						|
    CopyMem (
 | 
						|
      &Node.Guid,
 | 
						|
      &gEfiVT100Guid,
 | 
						|
      sizeof (EFI_GUID)
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  case VT100PlusType:
 | 
						|
    CopyMem (
 | 
						|
      &Node.Guid,
 | 
						|
      &gEfiVT100PlusGuid,
 | 
						|
      sizeof (EFI_GUID)
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  case VTUTF8Type:
 | 
						|
    CopyMem (
 | 
						|
      &Node.Guid,
 | 
						|
      &gEfiVTUTF8Guid,
 | 
						|
      sizeof (EFI_GUID)
 | 
						|
      );
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  SetDevicePathNodeLength (
 | 
						|
    &Node.Header,
 | 
						|
    sizeof (VENDOR_DEVICE_PATH)
 | 
						|
    );
 | 
						|
  //
 | 
						|
  // append the terminal node onto parent device path
 | 
						|
  // to generate a complete terminal device path.
 | 
						|
  //
 | 
						|
  *TerminalDevicePath = AppendDevicePathNode (
 | 
						|
                          ParentDevicePath,
 | 
						|
                          (EFI_DEVICE_PATH_PROTOCOL *) &Node
 | 
						|
                          );
 | 
						|
  if (*TerminalDevicePath == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
InitializeRawFiFo (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Make the raw fifo empty.
 | 
						|
  //
 | 
						|
  TerminalDevice->RawFiFo.Head = TerminalDevice->RawFiFo.Tail;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
InitializeUnicodeFiFo (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Make the unicode fifo empty
 | 
						|
  //
 | 
						|
  TerminalDevice->UnicodeFiFo.Head = TerminalDevice->UnicodeFiFo.Tail;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
InitializeEfiKeyFiFo (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Make the efi key fifo empty
 | 
						|
  //
 | 
						|
  TerminalDevice->EfiKeyFiFo.Head = TerminalDevice->EfiKeyFiFo.Tail;
 | 
						|
}
 |