terminal.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,176 行 · 第 1/3 页

C
1,176
字号
    goto Error;
  }
  EfiZeroMem(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;
  }

  Status = TerminalDevice->SimpleInput.Reset (
                                    &TerminalDevice->SimpleInput, 
                                    FALSE
                                    );
  if (EFI_ERROR (Status)) {   
    goto Error;
  }

  //
  // 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 Error;
  }
  Status = TerminalDevice->SimpleTextOutput.SetMode (
                                    &TerminalDevice->SimpleTextOutput,
                                    0
                                    );
  if (EFI_ERROR (Status)) {   
    goto Error;
  }
  Status = TerminalDevice->SimpleTextOutput.EnableCursor (
                                    &TerminalDevice->SimpleTextOutput,
                                    TRUE
                                    );
  if (EFI_ERROR (Status)) {   
    goto Error;
  }

  //
  //
  //
  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 device path for the child device
  //
  Status = SetTerminalDevicePath (
                          TerminalDevice->TerminalType,
                          ParentDevicePath,
                          &TerminalDevice->DevicePath
                          );
  if (EFI_ERROR(Status)) {
    goto Error;
  }

  //
  // Build the component name for the child device
  //
  TerminalDevice->ControllerNameTable = NULL;
  switch (TerminalDevice->TerminalType) {
  case PcAnsiType:
    EfiLibAddUnicodeString (
      "eng", 
      gTerminalComponentName.SupportedLanguages, 
      &TerminalDevice->ControllerNameTable, 
      L"PC-ANSI Serial Console"
      );
    break;
  case VT100Type:
    EfiLibAddUnicodeString (
      "eng", 
      gTerminalComponentName.SupportedLanguages, 
      &TerminalDevice->ControllerNameTable, 
      L"VT-100 Serial Console"
      );
    break;
  case VT100PlusType:
    EfiLibAddUnicodeString (
      "eng", 
      gTerminalComponentName.SupportedLanguages, 
      &TerminalDevice->ControllerNameTable, 
      L"VT-100+ Serial Console"
      );
    break;
  case VTUTF8Type:
    EfiLibAddUnicodeString (
      "eng", 
      gTerminalComponentName.SupportedLanguages, 
      &TerminalDevice->ControllerNameTable, 
      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;
  }

  return EFI_SUCCESS;   
  
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) {
        EfiLibFreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
      }
      
      gBS->FreePool (TerminalDevice);
    }
  }
  
  This->Stop (This, Controller, 0, NULL);           
  return Status;
}

EFI_STATUS
TerminalDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN  EFI_HANDLE                    Controller,
  IN  UINTN                         NumberOfChildren,
  IN  EFI_HANDLE                    *ChildHandleBuffer
  )

/*++

  Routine Description:

  Arguments:

  Returns:

--*/

{
  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;

  //
  // 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,     
                    &gTerminalDriverGuid,  
                    (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 (VarConsoleInpDev, ParentDevicePath);
      TerminalRemoveConsoleDevVariable (VarConsoleOutDev, ParentDevicePath);
      TerminalRemoveConsoleDevVariable (VarErrorOutDev,   ParentDevicePath);

      //
      // Uninstall the Terminal Driver's GUID Tag from the Serial controller
      //
      Status = gBS->UninstallMultipleProtocolInterfaces (
                      Controller,
                      &gTerminalDriverGuid, 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,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?