debugport.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 874 行 · 第 1/2 页

C
874
字号
      "Hello World from the DebugPort driver\n\n"
      );
  }
  )

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
DebugPortStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN  EFI_HANDLE                     ControllerHandle,
  IN  UINTN                          NumberOfChildren,
  IN  EFI_HANDLE                     *ChildHandleBuffer
  )
/*++

Routine Description:
  We're never intending to be stopped via the driver model so this just returns
  EFI_UNSUPPORTED

Arguments:
  Per EFI 1.10 driver model
  
Returns:
  EFI_UNSUPPORTED
  EFI_SUCCESS
  
--*/
{
  EFI_STATUS  Status;

  if (NumberOfChildren == 0) {
    //
    // Close the bus driver
    //
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiSerialIoProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );

    gDebugPortDevice->SerialIoBinding = NULL;

    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );

    gBS->FreePool (gDebugPortDevice->DebugPortDevicePath);

    return EFI_SUCCESS;
  } else {
    //
    // Disconnect SerialIo child handle
    //
    Status = gBS->CloseProtocol (
                    gDebugPortDevice->SerialIoDeviceHandle,
                    &gEfiSerialIoProtocolGuid,
                    This->DriverBindingHandle,
                    gDebugPortDevice->DebugPortDeviceHandle
                    );

    if (EFI_ERROR (Status)) {
      return Status;
    }
    //
    // Unpublish our protocols (DevicePath, DebugPort)
    //
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    gDebugPortDevice->DebugPortDeviceHandle,
                    &gEfiDevicePathProtocolGuid,
                    gDebugPortDevice->DebugPortDevicePath,
                    &gEfiDebugPortProtocolGuid,
                    &gDebugPortDevice->DebugPortInterface,
                    NULL
                    );

    if (EFI_ERROR (Status)) {
      gBS->OpenProtocol (
            ControllerHandle,
            &gEfiSerialIoProtocolGuid,
            &gDebugPortDevice->SerialIoBinding,
            This->DriverBindingHandle,
            gDebugPortDevice->DebugPortDeviceHandle,
            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
            );
    } else {
      gDebugPortDevice->DebugPortDeviceHandle = NULL;
    }
  }

  return Status;
}
//
// Debugport protocol member functions
//
EFI_STATUS
EFIAPI
DebugPortReset (
  IN EFI_DEBUGPORT_PROTOCOL   *This
  )
/*++

Routine Description:
  DebugPort protocol member function.  Calls SerialIo:GetControl to flush buffer.
  We cannot call SerialIo:SetAttributes because it uses pool services, which use
  locks, which affect TPL, so it's not interrupt context safe or re-entrant.
  SerialIo:Reset() calls SetAttributes, so it can't be used either.
  
  The port itself should be fine since it was set up during initialization.  
  
Arguments:
  This

Returns:

  EFI_SUCCESS

--*/
{
  DEBUGPORT_DEVICE  *DebugPortDevice;
  UINTN             BufferSize;
  UINTN             BitBucket;

  DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
  while (This->Poll (This) == EFI_SUCCESS) {
    BufferSize = 1;
    This->Read (This, 0, &BufferSize, &BitBucket);
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
DebugPortRead (
  IN EFI_DEBUGPORT_PROTOCOL   *This,
  IN UINT32                   Timeout,
  IN OUT UINTN                *BufferSize,
  IN VOID                     *Buffer
  )
/*++

Routine Description:
  DebugPort protocol member function.  Calls SerialIo:Read() after setting
  if it's different than the last SerialIo access.
  
Arguments:
  IN EFI_DEBUGPORT_PROTOCOL   *This
  IN UINT32                   Timeout,
  IN OUT UINTN                *BufferSize,
  IN VOID                     *Buffer

Returns:

  EFI_STATUS

--*/
{
  DEBUGPORT_DEVICE  *DebugPortDevice;
  UINTN             LocalBufferSize;
  EFI_STATUS        Status;
  UINT8             *BufferPtr;

  DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
  BufferPtr       = Buffer;
  LocalBufferSize = *BufferSize;
  do {
    Status = DebugPortDevice->SerialIoBinding->Read (
                                                DebugPortDevice->SerialIoBinding,
                                                &LocalBufferSize,
                                                BufferPtr
                                                );
    if (Status == EFI_TIMEOUT) {
      if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) {
        Timeout -= DEBUGPORT_UART_DEFAULT_TIMEOUT;
      } else {
        Timeout = 0;
      }
    } else if (EFI_ERROR (Status)) {
      break;
    }

    BufferPtr += LocalBufferSize;
    LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *) Buffer);
  } while (LocalBufferSize != 0 && Timeout > 0);

  *BufferSize = (UINTN) (BufferPtr - (UINT8 *) Buffer);

  return Status;
}

EFI_STATUS
EFIAPI
DebugPortWrite (
  IN EFI_DEBUGPORT_PROTOCOL   *This,
  IN UINT32                   Timeout,
  IN OUT UINTN                *BufferSize,
  OUT VOID                    *Buffer
  )
/*++

Routine Description:
  DebugPort protocol member function.  Calls SerialIo:Write() Writes 8 bytes at
  a time and does a GetControl between 8 byte writes to help insure reads are
  interspersed This is poor-man's flow control..
  
Arguments:
  This               - Pointer to DebugPort protocol
  Timeout            - Timeout value
  BufferSize         - On input, the size of Buffer. 
                       On output, the amount of data actually written.
  Buffer             - Pointer to buffer to write

Returns:
  EFI_SUCCESS        - The data was written.
  EFI_DEVICE_ERROR   - The device reported an error.
  EFI_TIMEOUT        - The data write was stopped due to a timeout.

--*/
{
  DEBUGPORT_DEVICE  *DebugPortDevice;
  UINTN             Position;
  UINTN             WriteSize;
  EFI_STATUS        Status;
  UINT32            SerialControl;

  Status          = EFI_SUCCESS;
  DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);

  WriteSize       = 8;
  for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) {
    DebugPortDevice->SerialIoBinding->GetControl (
                                        DebugPortDevice->SerialIoBinding,
                                        &SerialControl
                                        );
    if (*BufferSize - Position < 8) {
      WriteSize = *BufferSize - Position;
    }

    Status = DebugPortDevice->SerialIoBinding->Write (
                                                DebugPortDevice->SerialIoBinding,
                                                &WriteSize,
                                                &((UINT8 *) Buffer)[Position]
                                                );
  }

  *BufferSize = Position;
  return Status;
}

EFI_STATUS
EFIAPI
DebugPortPoll (
  IN EFI_DEBUGPORT_PROTOCOL   *This
  )
/*++

Routine Description:
  DebugPort protocol member function.  Calls SerialIo:Write() after setting
  if it's different than the last SerialIo access.
  
Arguments:
  IN EFI_DEBUGPORT_PROTOCOL   *This

Returns:
  EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
  EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
  EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)

--*/
{
  EFI_STATUS        Status;
  UINT32            SerialControl;
  DEBUGPORT_DEVICE  *DebugPortDevice;

  DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);

  Status = DebugPortDevice->SerialIoBinding->GetControl (
                                              DebugPortDevice->SerialIoBinding,
                                              &SerialControl
                                              );

  if (!EFI_ERROR (Status)) {
    if (SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) {
      Status = EFI_NOT_READY;
    } else {
      Status = EFI_SUCCESS;
    }
  }

  return Status;
}
//
// Misc. functions local to this module..
//
STATIC
VOID
GetDebugPortVariable (
  DEBUGPORT_DEVICE            *DebugPortDevice
  )
/*++

Routine Description:
  Local worker function to obtain device path information from DebugPort variable.
  Records requested settings in DebugPort device structure.
  
Arguments:
  DEBUGPORT_DEVICE  *DebugPortDevice,

Returns:

  Nothing

--*/
{
  UINTN                     DataSize;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  EFI_STATUS                Status;

  DataSize = 0;

  Status = gRT->GetVariable (
                  EFI_DEBUGPORT_VARIABLE_NAME,
                  &gEfiDebugPortVariableGuid,
                  NULL,
                  &DataSize,
                  DebugPortDevice->DebugPortVariable
                  );

  if (Status == EFI_BUFFER_TOO_SMALL) {
    if (gDebugPortDevice->DebugPortVariable != NULL) {
      gBS->FreePool (gDebugPortDevice->DebugPortVariable);
    }

    DebugPortDevice->DebugPortVariable = EfiLibAllocatePool (DataSize);
    if (DebugPortDevice->DebugPortVariable != NULL) {
      gRT->GetVariable (
            EFI_DEBUGPORT_VARIABLE_NAME,
            &gEfiDebugPortVariableGuid,
            NULL,
            &DataSize,
            DebugPortDevice->DebugPortVariable
            );
      DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DebugPortDevice->DebugPortVariable;
      while (!EfiIsDevicePathEnd (DevicePath) && !EfiIsUartDevicePath (DevicePath)) {
        DevicePath = EfiNextDevicePathNode (DevicePath);
      }

      if (EfiIsDevicePathEnd (DevicePath)) {
        gBS->FreePool (gDebugPortDevice->DebugPortVariable);
        DebugPortDevice->DebugPortVariable = NULL;
      } else {
        gBS->CopyMem (
              &DebugPortDevice->BaudRate,
              &((UART_DEVICE_PATH *) DevicePath)->BaudRate,
              sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate)
              );
        DebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
        DebugPortDevice->Timeout          = DEBUGPORT_UART_DEFAULT_TIMEOUT;
        gBS->CopyMem (
              &DebugPortDevice->Parity,
              &((UART_DEVICE_PATH *) DevicePath)->Parity,
              sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity)
              );
        gBS->CopyMem (
              &DebugPortDevice->DataBits,
              &((UART_DEVICE_PATH *) DevicePath)->DataBits,
              sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits)
              );
        gBS->CopyMem (
              &DebugPortDevice->StopBits,
              &((UART_DEVICE_PATH *) DevicePath)->StopBits,
              sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits)
              );
      }
    }
  }
}

STATIC
EFI_STATUS
EFIAPI
ImageUnloadHandler (
  EFI_HANDLE ImageHandle
  )
/*++

Routine Description:
  Unload function that is registered in the LoadImage protocol.  It un-installs
  protocols produced and deallocates pool used by the driver.  Called by the core
  when unloading the driver.
  
Arguments:
  EFI_HANDLE ImageHandle

Returns:

  EFI_SUCCESS

--*/
{
  EFI_STATUS  Status;

  if (gDebugPortDevice->SerialIoBinding != NULL) {
    return EFI_ABORTED;
  }

  Status = gBS->UninstallMultipleProtocolInterfaces (
                  ImageHandle,
                  &gEfiDriverBindingProtocolGuid,
                  &gDebugPortDevice->DriverBindingInterface,
                  &gEfiComponentNameProtocolGuid,
                  &gDebugPortDevice->ComponentNameInterface,
                  NULL
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Clean up allocations
  //
  if (gDebugPortDevice->DebugPortVariable != NULL) {
    gBS->FreePool (gDebugPortDevice->DebugPortVariable);
  }

  gBS->FreePool (gDebugPortDevice);

  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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