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