• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "update_image_block.h"
16 #include <cerrno>
17 #include <fcntl.h>
18 #include <pthread.h>
19 #include <sstream>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include "applypatch/block_set.h"
24 #include "applypatch/store.h"
25 #include "applypatch/transfer_manager.h"
26 #include "applypatch/partition_record.h"
27 #include "fs_manager/mount.h"
28 #include "log/log.h"
29 #include "utils.h"
30 
31 using namespace uscript;
32 using namespace hpackage;
33 using namespace updater;
34 
35 namespace updater {
36 constexpr int32_t SHA_CHECK_SECOND = 2;
37 constexpr int32_t SHA_CHECK_PARAMS = 3;
ExtractNewData(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)38 static int ExtractNewData(const PkgBuffer &buffer, size_t size, size_t start, bool isFinish, const void* context)
39 {
40     void *p = const_cast<void *>(context);
41     WriterThreadInfo *info = static_cast<WriterThreadInfo *>(p);
42     uint8_t *addr = buffer.buffer;
43     while (size > 0) {
44         pthread_mutex_lock(&info->mutex);
45         while (info->writer == nullptr) {
46             if (!info->readyToWrite) {
47                 LOG(WARNING) << "writer is not ready to write.";
48                 pthread_mutex_unlock(&info->mutex);
49                 return hpackage::PKG_INVALID_STREAM;
50             }
51             pthread_cond_wait(&info->cond, &info->mutex);
52         }
53         pthread_mutex_unlock(&info->mutex);
54         size_t toWrite = std::min(size, info->writer->GetBlocksSize() - info->writer->GetTotalWritten());
55         // No more data to write.
56         UPDATER_CHECK_ONLY_RETURN(toWrite != 0, break);
57         bool ret = info->writer->Write(const_cast<uint8_t *>(addr), toWrite, WRITE_BLOCK, "");
58         std::ostringstream logMessage;
59         logMessage << "Write " << toWrite << " byte(s) failed";
60         UPDATER_ERROR_CHECK(ret == true, logMessage.str(), return hpackage::PKG_INVALID_STREAM);
61         size -= toWrite;
62         addr += toWrite;
63 
64         if (info->writer->IsWriteDone()) {
65             pthread_mutex_lock(&info->mutex);
66             info->writer.reset();
67             pthread_cond_broadcast(&info->cond);
68             pthread_mutex_unlock(&info->mutex);
69         }
70     }
71     return hpackage::PKG_SUCCESS;
72 }
73 
UnpackNewData(void * arg)74 void* UnpackNewData(void *arg)
75 {
76     WriterThreadInfo *info = static_cast<WriterThreadInfo *>(arg);
77     hpackage::PkgManager::StreamPtr stream = nullptr;
78     TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
79     if (info->newPatch.empty()) {
80         LOG(ERROR) << "new patch file name is empty. thread quit.";
81         pthread_mutex_lock(&info->mutex);
82         info->readyToWrite = false;
83         if (info->writer != nullptr) {
84             pthread_cond_broadcast(&info->cond);
85         }
86         pthread_mutex_unlock(&info->mutex);
87         return nullptr;
88     }
89     LOG(DEBUG) << "new patch file name: " << info->newPatch;
90     auto env = tm->GetGlobalParams()->env;
91     const FileInfo *file = env->GetPkgManager()->GetFileInfo(info->newPatch);
92     if (file == nullptr) {
93         LOG(ERROR) << "Cannot get file info of :" << info->newPatch;
94         pthread_mutex_lock(&info->mutex);
95         info->readyToWrite = false;
96         if (info->writer != nullptr) {
97             pthread_cond_broadcast(&info->cond);
98         }
99         pthread_mutex_unlock(&info->mutex);
100         return nullptr;
101     }
102     LOG(DEBUG) << info->newPatch << " info: size " << file->packedSize << " unpacked size " <<
103         file->unpackedSize << " name " << file->identity;
104     int32_t ret = env->GetPkgManager()->CreatePkgStream(stream, info->newPatch, ExtractNewData, info);
105     if (ret != hpackage::PKG_SUCCESS || stream == nullptr) {
106         LOG(ERROR) << "Cannot extract " << info->newPatch << " from package.";
107         pthread_mutex_lock(&info->mutex);
108         info->readyToWrite = false;
109         if (info->writer != nullptr) {
110             pthread_cond_broadcast(&info->cond);
111         }
112         pthread_mutex_unlock(&info->mutex);
113         return nullptr;
114     }
115     ret = env->GetPkgManager()->ExtractFile(info->newPatch, stream);
116     env->GetPkgManager()->ClosePkgStream(stream);
117     pthread_mutex_lock(&info->mutex);
118     LOG(DEBUG) << "new data writer ending...";
119     // extract new data done.
120     // tell command.
121     info->readyToWrite = false;
122     UPDATER_WARING_CHECK (info->writer == nullptr, "writer is null", pthread_cond_broadcast(&info->cond));
123     pthread_mutex_unlock(&info->mutex);
124     return nullptr;
125 }
126 
ReturnAndPushParam(int32_t returnValue,uscript::UScriptContext & context)127 static int32_t ReturnAndPushParam(int32_t returnValue, uscript::UScriptContext &context)
128 {
129     context.PushParam(returnValue);
130     return returnValue;
131 }
132 
133 struct UpdateBlockInfo {
134     std::string partitionName;
135     std::string transferName;
136     std::string newDataName;
137     std::string patchDataName;
138     std::string devPath;
139 };
140 
GetUpdateBlockInfo(struct UpdateBlockInfo & infos,uscript::UScriptEnv & env,uscript::UScriptContext & context)141 static int32_t GetUpdateBlockInfo(struct UpdateBlockInfo &infos, uscript::UScriptEnv &env,
142     uscript::UScriptContext &context)
143 {
144     UPDATER_ERROR_CHECK(context.GetParamCount() == 4, "Invalid param",
145     return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context));
146 
147     // Get partition Name first.
148     // Use partition name as zip file name. ${partition name}.zip
149     // load ${partition name}.zip from updater package.
150     // Try to unzip ${partition name}.zip, extract transfer.list, net.dat, patch.dat
151     size_t pos = 0;
152     int32_t ret = context.GetParam(pos++, infos.partitionName);
153     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get param 1", return ret);
154     ret = context.GetParam(pos++, infos.transferName);
155     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get param 2", return ret);
156     ret = context.GetParam(pos++, infos.newDataName);
157     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get param 3", return ret);
158     ret = context.GetParam(pos++, infos.patchDataName);
159     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get param 4", return ret);
160 
161     LOG(INFO) << "ExecuteUpdateBlock::updating  " << infos.partitionName << " ...";
162     infos.devPath = GetBlockDeviceByMountPoint(infos.partitionName);
163     LOG(INFO) << "ExecuteUpdateBlock::updating  dev path : " << infos.devPath;
164     UPDATER_ERROR_CHECK(!infos.devPath.empty(), "cannot get block device of partition",
165         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
166     return USCRIPT_SUCCESS;
167 }
168 
ExecuteTransferCommand(int fd,const std::vector<std::string> & lines,uscript::UScriptEnv & env,uscript::UScriptContext & context,const std::string & partitionName)169 static int32_t ExecuteTransferCommand(int fd, const std::vector<std::string> &lines, uscript::UScriptEnv &env,
170     uscript::UScriptContext &context, const std::string &partitionName)
171 {
172     TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
173     auto globalParams = tm->GetGlobalParams();
174     auto writerThreadInfo = globalParams->writerThreadInfo.get();
175 
176     globalParams->storeBase = "/data/updater/update_tmp";
177     globalParams->retryFile = std::string("/data/updater") + partitionName + "_retry";
178     LOG(INFO) << "Store base path is " << globalParams->storeBase;
179     int32_t ret = Store::CreateNewSpace(globalParams->storeBase, !globalParams->env->IsRetry());
180     UPDATER_ERROR_CHECK(ret != -1, "Error to create new store space",
181     return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
182     globalParams->storeCreated = ret;
183 
184     UPDATER_CHECK_ONLY_RETURN(tm->CommandsParser(fd, lines), return USCRIPT_ERROR_EXECUTE);
185     pthread_mutex_lock(&writerThreadInfo->mutex);
186     if (writerThreadInfo->readyToWrite) {
187         LOG(WARNING) << "New data writer thread is still available...";
188     }
189 
190     writerThreadInfo->readyToWrite = false;
191     pthread_cond_broadcast(&writerThreadInfo->cond);
192     pthread_mutex_unlock(&writerThreadInfo->mutex);
193     ret = pthread_join(globalParams->thread, nullptr);
194     std::ostringstream logMessage;
195     logMessage << "pthread join returned with " << strerror(ret);
196     UPDATER_WARNING_CHECK_NOT_RETURN(ret == 0, logMessage.str());
197     if (globalParams->storeCreated != -1) {
198         Store::DoFreeSpace(globalParams->storeBase);
199     }
200     return USCRIPT_SUCCESS;
201 }
202 
InitThread(struct UpdateBlockInfo & infos,uscript::UScriptEnv & env,uscript::UScriptContext & context)203 static int InitThread(struct UpdateBlockInfo &infos, uscript::UScriptEnv &env, uscript::UScriptContext &context)
204 {
205     TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
206     auto globalParams = tm->GetGlobalParams();
207     auto writerThreadInfo = globalParams->writerThreadInfo.get();
208     writerThreadInfo->readyToWrite = true;
209     pthread_mutex_init(&writerThreadInfo->mutex, nullptr);
210     pthread_cond_init(&writerThreadInfo->cond, nullptr);
211     pthread_attr_t attr;
212     pthread_attr_init(&attr);
213     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
214     writerThreadInfo->newPatch = infos.newDataName;
215     int error = pthread_create(&globalParams->thread, &attr, UnpackNewData, writerThreadInfo);
216     return error;
217 }
218 
ExtractDiffPackageAndLoad(const UpdateBlockInfo & infos,uscript::UScriptEnv & env,uscript::UScriptContext & context)219 static int32_t ExtractDiffPackageAndLoad(const UpdateBlockInfo &infos, uscript::UScriptEnv &env,
220     uscript::UScriptContext &context)
221 {
222     hpackage::PkgManager::StreamPtr outStream = nullptr;
223     LOG(DEBUG) << "partitionName is " << infos.partitionName;
224     const FileInfo *info = env.GetPkgManager()->GetFileInfo(infos.partitionName);
225     UPDATER_ERROR_CHECK(info != nullptr, "Error to get file info", return USCRIPT_ERROR_EXECUTE);
226     std::string diffPackage = std::string("/data/updater") + infos.partitionName;
227     int32_t ret = env.GetPkgManager()->CreatePkgStream(outStream,
228         diffPackage, info->unpackedSize, PkgStream::PkgStreamType_Write);
229     UPDATER_ERROR_CHECK(outStream != nullptr, "Error to create output stream", return USCRIPT_ERROR_EXECUTE);
230 
231     ret = env.GetPkgManager()->ExtractFile(infos.partitionName, outStream);
232     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file",
233         env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
234     env.GetPkgManager()->ClosePkgStream(outStream);
235     std::string diffPackageZip = diffPackage + ".zip";
236     rename(diffPackage.c_str(), diffPackageZip.c_str());
237     LOG(DEBUG) << "Rename " << diffPackage << " to zip\nExtract " << diffPackage << " done\nReload " << diffPackageZip;
238     std::vector<std::string> diffPackageComponents;
239     ret = env.GetPkgManager()->LoadPackage(diffPackageZip, updater::utils::GetCertName(), diffPackageComponents);
240     UPDATER_ERROR_CHECK(diffPackageComponents.size() >= 1, "Diff package is empty",
241         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
242     return USCRIPT_SUCCESS;
243 }
244 
DoExecuteUpdateBlock(UpdateBlockInfo & infos,uscript::UScriptEnv & env,hpackage::PkgManager::StreamPtr & outStream,const std::vector<std::string> & lines,uscript::UScriptContext & context)245 static int32_t DoExecuteUpdateBlock(UpdateBlockInfo &infos, uscript::UScriptEnv &env,
246     hpackage::PkgManager::StreamPtr &outStream, const std::vector<std::string> &lines, uscript::UScriptContext &context)
247 {
248     int fd = open(infos.devPath.c_str(), O_RDWR | O_LARGEFILE);
249     UPDATER_ERROR_CHECK (fd != -1, "Failed to open block",
250         env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
251     int32_t ret = ExecuteTransferCommand(fd, lines, env, context, infos.partitionName);
252     fsync(fd);
253     close(fd);
254     fd = -1;
255     env.GetPkgManager()->ClosePkgStream(outStream);
256     if (ret == USCRIPT_SUCCESS) {
257         PartitionRecord::GetInstance().RecordPartitionUpdateStatus(infos.partitionName, true);
258     }
259     return ret;
260 }
261 
ExecuteUpdateBlock(uscript::UScriptEnv & env,uscript::UScriptContext & context)262 static int32_t ExecuteUpdateBlock(uscript::UScriptEnv &env, uscript::UScriptContext &context)
263 {
264     UpdateBlockInfo infos {};
265     UPDATER_CHECK_ONLY_RETURN(!GetUpdateBlockInfo(infos, env, context), return USCRIPT_ERROR_EXECUTE);
266     UPDATER_ERROR_CHECK(env.GetPkgManager() != nullptr, "Error to get pkg manager", return USCRIPT_ERROR_EXECUTE);
267 
268     if (env.IsRetry()) {
269         LOG(DEBUG) << "Retry updater, check if current partition updatered already during last time";
270         bool isUpdated = PartitionRecord::GetInstance().IsPartitionUpdated(infos.partitionName);
271         if (isUpdated) {
272             LOG(INFO) << infos.partitionName << " already updated, skip";
273             return USCRIPT_SUCCESS;
274         }
275     }
276 
277     int32_t ret = ExtractDiffPackageAndLoad(infos, env, context);
278     UPDATER_CHECK_ONLY_RETURN(ret == USCRIPT_SUCCESS, return USCRIPT_ERROR_EXECUTE);
279 
280     const FileInfo *info = env.GetPkgManager()->GetFileInfo(infos.transferName);
281     hpackage::PkgManager::StreamPtr outStream = nullptr;
282     ret = env.GetPkgManager()->CreatePkgStream(outStream,
283         infos.transferName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
284     ret = env.GetPkgManager()->ExtractFile(infos.transferName, outStream);
285     uint8_t *transferListBuffer = nullptr;
286     size_t transferListSize = 0;
287     ret = outStream->GetBuffer(transferListBuffer, transferListSize);
288     TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
289     auto globalParams = tm->GetGlobalParams();
290     /* Save Script Env to transfer manager */
291     globalParams->env = &env;
292     std::vector<std::string> lines =
293         updater::utils::SplitString(std::string(reinterpret_cast<const char*>(transferListBuffer)), "\n");
294     LOG(INFO) << "Ready to start a thread to handle new data processing";
295 
296     UPDATER_ERROR_CHECK (InitThread(infos, env, context) == 0, "Failed to create pthread",
297         env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
298     LOG(DEBUG) << "Start unpack new data thread done. Get patch data: " << infos.patchDataName;
299     info = env.GetPkgManager()->GetFileInfo(infos.patchDataName);
300     // Close stream opened before.
301     env.GetPkgManager()->ClosePkgStream(outStream);
302     ret = env.GetPkgManager()->CreatePkgStream(outStream,
303         infos.patchDataName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
304     UPDATER_ERROR_CHECK(outStream != nullptr, "Error to create output stream", return USCRIPT_ERROR_EXECUTE);
305     ret = env.GetPkgManager()->ExtractFile(infos.patchDataName, outStream);
306     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file",
307         env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
308     outStream->GetBuffer(globalParams->patchDataBuffer, globalParams->patchDataSize);
309     LOG(DEBUG) << "Patch data size is: " << globalParams->patchDataSize;
310     ret = DoExecuteUpdateBlock(infos, env, outStream, lines, context);
311     TransferManager::ReleaseTransferManagerInstance(tm);
312     return ret;
313 }
314 
Execute(uscript::UScriptEnv & env,uscript::UScriptContext & context)315 int32_t UScriptInstructionBlockUpdate::Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context)
316 {
317     int32_t result = ExecuteUpdateBlock(env, context);
318     context.PushParam(result);
319     return result;
320 }
321 
Execute(uscript::UScriptEnv & env,uscript::UScriptContext & context)322 int32_t UScriptInstructionBlockCheck::Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context)
323 {
324     UPDATER_ERROR_CHECK(context.GetParamCount() == 1, "Invalid param",
325         return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context));
326     UPDATER_CHECK_ONLY_RETURN(!env.IsRetry(), return ReturnAndPushParam(USCRIPT_SUCCESS, context));
327 
328     std::string partitionName;
329     int32_t ret = context.GetParam(0, partitionName);
330     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
331         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
332     auto devPath = GetBlockDeviceByMountPoint(partitionName);
333     LOG(INFO) << "UScriptInstructionBlockCheck::dev path : " << devPath;
334     UPDATER_ERROR_CHECK(!devPath.empty(), "cannot get block device of partition",
335         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
336     int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
337     UPDATER_ERROR_CHECK(fd != -1, "Failed to open file",
338         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
339     std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
340     BlockSet blk0(std::vector<BlockPair> {BlockPair{0, 1}});
341 
342     size_t pos = 0;
343     std::vector<BlockPair>::iterator it = blk0.Begin();
344     for (; it != blk0.End(); ++it) {
345         LOG(INFO) << "BlockSet::ReadDataFromBlock lseek64";
346         ret = lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET);
347         UPDATER_ERROR_CHECK(ret != -1, "Failed to seek",
348             return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
349         size_t size = (it->second - it->first) * H_BLOCK_SIZE;
350         LOG(INFO) << "BlockSet::ReadDataFromBlock Read " << size << " from block";
351         UPDATER_ERROR_CHECK(utils::ReadFully(fd, block_buff.data() + pos, size), "Failed to read",
352             return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
353         pos += size;
354     }
355 
356     time_t mountTime = *reinterpret_cast<uint32_t *>(&block_buff[0x400 + 0x2C]);
357     uint16_t mountCount = *reinterpret_cast<uint16_t *>(&block_buff[0x400 + 0x34]);
358 
359     if (mountCount > 0) {
360         std::ostringstream ostr;
361         ostr << "Device was remounted R/W " << mountCount << "times\nLast remount happened on " <<
362             ctime(&mountTime) << std::endl;
363         std::string message = ostr.str();
364         env.PostMessage("ui_log", message);
365     }
366     LOG(INFO) << "UScriptInstructionBlockCheck::Execute Success";
367     context.PushParam(USCRIPT_SUCCESS);
368     return USCRIPT_SUCCESS;
369 }
370 
Execute(uscript::UScriptEnv & env,uscript::UScriptContext & context)371 int32_t UScriptInstructionShaCheck::Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context)
372 {
373     UPDATER_ERROR_CHECK(context.GetParamCount() == SHA_CHECK_PARAMS, "Invalid param",
374                         return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context));
375     UPDATER_CHECK_ONLY_RETURN(!env.IsRetry(), return ReturnAndPushParam(USCRIPT_SUCCESS, context));
376 
377     std::string partitionName;
378     int32_t ret = context.GetParam(0, partitionName);
379     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
380                         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
381     std::string blockPairs;
382     ret = context.GetParam(1, blockPairs);
383     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
384                         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
385     std::string contrastSha;
386     ret = context.GetParam(SHA_CHECK_SECOND, contrastSha);
387     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
388                         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
389     auto devPath = GetBlockDeviceByMountPoint(partitionName);
390     LOG(INFO) << "UScriptInstructionShaCheck::dev path : " << devPath;
391     UPDATER_ERROR_CHECK(!devPath.empty(), "cannot get block device of partition",
392                         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
393     int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
394     UPDATER_ERROR_CHECK(fd != -1, "Failed to open file",
395                         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
396 
397     BlockSet blk;
398     blk.ParserAndInsert(blockPairs);
399     std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
400 
401     SHA256_CTX ctx;
402     SHA256_Init(&ctx);
403 
404     std::vector<BlockPair>::iterator it = blk.Begin();
405     for (; it != blk.End(); ++it) {
406         ret = lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET);
407         UPDATER_ERROR_CHECK(ret != -1, "Failed to seek",
408             return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
409 
410         for (size_t i = it->first; i < it->second; ++i) {
411             UPDATER_ERROR_CHECK(utils::ReadFully(fd, block_buff.data(), H_BLOCK_SIZE), "Failed to read",
412                 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
413             SHA256_Update(&ctx, block_buff.data(), H_BLOCK_SIZE);
414         }
415     }
416     uint8_t digest[SHA256_DIGEST_LENGTH];
417     SHA256_Final(digest, &ctx);
418     std::string resultSha = utils::ConvertSha256Hex(digest, SHA256_DIGEST_LENGTH);
419     UPDATER_ERROR_CHECK(resultSha == contrastSha, "Different sha256, cannot continue",
420                         return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
421     LOG(INFO) << "UScriptInstructionShaCheck::Execute Success";
422     context.PushParam(USCRIPT_SUCCESS);
423     return USCRIPT_SUCCESS;
424 }
425 }
426