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