/** Write BufferSize bytes from Lba into Buffer. This function writes the requested number of blocks to the device. All blocks are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA, EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is being used, the Event associated with this request will not be signaled. @param[in] This Indicates a pointer to the calling context. @param[in] MediaId The media ID that the write request is for. @param[in] Lba The starting logical block address to be written. The caller is responsible for writing to only legitimate locations. @param[in, out] Token A pointer to the token associated with the transaction. @param[in] BufferSize Size of Buffer, must be a multiple of device block size. @param[in] Buffer A pointer to the source buffer for the data. @retval EFI_SUCCESS The write request was queued if Event is not NULL. The data was written correctly to the device if the Event is NULL. @retval EFI_WRITE_PROTECTED The device can not be written to. @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_DEVICE_ERROR The device reported an error while performing the write. @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 LBAs that are not valid, or the buffer is not on proper alignment. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. **/ EFI_STATUS EFIAPI PartitionWriteBlocksEx ( IN EFI_BLOCK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, IN VOID *Buffer ) { PARTITION_PRIVATE_DATA *Private; UINT64 Offset; UINT32 UnderRun; Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This); if (Token == NULL) { return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_INVALID_PARAMETER); } if (BufferSize % Private->BlockSize != 0) { return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_BAD_BUFFER_SIZE); } Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start; if (Offset + BufferSize > Private->End) { return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_INVALID_PARAMETER); } // // Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must // be multiple of BlockSize. If the Spec will be updated the DiskIO to support // BlockIO2, this limitation will be removed and call DiskIO here. // Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun); if (UnderRun != 0) { return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_UNSUPPORTED); } // // Because some kinds of partition have different block size from their parent, // in that case it couldn't call parent Block I/O2. // if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) { return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_UNSUPPORTED); } return Private->ParentBlockIo2->WriteBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer); }
/** Read BufferSize bytes from Lba into Buffer. This function reads the requested number of blocks from the device. All the blocks are read, or an error is returned. If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and non-blocking I/O is being used, the Event associated with this request will not be signaled. @param[in] This Indicates a pointer to the calling context. @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, out] Token A pointer to the token associated with the transaction. @param[in] BufferSize Size of Buffer, must be a multiple of device block size. @param[out] 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 read request was queued if Token->Event is not NULL.The data was read correctly from the device if the Token->Event is NULL. @retval EFI_DEVICE_ERROR The device reported an error while performing the read. @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. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. **/ EFI_STATUS EFIAPI PartitionReadBlocksEx ( IN EFI_BLOCK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, OUT VOID *Buffer ) { EFI_STATUS Status; PARTITION_PRIVATE_DATA *Private; UINT64 Offset; PARTITION_ACCESS_TASK *Task; Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This); if (BufferSize % Private->BlockSize != 0) { return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE); } Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start; if (Offset + BufferSize > Private->End) { return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER); } if ((Token != NULL) && (Token->Event != NULL)) { Task = PartitionCreateAccessTask (Token); if (Task == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer); if (EFI_ERROR (Status)) { gBS->CloseEvent (Task->DiskIo2Token.Event); FreePool (Task); } } else { Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer); } return Status; }