• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "bin_chunk_update.h"
16 
17 #include <algorithm>
18 #include <fcntl.h>
19 #include <functional>
20 #include <iomanip> // 用于 std::setw 和 std::setfill
21 #include <iostream>
22 #include <sstream> // 用于 std::ostringstream
23 #include <sys/stat.h>
24 
25 #include "applypatch/command_process.h"
26 #include "applypatch/store.h"
27 #include "fs_manager/mount.h"
28 #include "log.h"
29 #include "scope_guard.h"
30 #include "slot_info/slot_info.h"
31 #include "utils.h"
32 
33 namespace Updater {
34 using namespace Uscript;
35 using namespace Hpackage;
36 using namespace std::placeholders;
37 
38 constexpr const char *UPDATE_BIN_FILE = "update.bin";
39 constexpr const size_t HASH_BUFFER_SIZE = 50 * 1024;
BinChunkUpdate(uint32_t maxBufSize)40 BinChunkUpdate::BinChunkUpdate(uint32_t maxBufSize)
41 {
42     LOG(DEBUG) << "BinChunkUpdate::BinChunkUpdate enter";
43     maxBufSize_ = maxBufSize;
44     buffer_ = new uint8_t[maxBufSize_];
45     chunkInstallProcess_.emplace(CHUNK_INSTALL_STEP_PRE, [this](uint8_t *data, uint32_t &len) {
46         return this->ChunkInstallPreWrite(data, len);
47     });
48     chunkInstallProcess_.emplace(CHUNK_INSTALL_STEP_DO, [this](uint8_t *data, uint32_t &len) {
49         return this->ChunkInstallDoWrite(data, len);
50     });
51     chunkInstallProcess_.emplace(CHUNK_INSTALL_STEP_POST, [this](uint8_t *data, uint32_t &len) {
52         return this->ChunkInstallPostWrite(data, len);
53     });
54     pkgManager_ = PkgManager::CreatePackageInstance();
55 }
56 
~BinChunkUpdate()57 BinChunkUpdate::~BinChunkUpdate()
58 {
59     PkgManager::ReleasePackageInstance(pkgManager_);
60     if (buffer_ != nullptr) {
61         delete[] buffer_;
62         buffer_ = nullptr;
63     }
64 }
65 
StartBinChunkUpdate(const uint8_t * data,uint32_t len,uint32_t & dealLen)66 UpdateResultCode BinChunkUpdate::StartBinChunkUpdate(const uint8_t *data, uint32_t len, uint32_t &dealLen)
67 {
68     LOG(DEBUG) << "BinChunkUpdate::StartBinChunkUpdate enter";
69     UpdateResultCode ret = STREAM_UPDATE_SUCCESS;
70     if (data == nullptr || len == 0 || pkgManager_ == nullptr) {
71         LOG(ERROR) << "para error";
72         return STREAM_UPDATE_FAILURE;
73     }
74     uint32_t remainLen = len;
75     uint32_t leftLen = curlen_;
76     LOG(DEBUG) << "BinChunkUpdate::StartBinChunkUpdate leftLen:" << leftLen;
77     dealLen = 0;
78     while (remainLen > 0) {
79         if (!AddRemainData(data + len - remainLen, remainLen)) {
80             LOG(ERROR) << "AddRemainData error";
81             return STREAM_UPDATE_FAILURE;
82         }
83         updateInfo_.needNewData = false;
84 
85         // 处理缓冲区的数据
86         ret = ProcessBufferData();
87         if (ret == STREAM_UPDATE_FAILURE) {
88             return ret;
89         }
90 
91         // 移动剩余数据
92         if (!MoveRemainingData()) {
93             return STREAM_UPDATE_FAILURE;
94         }
95     }
96 
97     dealLen = len + leftLen - curlen_;
98     LOG(DEBUG) << "BinChunkUpdate StartBinChunkUpdate dealLen:" << dealLen << " len:" << len << " curlen_:" << curlen_
99               << " leftLen:" << leftLen;
100     return ret;
101 }
102 
ProcessBufferData()103 UpdateResultCode BinChunkUpdate::ProcessBufferData()
104 {
105     UpdateResultCode ret = STREAM_UPDATE_SUCCESS;
106     while ((curlen_ - offset_) > 0 && !updateInfo_.needNewData) {
107         LOG(DEBUG) << "BinChunkUpdate::StartBinChunkUpdate curlen_:" << curlen_ << " offset_:" << offset_;
108         uint16_t type = ReadLE16(buffer_ + offset_);
109         LOG(DEBUG) << "BinChunkUpdate::StartBinChunkUpdate type:" << type;
110 
111         switch (type) {
112             case BIN_UPDATE_HEAD_TIP:
113                 ret = UpdateBinHead(buffer_, curlen_);
114                 break;
115             case BIN_UPDATE_DATA_TIP:
116                 ret = UpdateBinData(buffer_, curlen_);
117                 break;
118             case BIN_UPDATE_HASH_TIP:
119                 ret = UpdateBinHash(buffer_, curlen_);
120                 break;
121             default:
122                 ret = UpdateBinOther(buffer_, curlen_);
123                 break;
124         }
125 
126         if (ret == STREAM_UPDATE_FAILURE) {
127             LOG(ERROR) << "Update failed for type: " << type;
128             return ret;
129         }
130     }
131 
132     return ret;
133 }
134 
MoveRemainingData()135 bool BinChunkUpdate::MoveRemainingData()
136 {
137     LOG(DEBUG) << "curlen_:" << curlen_ << " offset_:" << offset_;
138 
139     if ((curlen_ - offset_) > 0) {
140         if (memmove_s(buffer_, curlen_, buffer_ + offset_, curlen_ - offset_) != EOK) {
141             LOG(ERROR) << "memmove failed";
142             return false;
143         }
144         curlen_ -= offset_;
145     } else {
146         if (memset_s(buffer_, maxBufSize_, 0, maxBufSize_) != 0) {
147             LOG(ERROR) << "memset_s failed";
148             return false;
149         }
150         curlen_ = 0;
151     }
152 
153     return true;
154 }
155 
AddRemainData(const uint8_t * data,uint32_t & len)156 bool BinChunkUpdate::AddRemainData(const uint8_t *data, uint32_t &len)
157 {
158     if (data == nullptr || len == 0) {
159         LOG(ERROR) << "AddRemainData para error";
160         return false;
161     }
162     uint32_t copySize = std::min(static_cast<size_t>(len), static_cast<size_t>(maxBufSize_ - curlen_));
163     LOG(DEBUG) << "BinChunkUpdate AddRemainData curlen_:" << curlen_ << " copySize:" << copySize;
164     if (memcpy_s(buffer_ + curlen_, maxBufSize_, data, copySize) != EOK) {
165         LOG(ERROR) << "AddRemainData memcpy failed" << " : " << strerror(errno);
166         return false;
167     }
168     curlen_ += copySize;
169     len -= copySize;
170     offset_ = 0;
171     return true;
172 }
173 
UpdateBinHash(uint8_t * data,uint32_t & len)174 UpdateResultCode BinChunkUpdate::UpdateBinHash(uint8_t *data, uint32_t &len)
175 {
176     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash enter";
177     uint32_t offset = offset_;
178     PartitionHashInfo hashInfos;
179     std::vector<uint8_t> signData;
180     std::vector<std::future<bool>> futures;
181 
182     // 初始化 SHA256 算法
183     updateInfo_.algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(PKG_DIGEST_TYPE_SHA256);
184     if (updateInfo_.algorithm == nullptr) {
185         LOG(ERROR) << "algorithm is null";
186         return STREAM_UPDATE_FAILURE;
187     }
188     updateInfo_.algorithm->Init();
189 
190     // 读取分区数量
191     if (!ProcessPartitionNum(data, len, offset)) {
192         return STREAM_UPDATE_SUCCESS;
193     }
194 
195     // 读取分区hash数据
196     if (!ProcessPartitionData(data, len, offset, hashInfos)) {
197         return STREAM_UPDATE_SUCCESS;
198     }
199 
200     // 读取签名
201     if (!ProcessSignature(data, len, offset, signData)) {
202         return STREAM_UPDATE_SUCCESS;
203     }
204 
205     offset_ = offset;
206 
207     // 签名验证
208     if (!VerifySignature(signData)) {
209         return STREAM_UPDATE_FAILURE;
210     }
211 
212     // 完整性验证(异步处理哈希验证)
213     if (!VerifyPartitionHashes(hashInfos, futures)) {
214         return STREAM_UPDATE_FAILURE;
215     }
216 
217     //切换ab分区
218     #ifndef UPDATER_UT
219     SetActiveSlot();
220     #else
221     int result = remove("/data/updater/test.txt");
222     if (result != 0) {
223         LOG(ERROR) << "Failed to remove /data/updater/test.txt, error: " << strerror(errno);
224     }
225     #endif
226     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash exit";
227     return STREAM_UPDATE_COMPLETE;
228 }
229 
ProcessPartitionNum(uint8_t * data,uint32_t & len,uint32_t & offset)230 bool BinChunkUpdate::ProcessPartitionNum(uint8_t *data, uint32_t &len, uint32_t &offset)
231 {
232     PkgTlvHH tlv;
233 
234     // 读取TLV头部信息
235     if ((len - offset) < sizeof(PkgTlvHH)) {
236         LOG(DEBUG) << "needNewData";
237         updateInfo_.needNewData = true;
238         return false;
239     }
240 
241     tlv.type = ReadLE16(data + offset);
242     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash tlv.type:" << tlv.type;
243     tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
244     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash tlv.length:" << tlv.length;
245     updateInfo_.algorithm->Update({data + offset, sizeof(PkgTlvHH)}, sizeof(PkgTlvHH));
246     offset += sizeof(PkgTlvHH);
247 
248     // 读取分区数量
249     if ((len - offset) < tlv.length) {
250         LOG(DEBUG) << "needNewData";
251         updateInfo_.needNewData = true;
252         return false;
253     }
254 
255     updateInfo_.patitionNum = ReadLE16(data + offset);
256     LOG(INFO) << "BinChunkUpdate::UpdateBinHash patitionNum:" << updateInfo_.patitionNum;
257     updateInfo_.algorithm->Update({data + offset, tlv.length}, tlv.length);
258     offset += tlv.length;
259 
260     return true;
261 }
262 
ProcessPartitionData(uint8_t * data,uint32_t & len,uint32_t & offset,PartitionHashInfo & hashInfos)263 bool BinChunkUpdate::ProcessPartitionData(uint8_t *data, uint32_t &len, uint32_t &offset, PartitionHashInfo &hashInfos)
264 {
265     PkgTlvHH tlv;
266 
267     for (auto i = 0; i < updateInfo_.patitionNum; i++) {
268         // 读取分区名称
269         if ((len - offset) < sizeof(PkgTlvHH)) {
270             LOG(DEBUG) << "needNewData";
271             updateInfo_.needNewData = true;
272             return false;
273         }
274 
275         tlv.type = ReadLE16(data + offset);
276         tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
277         updateInfo_.algorithm->Update({data + offset, sizeof(PkgTlvHH)}, sizeof(PkgTlvHH));
278         offset += sizeof(PkgTlvHH);
279 
280         std::string patition;
281         PkgFileImpl::ConvertBufferToString(patition, {data + offset, tlv.length});
282         LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash patition:" << patition;
283         updateInfo_.algorithm->Update({data + offset, tlv.length}, tlv.length);
284         offset += tlv.length;
285 
286         // 读取哈希值
287         std::string hashBuf;
288         if (!ReadHash(data, len, offset, hashBuf)) {
289             return false;
290         }
291 
292         hashInfos.hashValues[patition] = hashBuf;
293 
294         // 读取数据长度
295         if (!ReadDataLength(data, len, offset, patition, hashInfos.dataLenInfos)) {
296             return false;
297         }
298     }
299 
300     return true;
301 }
302 
ProcessSignature(uint8_t * data,uint32_t & len,uint32_t & offset,std::vector<uint8_t> & signData)303 bool BinChunkUpdate::ProcessSignature(uint8_t *data, uint32_t &len, uint32_t &offset,
304     std::vector<uint8_t> &signData)
305 {
306     PkgTlvHI tlv2;
307 
308     if ((len - offset) < sizeof(PkgTlvHI)) {
309         LOG(DEBUG) << "needNewData";
310         updateInfo_.needNewData = true;
311         return false;
312     }
313     tlv2.type = ReadLE16(data + offset);
314     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash tlv2.type:" << tlv2.type;
315     tlv2.length = ReadLE32(data + offset + sizeof(uint16_t));
316     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHash tlv2.length:" << tlv2.length;
317     offset += sizeof(PkgTlvHI);
318     if ((len - offset) < tlv2.length) {
319         LOG(DEBUG) << "needNewData";
320         updateInfo_.needNewData = true;
321         return false;
322     }
323     signData.assign(data + offset, data + offset + tlv2.length);
324     offset += tlv2.length;
325 
326     return true;
327 }
328 
ReadHash(uint8_t * data,uint32_t & len,uint32_t & offset,std::string & hashBuf)329 bool BinChunkUpdate::ReadHash(uint8_t *data, uint32_t &len, uint32_t &offset, std::string &hashBuf)
330 {
331     PkgTlvHH tlv;
332 
333     if ((len - offset) < sizeof(PkgTlvHH)) {
334         LOG(DEBUG) << "needNewData";
335         updateInfo_.needNewData = true;
336         return false;
337     }
338 
339     tlv.type = ReadLE16(data + offset);
340     tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
341     updateInfo_.algorithm->Update({data + offset, sizeof(PkgTlvHH)}, sizeof(PkgTlvHH));
342     offset += sizeof(PkgTlvHH);
343 
344     if ((len - offset) < tlv.length) {
345         LOG(DEBUG) << "needNewData";
346         updateInfo_.needNewData = true;
347         return false;
348     }
349 
350     PkgFileImpl::ConvertBufferToString(hashBuf, {data + offset, tlv.length});
351     updateInfo_.algorithm->Update({data + offset, tlv.length}, tlv.length);
352     offset += tlv.length;
353 
354     return true;
355 }
356 
ReadDataLength(uint8_t * data,uint32_t & len,uint32_t & offset,const std::string & patition,std::map<std::string,uint64_t> & dataLenInfos)357 bool BinChunkUpdate::ReadDataLength(uint8_t *data, uint32_t &len, uint32_t &offset,
358     const std::string &patition, std::map<std::string, uint64_t> &dataLenInfos)
359 {
360     PkgTlvHH tlv;
361 
362     if ((len - offset) < sizeof(PkgTlvHH)) {
363         LOG(DEBUG) << "needNewData";
364         updateInfo_.needNewData = true;
365         return false;
366     }
367 
368     tlv.type = ReadLE16(data + offset);
369     tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
370     updateInfo_.algorithm->Update({data + offset, sizeof(PkgTlvHH)}, sizeof(PkgTlvHH));
371     offset += sizeof(PkgTlvHH);
372 
373     if ((len - offset) < tlv.length) {
374         LOG(DEBUG) << "needNewData";
375         updateInfo_.needNewData = true;
376         return false;
377     }
378 
379     uint64_t dataLen = ReadLE64(data + offset);
380     updateInfo_.algorithm->Update({data + offset, tlv.length}, tlv.length);
381     offset += tlv.length;
382 
383     dataLenInfos[patition] = dataLen;
384 
385     return true;
386 }
387 
VerifySignature(std::vector<uint8_t> & signData)388 bool BinChunkUpdate::VerifySignature(std::vector<uint8_t> &signData)
389 {
390     // 计算最终的哈希值
391     PkgBuffer digest(DigestAlgorithm::GetDigestLen(PKG_DIGEST_TYPE_SHA256));
392     updateInfo_.algorithm->Final(digest);
393 
394     // 获取用于验证签名的算法
395     SignAlgorithm::SignAlgorithmPtr signAlgorithm =
396         PkgAlgorithmFactory::GetVerifyAlgorithm(Utils::GetCertName(), PKG_DIGEST_TYPE_SHA256);
397     if (signAlgorithm == nullptr) {
398         LOG(ERROR) << "BinChunkUpdate Invalid sign algo";
399         return false;
400     }
401 
402     // 验证签名
403     if (signAlgorithm->VerifyDigest(digest.data, signData) != 0) {
404         LOG(ERROR) << "BinChunkUpdate VerifyDigest failed";
405         return false;
406     }
407 
408     LOG(INFO) << "BinChunkUpdate VerifyDigest success";
409     return true;
410 }
411 
VerifyPartitionHashes(const PartitionHashInfo & hashInfos,std::vector<std::future<bool>> & futures)412 bool BinChunkUpdate::VerifyPartitionHashes(const PartitionHashInfo &hashInfos,
413     std::vector<std::future<bool>> &futures)
414 {
415     // 使用异步任务来验证每个分区的哈希
416     for (const auto &pair : hashInfos.hashValues) {
417         futures.push_back(std::async(std::launch::async, &BinChunkUpdate::VerifyPartitionHash, this, pair.first,
418                                      pair.second, std::ref(hashInfos.dataLenInfos)));
419     }
420 
421     // 等待所有异步任务完成
422     for (auto &future : futures) {
423         if (!future.get()) {
424             LOG(ERROR) << "BinChunkUpdate partition verify hash fail";
425             return false;
426         }
427     }
428 
429     return true;
430 }
431 
UpdateBinOther(uint8_t * data,uint32_t & len)432 UpdateResultCode BinChunkUpdate::UpdateBinOther(uint8_t *data, uint32_t &len)
433 {
434     LOG(DEBUG) << "BinChunkUpdate::UpdateBinOther enter";
435     return STREAM_UPDATE_FAILURE;
436 }
437 
UpdateBinHead(uint8_t * data,uint32_t & len)438 UpdateResultCode BinChunkUpdate::UpdateBinHead(uint8_t *data, uint32_t &len)
439 {
440     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHead enter";
441     PkgManager::StreamPtr stream = nullptr;
442     PkgBuffer buffer(data, len);
443     if (auto ret = pkgManager_->CreatePkgStream(stream, UPDATE_BIN_FILE, buffer); ret != PKG_SUCCESS) {
444         LOG(ERROR) << "ParseHead failed";
445         return STREAM_UPDATE_FAILURE;
446     }
447 
448     if (auto ret = pkgManager_->LoadPackageWithStream(UPDATE_BIN_FILE, Utils::GetCertName(), updateInfo_.componentNames,
449         PkgFile::PKG_TYPE_UPGRADE, stream); ret != PKG_SUCCESS) {
450         LOG(ERROR) << "LoadPackage fail ret :" << ret;
451         return STREAM_UPDATE_FAILURE;
452     }
453 
454     const PkgInfo *pkgInfo = pkgManager_->GetPackageInfo(UPDATE_BIN_FILE);
455     if (pkgInfo == nullptr || pkgInfo->updateFileHeadLen == 0 || len < pkgInfo->updateFileHeadLen) {
456         LOG(ERROR) << "GetPackageInfo failed";
457         return STREAM_UPDATE_FAILURE;
458     }
459     offset_ = pkgInfo->updateFileHeadLen;
460     LOG(DEBUG) << "BinChunkUpdate::UpdateBinHead exit pkgInfo->updateFileHeadLen:" << pkgInfo->updateFileHeadLen;
461     return STREAM_UPDATE_SUCCESS;
462 }
463 
ChunkInstallPreWrite(uint8_t * data,uint32_t & len)464 UpdateResultCode BinChunkUpdate::ChunkInstallPreWrite(uint8_t *data, uint32_t &len)
465 {
466     LOG(DEBUG) << "BinChunkUpdate::ChunkInstallPreWrite enter";
467 
468     if (!ReadPartitionData(data, len)) {
469         return STREAM_UPDATE_SUCCESS;
470     }
471 
472     if (!OpenDevPath()) {
473         return STREAM_UPDATE_FAILURE;
474     }
475 
476     if (!InitTransferParams()) {
477         return STREAM_UPDATE_FAILURE;
478     }
479 
480     updateInfo_.updateStep = CHUNK_INSTALL_STEP_DO;
481     return STREAM_UPDATE_SUCCESS;
482 }
483 
ReadPartitionData(uint8_t * data,uint32_t & len)484 bool BinChunkUpdate::ReadPartitionData(uint8_t *data, uint32_t &len)
485 {
486     PkgTlvHH tlv;
487     uint32_t offset = offset_;
488 
489     if ((len - offset) < sizeof(PkgTlvHH)) {
490         LOG(DEBUG) << "needNewData";
491         updateInfo_.needNewData = true;
492         return false;
493     }
494 
495     tlv.type = ReadLE16(data + offset);
496     tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
497     offset += sizeof(PkgTlvHH);
498 
499     if ((len - offset) < tlv.length) {
500         updateInfo_.needNewData = true;
501         return false;
502     }
503 
504     updateInfo_.curPartition = "";
505     PkgFileImpl::ConvertBufferToString(updateInfo_.curPartition, {data + offset, tlv.length});
506     LOG(DEBUG) << "PreWriteBin name " << updateInfo_.curPartition;
507 
508     return true;
509 }
510 
OpenDevPath()511 bool BinChunkUpdate::OpenDevPath()
512 {
513     #ifndef UPDATER_UT
514     std::string devPath = GetBlockDeviceByMountPoint(updateInfo_.curPartition);
515     std::string srcPath;
516     std::string targetPath;
517     srcPath = devPath;
518     targetPath = devPath;
519 
520     if (updateInfo_.curPartition != "/userdata") {
521         std::string suffix = "";
522         GetPartitionSuffix(suffix);
523         targetPath += suffix;
524         GetActivePartitionSuffix(suffix);
525         srcPath += suffix;
526     }
527 
528     LOG(DEBUG) << "ChunkInstallPreWrite curPartition:" << updateInfo_.curPartition
529         << " srcPath:" << srcPath << " targetPath:" << targetPath;
530 
531     updateInfo_.srcFd = open(srcPath.c_str(), O_RDWR | O_LARGEFILE);
532     if (updateInfo_.srcFd < 0) {
533         LOG(ERROR) << "open srcPath error";
534         return false;
535     }
536 
537     updateInfo_.targetFd = open(targetPath.c_str(), O_RDWR | O_LARGEFILE);
538     if (updateInfo_.targetFd < 0) {
539         LOG(ERROR) << "open targetPath error";
540         return false;
541     }
542     #else
543     int fd = open("/data/updater/test.txt", O_RDWR | O_LARGEFILE | O_CREAT);
544     if (fd < 0) {
545         LOG(ERROR) << "open test file error";
546         return false;
547     }
548     updateInfo_.srcFd = fd;
549     updateInfo_.targetFd = fd;
550     #endif
551     return true;
552 }
553 
InitTransferParams()554 bool BinChunkUpdate::InitTransferParams()
555 {
556     updateInfo_.transferParams = std::make_unique<TransferParams>();
557     updateInfo_.transferParams->storeBase = std::string("/data/updater/") + updateInfo_.curPartition + "_tmp";
558     updateInfo_.transferParams->canWrite = true;
559 
560     int32_t ret = Store::CreateNewSpace(updateInfo_.transferParams->storeBase, true);
561     if (ret == -1) {
562         LOG(ERROR) << "Error to create new store space";
563         return false;
564     }
565 
566     return true;
567 }
568 
ChunkInstallDoWrite(uint8_t * data,uint32_t & len)569 UpdateResultCode BinChunkUpdate::ChunkInstallDoWrite(uint8_t *data, uint32_t &len)
570 {
571     LOG(DEBUG) << "BinChunkUpdate::ChunkInstallDoWrite enter";
572     uint32_t offset = offset_;
573 
574     // 处理安装分区
575     if (!ProcessPartition(data, len, offset)) {
576         return STREAM_UPDATE_SUCCESS;
577     }
578 
579     // 处理安装命令
580     if (!ProcessCmdLine(data, len, offset)) {
581         return STREAM_UPDATE_SUCCESS;
582     }
583 
584     // 处理安装数据
585     if (!ProcessInstallData(data, len, offset)) {
586         return STREAM_UPDATE_SUCCESS;
587     }
588 
589     // 安装数据
590     if (!ExecuteCmdLine()) {
591         return STREAM_UPDATE_FAILURE;
592     }
593 
594     offset_ = offset;
595     return STREAM_UPDATE_SUCCESS;
596 }
597 
ProcessPartition(uint8_t * data,uint32_t & len,uint32_t & offset)598 bool BinChunkUpdate::ProcessPartition(uint8_t *data, uint32_t &len, uint32_t &offset)
599 {
600     PkgTlvHH tlv;
601     if ((len - offset) < sizeof(PkgTlvHH)) {
602         LOG(DEBUG) << "needNewData";
603         updateInfo_.needNewData = true;
604         return false;
605     }
606 
607     tlv.type = ReadLE16(data + offset);
608     LOG(DEBUG) << "tlv.type:" << tlv.type;
609     if (tlv.type == BIN_UPDATE_HASH_TIP) {
610         updateInfo_.updateStep = CHUNK_INSTALL_STEP_POST;
611         return false;
612     }
613 
614     tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
615     LOG(DEBUG) << "tlv.length:" << tlv.length;
616     offset += sizeof(PkgTlvHH);
617 
618     if ((len - offset) < tlv.length) {
619         LOG(DEBUG) << "needNewData";
620         updateInfo_.needNewData = true;
621         return false;
622     }
623 
624     std::string partition;
625     PkgFileImpl::ConvertBufferToString(partition, {data + offset, tlv.length});
626     LOG(DEBUG) << "partition:" << partition;
627     offset += tlv.length;
628 
629     if (partition != updateInfo_.curPartition) {
630         updateInfo_.updateStep = CHUNK_INSTALL_STEP_POST;
631         return false;
632     }
633 
634     return true;
635 }
636 
ProcessCmdLine(uint8_t * data,uint32_t & len,uint32_t & offset)637 bool BinChunkUpdate::ProcessCmdLine(uint8_t *data, uint32_t &len, uint32_t &offset)
638 {
639     PkgTlvHH tlv;
640     if ((len - offset) < sizeof(PkgTlvHH)) {
641         LOG(DEBUG) << "needNewData";
642         updateInfo_.needNewData = true;
643         return false;
644     }
645 
646     tlv.type = ReadLE16(data + offset);
647     LOG(DEBUG) << "tlv.type:" << tlv.type;
648     tlv.length = ReadLE16(data + offset + sizeof(uint16_t));
649     LOG(DEBUG) << "tlv.length:" << tlv.length;
650     offset += sizeof(PkgTlvHH);
651 
652     if ((len - offset) < tlv.length) {
653         LOG(DEBUG) << "needNewData";
654         updateInfo_.needNewData = true;
655         return false;
656     }
657 
658     updateInfo_.cmdLine = "";
659     PkgFileImpl::ConvertBufferToString(updateInfo_.cmdLine, {data + offset, tlv.length});
660     LOG(DEBUG) << "cmdLine:" << updateInfo_.cmdLine;
661     offset += tlv.length;
662 
663     return true;
664 }
665 
ProcessInstallData(uint8_t * data,uint32_t & len,uint32_t & offset)666 bool BinChunkUpdate::ProcessInstallData(uint8_t *data, uint32_t &len, uint32_t &offset)
667 {
668     PkgTlvHI tlv2;
669     if ((len - offset) < sizeof(PkgTlvHI)) {
670         LOG(DEBUG) << "needNewData";
671         updateInfo_.needNewData = true;
672         return false;
673     }
674 
675     tlv2.type = ReadLE16(data + offset);
676     LOG(DEBUG) << "tlv2.type:" << tlv2.type;
677     tlv2.length = ReadLE32(data + offset + sizeof(uint16_t));
678     LOG(DEBUG) << "tlv2.length:" << tlv2.length;
679     offset += sizeof(PkgTlvHI);
680 
681     if ((len - offset) < tlv2.length) {
682         LOG(DEBUG) << "needNewData";
683         updateInfo_.needNewData = true;
684         return false;
685     }
686 
687     updateInfo_.transferParams->dataBuffer = data + offset;
688     updateInfo_.transferParams->dataBufferSize = tlv2.length;
689 
690     offset += tlv2.length;
691     return true;
692 }
693 
ExecuteCmdLine()694 bool BinChunkUpdate::ExecuteCmdLine()
695 {
696     std::shared_ptr<Command> cmd = std::make_shared<Command>(updateInfo_.transferParams.get());
697     cmd->SetIsStreamCmd(true);
698     cmd->SetSrcFileDescriptor(updateInfo_.srcFd);
699     cmd->SetTargetFileDescriptor(updateInfo_.targetFd);
700     cmd->Init(updateInfo_.cmdLine);
701 
702     CommandFunction *cf = CommandFunctionFactory::GetInstance().GetCommandFunction(cmd->GetCommandHead());
703     CommandResult ret = cf->Execute(const_cast<Command &>(*cmd.get()));
704     if (SUCCESS != ret) {
705         LOG(ERROR) << "cf->Execute fail";
706         return false;
707     }
708 
709     LOG(INFO) << "cf->Execute SUCCESS";
710     return true;
711 }
712 
ChunkInstallPostWrite(uint8_t * data,uint32_t & len)713 UpdateResultCode BinChunkUpdate::ChunkInstallPostWrite(uint8_t *data, uint32_t &len)
714 {
715     LOG(DEBUG) << "BinChunkUpdate::ChunkInstallPostWrite enter";
716     if (updateInfo_.srcFd > 0) {
717         fsync(updateInfo_.srcFd);
718         close(updateInfo_.srcFd);
719     }
720     if (updateInfo_.targetFd > 0) {
721         fsync(updateInfo_.targetFd);
722         close(updateInfo_.targetFd);
723     }
724     Store::DoFreeSpace(updateInfo_.transferParams->storeBase);
725     (void)Utils::DeleteFile(updateInfo_.transferParams->storeBase);
726     updateInfo_.updateStep = CHUNK_INSTALL_STEP_PRE;
727     return STREAM_UPDATE_SUCCESS;
728 }
729 
UpdateBinData(uint8_t * data,uint32_t & len)730 UpdateResultCode BinChunkUpdate::UpdateBinData(uint8_t *data, uint32_t &len)
731 {
732     LOG(DEBUG) << "BinChunkUpdate::UpdateBinData enter";
733     UpdateResultCode ret;
734     do {
735         auto it = chunkInstallProcess_.find(updateInfo_.updateStep);
736         if (it == chunkInstallProcess_.end() || it->second == nullptr) {
737             LOG(ERROR) << "cannot find " << updateInfo_.updateStep;
738             return STREAM_UPDATE_FAILURE;
739         }
740         ret = it->second(data, len);
741     } while (!(updateInfo_.needNewData || ret == STREAM_UPDATE_FAILURE ||
742         updateInfo_.updateStep == CHUNK_INSTALL_STEP_PRE));
743 
744     LOG(DEBUG) << "BinChunkUpdate::UpdateBinData exit";
745     return ret;
746 }
747 
748 // 计算文件哈希值的函数
ComputeFileHash(const std::string & partitionName,const std::map<std::string,uint64_t> & dataLenInfos)749 std::string BinChunkUpdate::ComputeFileHash(const std::string &partitionName,
750                                             const std::map<std::string, uint64_t> &dataLenInfos)
751 {
752     LOG(DEBUG) << "BinChunkUpdate::ComputeFileHash enter";
753     std::vector<uint8_t> hash(SHA256_DIGEST_LENGTH);
754 
755     auto it = dataLenInfos.find(partitionName);
756     if (it == dataLenInfos.end()) {
757         LOG(ERROR) << "ComputeFileHash cannot find dataLenInfos " << partitionName;
758         return "";
759     }
760     uint64_t dataLen = it->second;
761     #ifndef UPDATER_UT
762     std::string devPath = GetBlockDeviceByMountPoint(partitionName);
763     if (partitionName != "/userdata") {
764         std::string suffix = "";
765         GetPartitionSuffix(suffix);
766         devPath += suffix;
767     }
768     #else
769     std::string devPath = "/data/updater/test.txt";
770     #endif
771     std::ifstream file(devPath, std::ios::binary);
772     if (!file) {
773         LOG(ERROR) << "Failed to open file: " << partitionName;
774         return "";
775     }
776 
777     SHA256_CTX sha256;
778     SHA256_Init(&sha256);
779 
780     while (dataLen > 0) {
781         std::vector<char> buffer(HASH_BUFFER_SIZE);
782         size_t size = std::min(static_cast<size_t>(dataLen), buffer.size());
783         file.read(buffer.data(), size);
784         SHA256_Update(&sha256, buffer.data(), file.gcount());
785         dataLen -= file.gcount();
786     }
787 
788     SHA256_Final(hash.data(), &sha256);
789     std::ostringstream oss;
790     oss << std::hex << std::setfill('0');
791     const int kByteWidth = 2;
792     for (auto byte : hash) {
793         oss << std::setw(kByteWidth) << static_cast<int>(byte);
794     }
795 
796     return oss.str();
797 }
798 
799 // 比对哈希值的函数
VerifyPartitionHash(const std::string & partitionName,const std::string & expectedHash,const std::map<std::string,uint64_t> & dataLenInfos)800 bool BinChunkUpdate::VerifyPartitionHash(const std::string &partitionName, const std::string &expectedHash,
801                                          const std::map<std::string, uint64_t> &dataLenInfos)
802 {
803     LOG(DEBUG) << "BinChunkUpdate::VerifyPartitionHash enter";
804     std::string actualHash = ComputeFileHash(partitionName, dataLenInfos);
805 
806     LOG(DEBUG) << "actualHash:" << actualHash << " expectedHash:" << expectedHash;
807 
808     if (actualHash != expectedHash) {
809         LOG(ERROR) << "Error verifying hash for partition " << partitionName;
810         return false;
811     }
812     return true;
813 }
814 
815 } // namespace Updater
816