• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_flow_update.h"
16 
17 #include <algorithm>
18 #include <functional>
19 
20 #include "log.h"
21 #include "scope_guard.h"
22 #include "pkg_manager/pkg_stream.h"
23 #include "pkg_package/pkg_pkgfile.h"
24 #include "securec.h"
25 #include "utils.h"
26 
27 namespace Updater {
28 using namespace Uscript;
29 using namespace Hpackage;
30 using namespace std::placeholders;
31 
32 constexpr const char *UPDATE_BIN_FILE = "update.bin";
33 constexpr uint32_t DEFAULT_SIZE = 4 * 1024 * 1024;
34 
BinFlowUpdate(uint32_t maxBufSize)35 BinFlowUpdate::BinFlowUpdate(uint32_t maxBufSize)
36 {
37     maxBufSize_ = maxBufSize == 0 ? DEFAULT_SIZE : maxBufSize;
38     buffer_ = new uint8_t[maxBufSize_];
39     updateBinProcess_.emplace(BIN_UPDATE_STEP_PRE, std::bind(&BinFlowUpdate::BinUpdatePreWrite, this, _1, _2));
40     updateBinProcess_.emplace(BIN_UPDATE_STEP_DO, std::bind(&BinFlowUpdate::BinUpdateDoWrite, this, _1, _2));
41     updateBinProcess_.emplace(BIN_UPDATE_STEP_POST, std::bind(&BinFlowUpdate::BinUpdatePostWrite, this, _1, _2));
42     pkgManager_ = PkgManager::CreatePackageInstance();
43 }
44 
~BinFlowUpdate()45 BinFlowUpdate::~BinFlowUpdate()
46 {
47     PkgManager::ReleasePackageInstance(pkgManager_);
48     if (buffer_ != nullptr) {
49         delete[] buffer_;
50         buffer_ = nullptr;
51     }
52 }
53 
StartBinFlowUpdate(uint8_t * data,uint32_t len)54 int32_t BinFlowUpdate::StartBinFlowUpdate(uint8_t *data, uint32_t len)
55 {
56     if (data == nullptr || len == 0 || pkgManager_ == nullptr) {
57         LOG(ERROR) << "para error";
58         return -1;
59     }
60     uint32_t remainLen = len;
61     while (remainLen > 0) {
62         // 1: add remained data
63         if (!AddRemainData(data + len - remainLen, remainLen)) {
64             LOG(ERROR) << "AddRemainData error";
65             return -1;
66         }
67 
68         // 2: parse head
69         if (!headInit_ && UpdateBinHead(buffer_, curlen_) != 0) {
70             LOG(ERROR) << "ParseHead error";
71             return -1;
72         }
73 
74         // 3: process data
75         updateInfo_.needNewData = false;
76         while (curlen_ > 0 && !updateInfo_.needNewData) {
77             if (auto ret = UpdateBinData(buffer_, curlen_); ret != 0) {
78                 LOG(ERROR) << "ProcessData error";
79                 return ret;
80             }
81         }
82     }
83     return 0;
84 }
85 
AddRemainData(uint8_t * data,uint32_t & len)86 bool BinFlowUpdate::AddRemainData(uint8_t *data, uint32_t &len)
87 {
88     uint32_t copySize = std::min(static_cast<size_t>(len), static_cast<size_t>(maxBufSize_ - curlen_));
89     if (memcpy_s(buffer_ + curlen_, maxBufSize_, data, copySize) != EOK) {
90         LOG(ERROR) << "AddRemainData memcpy failed" << " : " << strerror(errno);
91         return false;
92     }
93     curlen_ += copySize;
94     len -= copySize;
95     return true;
96 }
97 
98 
UpdateBinHead(uint8_t * data,uint32_t & len)99 uint32_t BinFlowUpdate::UpdateBinHead(uint8_t *data, uint32_t &len)
100 {
101     PkgManager::StreamPtr stream = nullptr;
102     PkgBuffer buffer(data, len);
103     if (auto ret = pkgManager_->CreatePkgStream(stream, UPDATE_BIN_FILE, buffer); ret != PKG_SUCCESS) {
104         LOG(ERROR) << "ParseHead failed";
105         return -1;
106     }
107 
108     if (auto ret = pkgManager_->LoadPackageWithStream(UPDATE_BIN_FILE, Utils::GetCertName(),
109         updateInfo_.componentNames, PkgFile::PKG_TYPE_UPGRADE, stream); ret != PKG_SUCCESS) {
110         LOG(ERROR) << "LoadPackage fail ret :"<< ret;
111         return ret;
112     }
113 
114     const PkgInfo *pkgInfo = pkgManager_->GetPackageInfo(UPDATE_BIN_FILE);
115     if (pkgInfo == nullptr || pkgInfo->updateFileHeadLen == 0 || len < pkgInfo->updateFileHeadLen) {
116         LOG(ERROR) << "GetPackageInfo failed";
117         return -1;
118     }
119 
120     if (len > pkgInfo->updateFileHeadLen &&
121         memmove_s(data, len, data + pkgInfo->updateFileHeadLen, len - pkgInfo->updateFileHeadLen) != EOK) {
122         LOG(ERROR) << "memmove failed";
123         return -1;
124     }
125 
126     len -= pkgInfo->updateFileHeadLen;
127     headInit_ = true;
128     return 0;
129 }
130 
GetDataWriter(const std::string & partition)131 std::unique_ptr<DataWriter> BinFlowUpdate::GetDataWriter(const std::string &partition)
132 {
133     static std::string lastPartition {};
134     static int lastIndex = 0;
135     if (lastPartition == partition) {
136         lastIndex++;
137         lastPartition = partition + std::to_string(lastIndex);
138     } else {
139         lastPartition = partition;
140         lastIndex = 0;
141     }
142     const std::string writePath = "/data/updater" + lastPartition;
143     FILE *pFile = fopen(writePath.c_str(), "w+");
144     if (pFile != nullptr) {
145         uint8_t data[1] {};
146         fwrite(data, 1, sizeof(data), pFile);
147         fclose(pFile);
148     }
149     LOG(INFO) << "GetDataWriter writePath " << writePath.c_str();
150     return DataWriter::CreateDataWriter(WRITE_RAW, writePath, static_cast<uint64_t>(0));
151 }
152 
BinUpdatePreWrite(uint8_t * data,uint32_t & len)153 int BinFlowUpdate::BinUpdatePreWrite(uint8_t *data, uint32_t &len)
154 {
155     if (procCompIndex_ >= updateInfo_.componentNames.size()) {
156         LOG(ERROR) << "PreWriteBin index error cur:" << procCompIndex_ << " max:" << updateInfo_.componentNames.size();
157         return -1;
158     }
159 
160     LOG(INFO) << "PreWriteBin name "<< updateInfo_.componentNames[procCompIndex_];
161     updateInfo_.imageWriteLen = 0;
162     updateInfo_.writer = GetDataWriter(updateInfo_.componentNames[procCompIndex_]);
163     if (updateInfo_.writer == nullptr) {
164         LOG(ERROR) << "GetDataWriter error";
165         return -1;
166     }
167 
168     updateInfo_.info = pkgManager_->GetFileInfo(updateInfo_.componentNames[procCompIndex_]);
169     if (updateInfo_.info == nullptr) {
170         LOG(ERROR) << ("Can not get file info");
171         return -1;
172     }
173 
174     updateInfo_.updateStep = BIN_UPDATE_STEP_DO;
175     return 0;
176 }
177 
BinUpdateDoWrite(uint8_t * data,uint32_t & len)178 int BinFlowUpdate::BinUpdateDoWrite(uint8_t *data, uint32_t &len)
179 {
180     size_t writeLen = std::min(static_cast<size_t>(updateInfo_.info->unpackedSize - updateInfo_.imageWriteLen),
181         static_cast<size_t>(len));
182     LOG(INFO) << "DoWriteBin len " << len << " unpackedSize " << updateInfo_.info->unpackedSize << " already write " <<
183         updateInfo_.imageWriteLen;
184 
185     if (!updateInfo_.writer->Write(data, writeLen, nullptr)) {
186         LOG(ERROR) << "Write failed";
187         return -1;
188     }
189 
190     if (memmove_s(data, len, data + writeLen, len - writeLen) != EOK) {
191         LOG(ERROR) << "memmove failed";
192         return -1;
193     }
194 
195     updateInfo_.imageWriteLen += writeLen;
196     len -= writeLen;
197     if (updateInfo_.imageWriteLen == updateInfo_.info->unpackedSize) {
198         LOG(INFO) << "DoWriteBin all len " << updateInfo_.imageWriteLen;
199         updateInfo_.updateStep = BIN_UPDATE_STEP_POST;
200     } else if (updateInfo_.imageWriteLen > updateInfo_.info->unpackedSize) {
201         LOG(INFO) << "DoWriteBin write len " << updateInfo_.imageWriteLen <<
202             " all len " << updateInfo_.info->unpackedSize;
203         return -1;
204     }
205 
206     return 0;
207 }
208 
BinUpdatePostWrite(uint8_t * data,uint32_t & len)209 int BinFlowUpdate::BinUpdatePostWrite(uint8_t *data, uint32_t &len)
210 {
211     procCompIndex_++;
212     updateInfo_.updateStep = BIN_UPDATE_STEP_PRE;
213     return 0;
214 }
215 
UpdateBinData(uint8_t * data,uint32_t & len)216 int BinFlowUpdate::UpdateBinData(uint8_t *data, uint32_t &len)
217 {
218     auto it = updateBinProcess_.find(updateInfo_.updateStep);
219     if (it == updateBinProcess_.end() || it->second == nullptr) {
220         LOG(ERROR) << "cannot find " << updateInfo_.updateStep;
221         return -1;
222     }
223 
224     return it->second(data, len);
225 }
226 } // Updater
227