Exemplo n.º 1
0
/**
  Reset the block device.

  This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
  It resets the block device hardware.
  ExtendedVerification is ignored in this implementation.

  @param  This                   Indicates a pointer to the calling context.
  @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive
                                 verification operation of the device during reset.

  @retval EFI_SUCCESS            The block device was reset.
  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and could not be reset.

**/
EFI_STATUS
EFIAPI
UsbMassReset (
  IN EFI_BLOCK_IO_PROTOCOL    *This,
  IN BOOLEAN                  ExtendedVerification
  )
{
  USB_MASS_DEVICE *UsbMass;
  EFI_TPL         OldTpl;
  EFI_STATUS      Status;

  //
  // Raise TPL to TPL_CALLBACK to serialize all its operations
  // to protect shared data structures.
  //
  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);

  UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
  Status  = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);

  gBS->RestoreTPL (OldTpl);

  return Status;
}
Exemplo n.º 2
0
/**
  Reads the requested number of blocks from the device.

  This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
  It reads the requested number of blocks from the device.
  All the blocks are read, or an error is returned.

  @param  This                   Indicates a pointer to the calling context.
  @param  MediaId                The media ID that the read request is for.
  @param  Lba                    The starting logical block address to read from on the device.
  @param  BufferSize             The size of the Buffer in bytes.
                                 This must be a multiple of the intrinsic block size of the device.
  @param  Buffer                 A pointer to the destination buffer for the data. The caller is
                                 responsible for either having implicit or explicit ownership of the buffer.

  @retval EFI_SUCCESS            The data was read correctly from the device.
  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the read operation.
  @retval EFI_NO_MEDIA           There is no media in the device.
  @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
  @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic block size of the device.
  @retval EFI_INVALID_PARAMETER  The read request contains LBAs that are not valid,
                                 or the buffer is not on proper alignment.

**/
EFI_STATUS
EFIAPI
UsbMassReadBlocks (
  IN EFI_BLOCK_IO_PROTOCOL    *This,
  IN UINT32                   MediaId,
  IN EFI_LBA                  Lba,
  IN UINTN                    BufferSize,
  OUT VOID                    *Buffer
  )
{
  USB_MASS_DEVICE     *UsbMass;
  EFI_BLOCK_IO_MEDIA  *Media;
  EFI_STATUS          Status;
  EFI_TPL             OldTpl;
  UINTN               TotalBlock;

  //
  // Raise TPL to TPL_CALLBACK to serialize all its operations
  // to protect shared data structures.
  //
  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);
  UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
  Media   = &UsbMass->BlockIoMedia;

  //
  // If it is a removable media, such as CD-Rom or Usb-Floppy,
  // need to detect the media before each read/write. While some of
  // Usb-Flash is marked as removable media.
  //
  if (Media->RemovableMedia) {
    Status = UsbBootDetectMedia (UsbMass);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }
  }

  if (!(Media->MediaPresent)) {
    Status = EFI_NO_MEDIA;
    goto ON_EXIT;
  }

  if (MediaId != Media->MediaId) {
    Status = EFI_MEDIA_CHANGED;
    goto ON_EXIT;
  }

  if (BufferSize == 0) {
    Status = EFI_SUCCESS;
    goto ON_EXIT;
  }

  if (Buffer == NULL) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  }

  //
  // BufferSize must be a multiple of the intrinsic block size of the device.
  //
  if ((BufferSize % Media->BlockSize) != 0) {
    Status = EFI_BAD_BUFFER_SIZE;
    goto ON_EXIT;
  }

  TotalBlock = BufferSize / Media->BlockSize;

  //
  // Make sure the range to read is valid.
  //
  if (Lba + TotalBlock - 1 > Media->LastBlock) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  }

  if (UsbMass->Cdb16Byte) {
    Status = UsbBootReadBlocks16 (UsbMass, Lba, TotalBlock, Buffer);
  } else {
    Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
  }

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));
    UsbMassReset (This, TRUE);
  }

ON_EXIT:
  gBS->RestoreTPL (OldTpl);
  return Status;
}
Exemplo n.º 3
0
/**
  Stop controlling the device.

  @param  This                   The USB mass storage driver binding
  @param  Controller             The device controller controlled by the driver.
  @param  NumberOfChildren       The number of children of this device
  @param  ChildHandleBuffer      The buffer of children handle.

  @retval EFI_SUCCESS            The driver stopped from controlling the device.
  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.
  @retval EFI_UNSUPPORTED        Block I/O Protocol is not installed on Controller.
  @retval Others                 Failed to stop the driver

**/
EFI_STATUS
EFIAPI
USBMassDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
  IN  EFI_HANDLE                  Controller,
  IN  UINTN                       NumberOfChildren,
  IN  EFI_HANDLE                  *ChildHandleBuffer
  )
{
  EFI_STATUS            Status;
  USB_MASS_DEVICE       *UsbMass;
  EFI_USB_IO_PROTOCOL   *UsbIo;
  EFI_BLOCK_IO_PROTOCOL *BlockIo;
  UINTN                 Index;
  BOOLEAN               AllChildrenStopped;

  //
  // This is a bus driver stop function since multi-lun is supported.
  // There are three kinds of device handles that might be passed:
  // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)
  // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)
  // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).
  //
  if (NumberOfChildren == 0) {
    //
    // A handle without any children, might be 1st and 2nd type.
    //
    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiBlockIoProtocolGuid,
                    (VOID **) &BlockIo,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );

    if (EFI_ERROR(Status)) {
      //
      // This is a 2nd type handle(multi-lun root), it needs to close devicepath
      // and usbio protocol.
      //
      gBS->CloseProtocol (
            Controller,
            &gEfiDevicePathProtocolGuid,
            This->DriverBindingHandle,
            Controller
            );
      gBS->CloseProtocol (
            Controller,
            &gEfiUsbIoProtocolGuid,
            This->DriverBindingHandle,
            Controller
            );
      DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));
      return EFI_SUCCESS;
    }

    //
    // This is a 1st type handle(non-multi-lun), which only needs to uninstall
    // Block I/O Protocol, close USB I/O Protocol and free mass device.
    //
    UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);

    //
    // Uninstall Block I/O protocol from the device handle,
    // then call the transport protocol to stop itself.
    //
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    Controller,
                    &gEfiBlockIoProtocolGuid,
                    &UsbMass->BlockIo,
                    &gEfiDiskInfoProtocolGuid,
                    &UsbMass->DiskInfo,
                    NULL
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    gBS->CloseProtocol (
          Controller,
          &gEfiUsbIoProtocolGuid,
          This->DriverBindingHandle,
          Controller
          );

    UsbMass->Transport->CleanUp (UsbMass->Context);
    FreePool (UsbMass);

    DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));
    return EFI_SUCCESS;
  }

  //
  // This is a 3rd type handle(multi-lun), which needs uninstall
  // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
  // free mass device for all children.
  //
  AllChildrenStopped = TRUE;

  for (Index = 0; Index < NumberOfChildren; Index++) {

    Status = gBS->OpenProtocol (
                    ChildHandleBuffer[Index],
                    &gEfiBlockIoProtocolGuid,
                    (VOID **) &BlockIo,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      AllChildrenStopped = FALSE;
      DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32)Index));
      continue;
    }

    UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);

    gBS->CloseProtocol (
           Controller,
           &gEfiUsbIoProtocolGuid,
           This->DriverBindingHandle,
           ChildHandleBuffer[Index]
           );

    Status = gBS->UninstallMultipleProtocolInterfaces (
                    ChildHandleBuffer[Index],
                    &gEfiDevicePathProtocolGuid,
                    UsbMass->DevicePath,
                    &gEfiBlockIoProtocolGuid,
                    &UsbMass->BlockIo,
                    &gEfiDiskInfoProtocolGuid,
                    &UsbMass->DiskInfo,
                    NULL
                    );

    if (EFI_ERROR (Status)) {
      //
      // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.
      //
      AllChildrenStopped = FALSE;
      DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));

      gBS->OpenProtocol (
             Controller,
             &gEfiUsbIoProtocolGuid,
             (VOID **) &UsbIo,
             This->DriverBindingHandle,
             ChildHandleBuffer[Index],
             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
             );
    } else {
      //
      // Succeed to stop this multi-lun handle, so go on with next child.
      //
      if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {
        UsbMass->Transport->CleanUp (UsbMass->Context);
      }
      FreePool (UsbMass);
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32) NumberOfChildren));
  return EFI_SUCCESS;
}
Exemplo n.º 4
0
/***
  Get all USB devices in system.

  @param[out]  DeviceList  - Linked list of USB devices.
  @param[out]  MaxDevices  - Number of USB devices in linked list.
  
  @retval  EFI_SUCCESS	The function exited normally.
  @retval  Other     	  An error occurred.
***/
EFI_STATUS
UsbGetAllUsbDevices (   
  OUT LIST_ENTRY     *DeviceList,
  OUT UINTN          *MaxDevices
  )
{
  EFI_STATUS              Status;
  DISK_ENTRY              *DiskEntry = NULL;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo = NULL;
  EFI_DEVICE_PATH         *DevPath = NULL;
  EFI_DEVICE_PATH         *TmpPath = NULL;
  EFI_HANDLE              *HandleBuffer;
    
  UINTN       NumberHandles, Index; 
  UINTN       NumDevices = 0;
  
  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &NumberHandles, &HandleBuffer);
  if (EFI_ERROR (Status)) {	
    ERROR (L"Error on locating handles of gEfiDevicePathProtocolGuid\n");
    return Status;
  }
  
  for (Index = 0; Index < NumberHandles; Index++) {
    Status = gBS->HandleProtocol (
                      HandleBuffer[Index], 
                      &gEfiDevicePathProtocolGuid, 
                      (VOID**)&DevPath
                      );
    if (!EFI_ERROR (Status)) {
      TmpPath = DevPath;
      while (!IsDevicePathEnd (TmpPath)) {
        if (DevicePathType (TmpPath) == MESSAGING_DEVICE_PATH && 
            (DevicePathSubType (TmpPath) == MSG_USB_DP ||
            DevicePathSubType (TmpPath) == MSG_USB_CLASS_DP ||
            DevicePathSubType (TmpPath) == MSG_USB_WWID_DP ||
            DevicePathSubType (TmpPath) == MSG_DEVICE_LOGICAL_UNIT_DP)) {
          //Open BlockIo protocol
          Status = gBS->OpenProtocol (
                        HandleBuffer[Index], 
                        &gEfiBlockIoProtocolGuid, 
                        (VOID**)&BlockIo, 
                        gImageHandle, 
                        NULL, 
                        EFI_OPEN_PROTOCOL_GET_PROTOCOL
                        );
          if (!EFI_ERROR (Status) && BlockIo != NULL) {
            //A USB partition will be also detected like a USB device. we only get USB devices.
            if ((USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo))->Signature == USB_MASS_SIGNATURE) {
              DBG ("An USB device.\n");
              NumDevices++;
              DiskEntry = (DISK_ENTRY*)AllocatePool (sizeof (DISK_ENTRY));
              DiskEntry->DiskInfo.DiskHandle = HandleBuffer[Index];
              DiskEntry->DiskInfo.DiskIndex = NumDevices;
              DiskEntry->DiskInfo.BlockIo = BlockIo;
              DiskEntry->DiskInfo.MaxPartitions = 0;
              InsertTailList (DeviceList, &DiskEntry->Link);
            }
          }
        } //end if()
        TmpPath = NextDevicePathNode (TmpPath);
      } //end while()
    } 
  } //end for()
  
  *MaxDevices = NumDevices;
  
  return EFI_SUCCESS;
}