示例#1
0
/**
  Write by using the Disk IO protocol on the parent device. Lba addresses
  must be converted to byte offsets.

  @param[in]  This       Protocol instance pointer.
  @param[in]  MediaId    Id of the media, changes every time the media is replaced.
  @param[in]  Lba        The starting Logical Block Address to read from
  @param[in]  BufferSize Size of Buffer, must be a multiple of device block size.
  @param[in]  Buffer     Buffer containing data to be written to device.

  @retval EFI_SUCCESS           The data was written correctly to the device.
  @retval EFI_WRITE_PROTECTED   The device can not be written to.
  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
  @retval EFI_NO_MEDIA          There is no media in the device.
  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
  @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
                                valid for the device.

**/
EFI_STATUS
EFIAPI
PartitionWriteBlocks (
  IN EFI_BLOCK_IO_PROTOCOL  *This,
  IN UINT32                 MediaId,
  IN EFI_LBA                Lba,
  IN UINTN                  BufferSize,
  IN VOID                  *Buffer
  )
{
  PARTITION_PRIVATE_DATA  *Private;
  UINT64                  Offset;

  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);

  if (BufferSize % Private->BlockSize != 0) {
    return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
  }

  Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
  if (Offset + BufferSize > Private->End) {
    return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
  }
  //
  // Because some kinds of partition have different block size from their parent
  // device, we call the Disk IO protocol on the parent device, not the Block IO
  // protocol
  //
  return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
}
示例#2
0
/**
  Flush the parent Block Device.

  @param  This              Protocol instance pointer.

  @retval EFI_SUCCESS       All outstanding data was written to the device
  @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
  @retval EFI_NO_MEDIA      There is no media in the device.

**/
EFI_STATUS
EFIAPI
PartitionFlushBlocks (
  IN EFI_BLOCK_IO_PROTOCOL  *This
  )
{
  PARTITION_PRIVATE_DATA  *Private;

  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);

  return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
}
示例#3
0
/**
  Reset the Block Device.

  @param  This                 Protocol instance pointer.
  @param  ExtendedVerification Driver may perform diagnostics on reset.

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

**/
EFI_STATUS
EFIAPI
PartitionReset (
  IN EFI_BLOCK_IO_PROTOCOL  *This,
  IN BOOLEAN                ExtendedVerification
  )
{
  PARTITION_PRIVATE_DATA  *Private;

  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);

  return Private->ParentBlockIo->Reset (
                                  Private->ParentBlockIo,
                                  ExtendedVerification
                                  );
}
示例#4
0
/**
  Stop this driver on ControllerHandle. Support stopping any child handles
  created by this driver.

  @param  This              Protocol instance pointer.
  @param  ControllerHandle  Handle of device to stop driver on
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
                            children is zero stop the entire bus driver.
  @param  ChildHandleBuffer List of Child Handles to Stop.

  @retval EFI_SUCCESS       This driver is removed ControllerHandle
  @retval other             This driver was not removed from this device

**/
EFI_STATUS
EFIAPI
PartitionDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN  EFI_HANDLE                    ControllerHandle,
  IN  UINTN                         NumberOfChildren,
  IN  EFI_HANDLE                    *ChildHandleBuffer
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;
  BOOLEAN                 AllChildrenStopped;
  PARTITION_PRIVATE_DATA  *Private;
  EFI_DISK_IO_PROTOCOL    *DiskIo;

  BlockIo  = NULL;
  BlockIo2 = NULL;
  Private = NULL;

  if (NumberOfChildren == 0) {
    //
    // Close the bus driver
    //
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDiskIoProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    //
    // Close Parent BlockIO2 if has.
    //    
    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiDiskIo2ProtocolGuid,
           This->DriverBindingHandle,
           ControllerHandle
           );

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

  AllChildrenStopped = TRUE;
  for (Index = 0; Index < NumberOfChildren; Index++) {
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIoProtocolGuid,
           (VOID **) &BlockIo,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           );
    //
    // Try to locate BlockIo2.
    //
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIo2ProtocolGuid,
           (VOID **) &BlockIo2,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           ); 


    Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);

    Status = gBS->CloseProtocol (
                    ControllerHandle,
                    &gEfiDiskIoProtocolGuid,
                    This->DriverBindingHandle,
                    ChildHandleBuffer[Index]
                    );
    //
    // All Software protocols have be freed from the handle so remove it.
    // Remove the BlockIo Protocol if has.
    // Remove the BlockIo2 Protocol if has.
    //
    if (BlockIo2 != NULL) {
      BlockIo->FlushBlocks (BlockIo);
      BlockIo2->FlushBlocksEx (BlockIo2, NULL);
      Status = gBS->UninstallMultipleProtocolInterfaces (
                       ChildHandleBuffer[Index],
                       &gEfiDevicePathProtocolGuid,
                       Private->DevicePath,
                       &gEfiBlockIoProtocolGuid,
                       &Private->BlockIo,
                       &gEfiBlockIo2ProtocolGuid,
                       &Private->BlockIo2,
                       Private->EspGuid,
                       NULL,
                       NULL
                       );
    } else {
      BlockIo->FlushBlocks (BlockIo);
      Status = gBS->UninstallMultipleProtocolInterfaces (
                       ChildHandleBuffer[Index],
                       &gEfiDevicePathProtocolGuid,
                       Private->DevicePath,
                       &gEfiBlockIoProtocolGuid,
                       &Private->BlockIo,
                       Private->EspGuid,
                       NULL,
                       NULL
                       );
    }

    if (EFI_ERROR (Status)) {
      gBS->OpenProtocol (
             ControllerHandle,
             &gEfiDiskIoProtocolGuid,
             (VOID **) &DiskIo,
             This->DriverBindingHandle,
             ChildHandleBuffer[Index],
             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
             );
    } else {
      FreePool (Private->DevicePath);
      FreePool (Private);
    }

    if (EFI_ERROR (Status)) {
      AllChildrenStopped = FALSE;
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}
示例#5
0
文件: Partition.c 项目: lersek/edk2
/**
  Stop this driver on ControllerHandle. Support stopping any child handles
  created by this driver.

  @param  This              Protocol instance pointer.
  @param  ControllerHandle  Handle of device to stop driver on
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
                            children is zero stop the entire bus driver.
  @param  ChildHandleBuffer List of Child Handles to Stop.

  @retval EFI_SUCCESS       This driver is removed ControllerHandle
  @retval other             This driver was not removed from this device

**/
EFI_STATUS
EFIAPI
PartitionDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN  EFI_HANDLE                    ControllerHandle,
  IN  UINTN                         NumberOfChildren,
  IN  EFI_HANDLE                    *ChildHandleBuffer
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;
  BOOLEAN                 AllChildrenStopped;
  PARTITION_PRIVATE_DATA  *Private;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  EFI_GUID                *TypeGuid;

  BlockIo  = NULL;
  BlockIo2 = NULL;
  Private = NULL;

  if (NumberOfChildren == 0) {
    //
    // In the case of re-entry of the PartitionDriverBindingStop, the
    // NumberOfChildren may not reflect the actual number of children on the
    // bus driver. Hence, additional check is needed here.
    //
    if (HasChildren (ControllerHandle)) {
      DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n"));
      return EFI_DEVICE_ERROR;
    }

    //
    // Close the bus driver
    //
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDiskIoProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    //
    // Close Parent BlockIO2 if has.
    //
    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiDiskIo2ProtocolGuid,
           This->DriverBindingHandle,
           ControllerHandle
           );

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

  AllChildrenStopped = TRUE;
  for (Index = 0; Index < NumberOfChildren; Index++) {
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIoProtocolGuid,
           (VOID **) &BlockIo,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           );
    //
    // Try to locate BlockIo2.
    //
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIo2ProtocolGuid,
           (VOID **) &BlockIo2,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           );


    Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
    if (Private->InStop) {
      //
      // If the child handle is going to be stopped again during the re-entry
      // of DriverBindingStop, just do nothing.
      //
      break;
    }
    Private->InStop = TRUE;

    BlockIo->FlushBlocks (BlockIo);

    if (BlockIo2 != NULL) {
      Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL);
      DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status));
    } else {
      Status = EFI_SUCCESS;
    }

    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiDiskIoProtocolGuid,
           This->DriverBindingHandle,
           ChildHandleBuffer[Index]
           );

    if (IsZeroGuid (&Private->TypeGuid)) {
      TypeGuid = NULL;
    } else {
      TypeGuid = &Private->TypeGuid;
    }

    //
    // All Software protocols have be freed from the handle so remove it.
    // Remove the BlockIo Protocol if has.
    // Remove the BlockIo2 Protocol if has.
    //
    if (BlockIo2 != NULL) {
      //
      // Some device drivers might re-install the BlockIO(2) protocols for a
      // media change condition. Therefore, if the FlushBlocksEx returned with
      // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential
      // reference of already stopped child handle.
      //
      if (Status != EFI_MEDIA_CHANGED) {
        Status = gBS->UninstallMultipleProtocolInterfaces (
                         ChildHandleBuffer[Index],
                         &gEfiDevicePathProtocolGuid,
                         Private->DevicePath,
                         &gEfiBlockIoProtocolGuid,
                         &Private->BlockIo,
                         &gEfiBlockIo2ProtocolGuid,
                         &Private->BlockIo2,
                         &gEfiPartitionInfoProtocolGuid,
                         &Private->PartitionInfo,
                         TypeGuid,
                         NULL,
                         NULL
                         );
      }
    } else {
      Status = gBS->UninstallMultipleProtocolInterfaces (
                       ChildHandleBuffer[Index],
                       &gEfiDevicePathProtocolGuid,
                       Private->DevicePath,
                       &gEfiBlockIoProtocolGuid,
                       &Private->BlockIo,
                       &gEfiPartitionInfoProtocolGuid,
                       &Private->PartitionInfo,
                       TypeGuid,
                       NULL,
                       NULL
                       );
    }

    if (EFI_ERROR (Status)) {
      Private->InStop = FALSE;
      gBS->OpenProtocol (
             ControllerHandle,
             &gEfiDiskIoProtocolGuid,
             (VOID **) &DiskIo,
             This->DriverBindingHandle,
             ChildHandleBuffer[Index],
             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
             );
    } else {
      FreePool (Private->DevicePath);
      FreePool (Private);
    }

    if (EFI_ERROR (Status)) {
      AllChildrenStopped = FALSE;
      if (Status == EFI_MEDIA_CHANGED) {
        break;
      }
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}