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