Loading fastboot/device/flashing.cpp +22 −14 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ void WipeOverlayfsForPartition(FastbootDevice* device, const std::string& partit } // namespace int FlashRawDataChunk(int fd, const char* data, size_t len) { int FlashRawDataChunk(PartitionHandle* handle, const char* data, size_t len) { size_t ret = 0; const size_t max_write_size = 1048576; void* aligned_buffer; Loading @@ -91,7 +91,15 @@ int FlashRawDataChunk(int fd, const char* data, size_t len) { while (ret < len) { int this_len = std::min(max_write_size, len - ret); memcpy(aligned_buffer_unique_ptr.get(), data, this_len); int this_ret = write(fd, aligned_buffer_unique_ptr.get(), this_len); // In case of non 4KB aligned writes, reopen without O_DIRECT flag if (this_len & 0xFFF) { if (handle->Reset(O_WRONLY) != true) { PLOG(ERROR) << "Failed to reset file descriptor"; return -1; } } int this_ret = write(handle->fd(), aligned_buffer_unique_ptr.get(), this_len); if (this_ret < 0) { PLOG(ERROR) << "Failed to flash data of len " << len; return -1; Loading @@ -102,8 +110,8 @@ int FlashRawDataChunk(int fd, const char* data, size_t len) { return 0; } int FlashRawData(int fd, const std::vector<char>& downloaded_data) { int ret = FlashRawDataChunk(fd, downloaded_data.data(), downloaded_data.size()); int FlashRawData(PartitionHandle* handle, const std::vector<char>& downloaded_data) { int ret = FlashRawDataChunk(handle, downloaded_data.data(), downloaded_data.size()); if (ret < 0) { return -errno; } Loading @@ -111,30 +119,30 @@ int FlashRawData(int fd, const std::vector<char>& downloaded_data) { } int WriteCallback(void* priv, const void* data, size_t len) { int fd = reinterpret_cast<long long>(priv); PartitionHandle* handle = reinterpret_cast<PartitionHandle*>(priv); if (!data) { return lseek64(fd, len, SEEK_CUR) >= 0 ? 0 : -errno; return lseek64(handle->fd(), len, SEEK_CUR) >= 0 ? 0 : -errno; } return FlashRawDataChunk(fd, reinterpret_cast<const char*>(data), len); return FlashRawDataChunk(handle, reinterpret_cast<const char*>(data), len); } int FlashSparseData(int fd, std::vector<char>& downloaded_data) { int FlashSparseData(PartitionHandle* handle, std::vector<char>& downloaded_data) { struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), downloaded_data.size(), true, false); if (!file) { // Invalid sparse format return -EINVAL; } return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(fd)); return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(handle)); } int FlashBlockDevice(int fd, std::vector<char>& downloaded_data) { lseek64(fd, 0, SEEK_SET); int FlashBlockDevice(PartitionHandle* handle, std::vector<char>& downloaded_data) { lseek64(handle->fd(), 0, SEEK_SET); if (downloaded_data.size() >= sizeof(SPARSE_HEADER_MAGIC) && *reinterpret_cast<uint32_t*>(downloaded_data.data()) == SPARSE_HEADER_MAGIC) { return FlashSparseData(fd, downloaded_data); return FlashSparseData(handle, downloaded_data); } else { return FlashRawData(fd, downloaded_data); return FlashRawData(handle, downloaded_data); } } Loading Loading @@ -181,7 +189,7 @@ int Flash(FastbootDevice* device, const std::string& partition_name) { if (android::base::GetProperty("ro.system.build.type", "") != "user") { WipeOverlayfsForPartition(device, partition_name); } int result = FlashBlockDevice(handle.fd(), data); int result = FlashBlockDevice(&handle, data); sync(); return result; } Loading fastboot/device/utility.cpp +1 −8 Original line number Diff line number Diff line Loading @@ -90,14 +90,7 @@ bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHan return false; } flags |= (O_EXCL | O_CLOEXEC | O_BINARY); unique_fd fd(TEMP_FAILURE_RETRY(open(handle->path().c_str(), flags))); if (fd < 0) { PLOG(ERROR) << "Failed to open block device: " << handle->path(); return false; } handle->set_fd(std::move(fd)); return true; return handle->Open(flags); } std::optional<std::string> FindPhysicalPartition(const std::string& name) { Loading fastboot/device/utility.h +43 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <optional> #include <string> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/unique_fd.h> #include <android/hardware/boot/1.0/IBootControl.h> #include <fstab/fstab.h> Loading @@ -44,11 +46,51 @@ class PartitionHandle { } const std::string& path() const { return path_; } int fd() const { return fd_.get(); } void set_fd(android::base::unique_fd&& fd) { fd_ = std::move(fd); } bool Open(int flags) { flags |= (O_EXCL | O_CLOEXEC | O_BINARY); // Attempts to open a second device can fail with EBUSY if the device is already open. // Explicitly close any previously opened devices as unique_fd won't close them until // after the attempt to open. fd_.reset(); fd_ = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path_.c_str(), flags))); if (fd_ < 0) { PLOG(ERROR) << "Failed to open block device: " << path_; return false; } flags_ = flags; return true; } bool Reset(int flags) { if (fd_.ok() && (flags | O_EXCL | O_CLOEXEC | O_BINARY) == flags_) { return true; } off_t offset = fd_.ok() ? lseek(fd_.get(), 0, SEEK_CUR) : 0; if (offset < 0) { PLOG(ERROR) << "Failed lseek on block device: " << path_; return false; } sync(); if (Open(flags) == false) { return false; } if (lseek(fd_.get(), offset, SEEK_SET) != offset) { PLOG(ERROR) << "Failed lseek on block device: " << path_; return false; } return true; } private: std::string path_; android::base::unique_fd fd_; int flags_; std::function<void()> closer_; }; Loading Loading
fastboot/device/flashing.cpp +22 −14 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ void WipeOverlayfsForPartition(FastbootDevice* device, const std::string& partit } // namespace int FlashRawDataChunk(int fd, const char* data, size_t len) { int FlashRawDataChunk(PartitionHandle* handle, const char* data, size_t len) { size_t ret = 0; const size_t max_write_size = 1048576; void* aligned_buffer; Loading @@ -91,7 +91,15 @@ int FlashRawDataChunk(int fd, const char* data, size_t len) { while (ret < len) { int this_len = std::min(max_write_size, len - ret); memcpy(aligned_buffer_unique_ptr.get(), data, this_len); int this_ret = write(fd, aligned_buffer_unique_ptr.get(), this_len); // In case of non 4KB aligned writes, reopen without O_DIRECT flag if (this_len & 0xFFF) { if (handle->Reset(O_WRONLY) != true) { PLOG(ERROR) << "Failed to reset file descriptor"; return -1; } } int this_ret = write(handle->fd(), aligned_buffer_unique_ptr.get(), this_len); if (this_ret < 0) { PLOG(ERROR) << "Failed to flash data of len " << len; return -1; Loading @@ -102,8 +110,8 @@ int FlashRawDataChunk(int fd, const char* data, size_t len) { return 0; } int FlashRawData(int fd, const std::vector<char>& downloaded_data) { int ret = FlashRawDataChunk(fd, downloaded_data.data(), downloaded_data.size()); int FlashRawData(PartitionHandle* handle, const std::vector<char>& downloaded_data) { int ret = FlashRawDataChunk(handle, downloaded_data.data(), downloaded_data.size()); if (ret < 0) { return -errno; } Loading @@ -111,30 +119,30 @@ int FlashRawData(int fd, const std::vector<char>& downloaded_data) { } int WriteCallback(void* priv, const void* data, size_t len) { int fd = reinterpret_cast<long long>(priv); PartitionHandle* handle = reinterpret_cast<PartitionHandle*>(priv); if (!data) { return lseek64(fd, len, SEEK_CUR) >= 0 ? 0 : -errno; return lseek64(handle->fd(), len, SEEK_CUR) >= 0 ? 0 : -errno; } return FlashRawDataChunk(fd, reinterpret_cast<const char*>(data), len); return FlashRawDataChunk(handle, reinterpret_cast<const char*>(data), len); } int FlashSparseData(int fd, std::vector<char>& downloaded_data) { int FlashSparseData(PartitionHandle* handle, std::vector<char>& downloaded_data) { struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), downloaded_data.size(), true, false); if (!file) { // Invalid sparse format return -EINVAL; } return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(fd)); return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(handle)); } int FlashBlockDevice(int fd, std::vector<char>& downloaded_data) { lseek64(fd, 0, SEEK_SET); int FlashBlockDevice(PartitionHandle* handle, std::vector<char>& downloaded_data) { lseek64(handle->fd(), 0, SEEK_SET); if (downloaded_data.size() >= sizeof(SPARSE_HEADER_MAGIC) && *reinterpret_cast<uint32_t*>(downloaded_data.data()) == SPARSE_HEADER_MAGIC) { return FlashSparseData(fd, downloaded_data); return FlashSparseData(handle, downloaded_data); } else { return FlashRawData(fd, downloaded_data); return FlashRawData(handle, downloaded_data); } } Loading Loading @@ -181,7 +189,7 @@ int Flash(FastbootDevice* device, const std::string& partition_name) { if (android::base::GetProperty("ro.system.build.type", "") != "user") { WipeOverlayfsForPartition(device, partition_name); } int result = FlashBlockDevice(handle.fd(), data); int result = FlashBlockDevice(&handle, data); sync(); return result; } Loading
fastboot/device/utility.cpp +1 −8 Original line number Diff line number Diff line Loading @@ -90,14 +90,7 @@ bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHan return false; } flags |= (O_EXCL | O_CLOEXEC | O_BINARY); unique_fd fd(TEMP_FAILURE_RETRY(open(handle->path().c_str(), flags))); if (fd < 0) { PLOG(ERROR) << "Failed to open block device: " << handle->path(); return false; } handle->set_fd(std::move(fd)); return true; return handle->Open(flags); } std::optional<std::string> FindPhysicalPartition(const std::string& name) { Loading
fastboot/device/utility.h +43 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <optional> #include <string> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/unique_fd.h> #include <android/hardware/boot/1.0/IBootControl.h> #include <fstab/fstab.h> Loading @@ -44,11 +46,51 @@ class PartitionHandle { } const std::string& path() const { return path_; } int fd() const { return fd_.get(); } void set_fd(android::base::unique_fd&& fd) { fd_ = std::move(fd); } bool Open(int flags) { flags |= (O_EXCL | O_CLOEXEC | O_BINARY); // Attempts to open a second device can fail with EBUSY if the device is already open. // Explicitly close any previously opened devices as unique_fd won't close them until // after the attempt to open. fd_.reset(); fd_ = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path_.c_str(), flags))); if (fd_ < 0) { PLOG(ERROR) << "Failed to open block device: " << path_; return false; } flags_ = flags; return true; } bool Reset(int flags) { if (fd_.ok() && (flags | O_EXCL | O_CLOEXEC | O_BINARY) == flags_) { return true; } off_t offset = fd_.ok() ? lseek(fd_.get(), 0, SEEK_CUR) : 0; if (offset < 0) { PLOG(ERROR) << "Failed lseek on block device: " << path_; return false; } sync(); if (Open(flags) == false) { return false; } if (lseek(fd_.get(), offset, SEEK_SET) != offset) { PLOG(ERROR) << "Failed lseek on block device: " << path_; return false; } return true; } private: std::string path_; android::base::unique_fd fd_; int flags_; std::function<void()> closer_; }; Loading