From bfeb752c73fc71686f137738424cf7d0534b058e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=98=E7=BD=97=E5=AE=87?= Date: Thu, 5 Jun 2025 09:20:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:chunk=E6=96=B0=E5=A2=9E=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 甘罗宇 --- services/stream_update/BUILD.gn | 1 + services/stream_update/bin_chunk_update.cpp | 146 +++++++++++++++++++- services/stream_update/bin_chunk_update.h | 19 +++ 3 files changed, 161 insertions(+), 5 deletions(-) diff --git a/services/stream_update/BUILD.gn b/services/stream_update/BUILD.gn index aabb0996..2d5890e2 100755 --- a/services/stream_update/BUILD.gn +++ b/services/stream_update/BUILD.gn @@ -55,6 +55,7 @@ ohos_static_library("libbinchunkupdate") { "init:libbegetutil_static", "init:libfsmanager_static_real", "openssl:libcrypto_static", + "zlib:libz", ] public_configs = [ ":libstreamupdate_exported_headers" ] diff --git a/services/stream_update/bin_chunk_update.cpp b/services/stream_update/bin_chunk_update.cpp index a9140fd9..0cf7c1fa 100755 --- a/services/stream_update/bin_chunk_update.cpp +++ b/services/stream_update/bin_chunk_update.cpp @@ -30,6 +30,8 @@ #include "slot_info/slot_info.h" #include "utils.h" +#include // 支持ZIP_ZLIB和ZIP_GZIP + namespace Updater { using namespace Uscript; using namespace Hpackage; @@ -37,6 +39,12 @@ using namespace std::placeholders; constexpr const char *UPDATE_BIN_FILE = "update.bin"; constexpr const size_t HASH_BUFFER_SIZE = 50 * 1024; +constexpr size_t CHUNK_INFO_MAGIC_SIZE = 8; +constexpr size_t CHUNK_INFO_VERSION_SIZE = 8; +constexpr size_t CHUNK_INFO_RESERVED_SIZE = 232; +constexpr size_t CHUNK_DATA_PARTION_SIZE = 32; +constexpr size_t CHUNK_DATA_RESERVED_SIZE = 224; + BinChunkUpdate::BinChunkUpdate(uint32_t maxBufSize) { LOG(DEBUG) << "BinChunkUpdate::BinChunkUpdate enter"; @@ -112,6 +120,9 @@ UpdateResultCode BinChunkUpdate::ProcessBufferData() case BIN_UPDATE_HEAD_TIP: ret = UpdateBinHead(buffer_, curlen_); break; + case BIN_UPDATE_INFO_TIP: + ret = UpdateBinInfo(buffer_, curlen_); + break; case BIN_UPDATE_DATA_TIP: ret = UpdateBinData(buffer_, curlen_); break; @@ -502,7 +513,7 @@ bool BinChunkUpdate::ReadPartitionData(uint8_t *data, uint32_t &len) } updateInfo_.curPartition = ""; - PkgFileImpl::ConvertBufferToString(updateInfo_.curPartition, {data + offset, tlv.length}); + PkgFileImpl::ConvertBufferToString(updateInfo_.curPartition, {data + offset, CHUNK_DATA_PARTION_SIZE}); LOG(DEBUG) << "PreWriteBin name " << updateInfo_.curPartition; return true; @@ -622,9 +633,16 @@ bool BinChunkUpdate::ProcessPartition(uint8_t *data, uint32_t &len, uint32_t &of } std::string partition; - PkgFileImpl::ConvertBufferToString(partition, {data + offset, tlv.length}); + PkgFileImpl::ConvertBufferToString(partition, {data + offset, CHUNK_DATA_PARTION_SIZE}); LOG(DEBUG) << "partition:" << partition; - offset += tlv.length; + offset += CHUNK_DATA_PARTION_SIZE; + + std::string reservedData; + reservedData.assign(data + offset, data + offset + 224); + if (reservedData.size() != CHUNK_DATA_RESERVED_SIZE) { + LOG(ERROR) << " ERROR Reserved size:" << reservedData.size(); + } + offset += CHUNK_DATA_RESERVED_SIZE; if (partition != updateInfo_.curPartition) { updateInfo_.updateStep = CHUNK_INSTALL_STEP_POST; @@ -684,8 +702,22 @@ bool BinChunkUpdate::ProcessInstallData(uint8_t *data, uint32_t &len, uint32_t & return false; } - updateInfo_.transferParams->dataBuffer = data + offset; - updateInfo_.transferParams->dataBufferSize = tlv2.length; + // 提取数据 + std::vector compressed_data(data + offset, data + offset + tlv2.length); + + persistentDecompressedData_ = decompress_data(updateInfo_.compresionMethod, compressed_data); + + // if (decompressed_data.empty()) { + // LOG(ERROR) << "Decompression failed"; + // return false; + // } + + // Store the decompressed data in the updateInfo structure + updateInfo_.transferParams->dataBuffer = persistentDecompressedData_.data(); + updateInfo_.transferParams->dataBufferSize = persistentDecompressedData_.size(); + + // updateInfo_.transferParams->dataBuffer = data + offset; + // updateInfo_.transferParams->dataBufferSize = tlv2.length; offset += tlv2.length; return true; @@ -727,6 +759,68 @@ UpdateResultCode BinChunkUpdate::ChunkInstallPostWrite(uint8_t *data, uint32_t & return STREAM_UPDATE_SUCCESS; } +UpdateResultCode BinChunkUpdate::UpdateBinInfo(uint8_t *data, uint32_t &len) +{ + LOG(INFO) << "BinChunkUptdate::UpdateBinInfo enter"; + PkgTlvHH tlv; + uint32_t offset = offset_; + + if ((len - offset) < sizeof(PkgTlvHH)) { + LOG(INFO) << "needNewData"; + updateInfo_.needNewData = true; + return STREAM_UPDATE_SUCCESS; + } + + tlv.type = ReadLE16(data + offset); + LOG(INFO) << "tlv.type:" << tlv.type; + if (tlv.type != BIN_UPDATE_INFO_TIP) { + LOG(ERROR) << "Invalid chunkinfo type: 0x" << std::hex << tlv.type; + return STREAM_UPDATE_FAILURE; + } + + tlv.length = ReadLE16(data + offset + sizeof(uint16_t)); + LOG(INFO) << "tlv.length:" << tlv.length; + offset += sizeof(PkgTlvHH); + + if ((len - offset) < tlv.length) { + LOG(INFO) << "needNewData"; + updateInfo_.needNewData = true; + return STREAM_UPDATE_SUCCESS; + } + + updateInfo_.magicNum.assign(data + offset, data + offset + CHUNK_INFO_MAGIC_SIZE); + LOG(INFO) << "magicNum:" << updateInfo_.magicNum; + offset += CHUNK_INFO_MAGIC_SIZE; + + updateInfo_.fileFormatVeriosn.assign(data + offset, data + offset + CHUNK_INFO_VERSION_SIZE); + LOG(INFO) << "fileFormatVeriosn:" << updateInfo_.fileFormatVeriosn; + offset += CHUNK_INFO_VERSION_SIZE; + + updateInfo_.compresionMethod = ReadLE16(data + offset); + LOG(INFO) << "compresionMethod:" << updateInfo_.compresionMethod; + offset += sizeof(uint16_t); + + updateInfo_.signMethod = ReadLE16(data + offset); + LOG(INFO) << "signMethod:" << updateInfo_.signMethod; + offset += sizeof(uint16_t); + + updateInfo_.chunkListNum = ReadLE32(data + offset); + LOG(INFO) << "chunkListNum:" << updateInfo_.chunkListNum; + offset += sizeof(uint32_t); + + std::string reservedData; + reservedData.assign(data + offset, data + offset + CHUNK_INFO_RESERVED_SIZE); + if (reservedData.size() != CHUNK_INFO_RESERVED_SIZE) { + LOG(ERROR) << " ERROR Reserved size:" << reservedData.size(); + return STREAM_UPDATE_FAILURE; + } + offset += CHUNK_INFO_RESERVED_SIZE; + + offset_ = offset; + + return STREAM_UPDATE_SUCCESS; +} + UpdateResultCode BinChunkUpdate::UpdateBinData(uint8_t *data, uint32_t &len) { LOG(DEBUG) << "BinChunkUpdate::UpdateBinData enter"; @@ -812,4 +906,46 @@ bool BinChunkUpdate::VerifyPartitionHash(const std::string &partitionName, const return true; } +std::vector BinChunkUpdate::decompress_data(int compress_method, + const std::vector& compressed_data) +{ + LOG(DEBUG) << "BinChunkUpdate::decompress_data enter"; + switch(compress_method) { + case NO_COMPRESS: + return compressed_data; + + case ZIP_ZLIB: { + z_stream zs = {}; + if (inflateInit(&zs) != Z_OK) + LOG(ERROR) << "inflateInit failed"; + return {}; + + zs.next_in = const_cast(compressed_data.data()); + zs.avail_in = compressed_data.size(); + + std::vector output(compressed_data.size() * 5); + int ret; + do { + zs.next_out = output.data() + zs.total_out; + zs.avail_out = output.size() - zs.total_out; + ret = inflate(&zs, Z_FINISH); + if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) { + inflateEnd(&zs); + LOG(ERROR) << "zlib decompress error"; + } + if (zs.avail_out == 0) + output.resize(output.size() * 2); + } while (ret != Z_STREAM_END); + + inflateEnd(&zs); + output.resize(zs.total_out); + return output; + } + + default: + LOG(ERROR) << "zlib decompress error"; + return {}; + } +} + } // namespace Updater diff --git a/services/stream_update/bin_chunk_update.h b/services/stream_update/bin_chunk_update.h index 306326d6..ff08d6be 100755 --- a/services/stream_update/bin_chunk_update.h +++ b/services/stream_update/bin_chunk_update.h @@ -49,10 +49,19 @@ using UpdateResultCode = enum { using BinUpdateTip = enum { BIN_UPDATE_ZIP_TIP = 0xaa, BIN_UPDATE_HEAD_TIP = 0x01, + BIN_UPDATE_INFO_TIP = 0x10, BIN_UPDATE_DATA_TIP = 0x12, BIN_UPDATE_HASH_TIP = 0x16 }; +using CompressMethod = enum { + NO_COMPRESS = 0, + ZIP_ZLIB = 4, + ZIP_GZIP = 8, + ZIP_BZIP2 = 12, + ZIP_LZMA = 16 +}; + using ChunkInstallStep = enum { CHUNK_INSTALL_STEP_PRE = 0, CHUNK_INSTALL_STEP_DO, @@ -66,6 +75,11 @@ struct BinChunkUpdateInfo { int srcFd; int targetFd; std::unique_ptr transferParams; + std::string magicNum; + std::string fileFormatVeriosn; + int16_t compresionMethod; + int16_t signMethod; + int32_t chunkListNum; std::string curPartition; std::string cmdLine; int patitionNum; @@ -90,6 +104,7 @@ private: UpdateResultCode ChunkInstallPostWrite(uint8_t *data, uint32_t &len); UpdateResultCode UpdateBinHead(uint8_t *data, uint32_t &len); + UpdateResultCode UpdateBinInfo(uint8_t *data, uint32_t &len); UpdateResultCode UpdateBinData(uint8_t *data, uint32_t &len); UpdateResultCode UpdateBinHash(uint8_t *data, uint32_t &len); UpdateResultCode UpdateBinOther(uint8_t *data, uint32_t &len); @@ -130,11 +145,15 @@ private: const std::map &dataLenInfos); std::string ComputeFileHash(const std::string& partitionName, const std::map &dataLenInfos); + std::vector decompress_data(int compress_method, + const std::vector& compressed_data); + Hpackage::PkgManager::PkgManagerPtr pkgManager_; uint8_t *buffer_ = nullptr; uint32_t maxBufSize_ = 0; uint32_t curlen_ = 0; uint32_t offset_ = 0; + std::vector persistentDecompressedData_; std::map> chunkInstallProcess_; BinChunkUpdateInfo updateInfo_ {}; -- Gitee