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/dump.h"
29 #include "log/log.h"
30 #include "updater/updater_const.h"
31 #include "updater/hwfault_retry.h"
32 #include "utils.h"
33
34 using namespace Uscript;
35 using namespace Hpackage;
36 using namespace Updater;
37
38 namespace Updater {
39 constexpr int32_t SHA_CHECK_SECOND = 2;
40 constexpr int32_t SHA_CHECK_PARAMS = 3;
ExtractNewData(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)41 static int ExtractNewData(const PkgBuffer &buffer, size_t size, size_t start, bool isFinish, const void* context)
42 {
43 void *p = const_cast<void *>(context);
44 WriterThreadInfo *info = static_cast<WriterThreadInfo *>(p);
45 uint8_t *addr = buffer.buffer;
46 while (size > 0) {
47 pthread_mutex_lock(&info->mutex);
48 while (info->writer == nullptr) {
49 if (!info->readyToWrite) {
50 LOG(WARNING) << "writer is not ready to write.";
51 pthread_mutex_unlock(&info->mutex);
52 return Hpackage::PKG_INVALID_STREAM;
53 }
54 pthread_cond_wait(&info->cond, &info->mutex);
55 }
56 pthread_mutex_unlock(&info->mutex);
57 size_t toWrite = std::min(size, info->writer->GetBlocksSize() - info->writer->GetTotalWritten());
58 // No more data to write.
59 if (toWrite == 0) {
60 break;
61 }
62 bool ret = info->writer->Write(addr, toWrite, nullptr);
63 std::ostringstream logMessage;
64 logMessage << "Write " << toWrite << " byte(s) failed";
65 if (!ret) {
66 LOG(ERROR) << logMessage.str();
67 return Hpackage::PKG_INVALID_STREAM;
68 }
69 size -= toWrite;
70 addr += toWrite;
71
72 if (info->writer->IsWriteDone()) {
73 pthread_mutex_lock(&info->mutex);
74 info->writer.reset();
75 pthread_cond_broadcast(&info->cond);
76 pthread_mutex_unlock(&info->mutex);
77 }
78 }
79 return Hpackage::PKG_SUCCESS;
80 }
81
CondBroadcast(WriterThreadInfo * info)82 static inline void CondBroadcast(WriterThreadInfo *info)
83 {
84 pthread_mutex_lock(&info->mutex);
85 info->readyToWrite = false;
86 if (info->writer != nullptr) {
87 pthread_cond_broadcast(&info->cond);
88 }
89 pthread_mutex_unlock(&info->mutex);
90 }
91
UnpackNewData(void * arg)92 void* UnpackNewData(void *arg)
93 {
94 TransferManagerPtr tm = static_cast<TransferManagerPtr>(arg);
95 WriterThreadInfo *info = tm->GetTransferParams()->writerThreadInfo.get();
96 Hpackage::PkgManager::StreamPtr stream = nullptr;
97 if (info->newPatch.empty()) {
98 LOG(ERROR) << "new patch file name is empty. thread quit.";
99 CondBroadcast(info);
100 return nullptr;
101 }
102 LOG(DEBUG) << "new patch file name: " << info->newPatch;
103 auto env = tm->GetTransferParams()->env;
104 const FileInfo *file = env->GetPkgManager()->GetFileInfo(info->newPatch);
105 if (file == nullptr) {
106 LOG(ERROR) << "Cannot get file info of :" << info->newPatch;
107 CondBroadcast(info);
108 return nullptr;
109 }
110 LOG(DEBUG) << info->newPatch << " info: size " << file->packedSize << " unpacked size " <<
111 file->unpackedSize << " name " << file->identity;
112 int32_t ret = env->GetPkgManager()->CreatePkgStream(stream, info->newPatch, ExtractNewData, info);
113 if (ret != Hpackage::PKG_SUCCESS || stream == nullptr) {
114 LOG(ERROR) << "Cannot extract " << info->newPatch << " from package.";
115 CondBroadcast(info);
116 return nullptr;
117 }
118 ret = env->GetPkgManager()->ExtractFile(info->newPatch, stream);
119 env->GetPkgManager()->ClosePkgStream(stream);
120 LOG(DEBUG) << "new data writer ending...";
121 // extract new data done.
122 // tell command.
123 CondBroadcast(info);
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 if (context.GetParamCount() != 4) { // 4:Determine the number of parameters
145 LOG(ERROR) << "Invalid param";
146 return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
147 }
148
149 // Get partition Name first.
150 // Use partition name as zip file name. ${partition name}.zip
151 // load ${partition name}.zip from updater package.
152 // Try to unzip ${partition name}.zip, extract transfer.list, net.dat, patch.dat
153 size_t pos = 0;
154 int32_t ret = context.GetParam(pos++, infos.partitionName);
155 if (ret != USCRIPT_SUCCESS) {
156 LOG(ERROR) << "Error to get param 1";
157 return ret;
158 }
159 ret = context.GetParam(pos++, infos.transferName);
160 if (ret != USCRIPT_SUCCESS) {
161 LOG(ERROR) << "Error to get param 2";
162 return ret;
163 }
164 ret = context.GetParam(pos++, infos.newDataName);
165 if (ret != USCRIPT_SUCCESS) {
166 LOG(ERROR) << "Error to get param 3";
167 return ret;
168 }
169 ret = context.GetParam(pos++, infos.patchDataName);
170 if (ret != USCRIPT_SUCCESS) {
171 LOG(ERROR) << "Error to get param 4";
172 return ret;
173 }
174
175 LOG(INFO) << "ExecuteUpdateBlock::updating " << infos.partitionName << " ...";
176 infos.devPath = GetBlockDeviceByMountPoint(infos.partitionName);
177 LOG(INFO) << "ExecuteUpdateBlock::updating dev path : " << infos.devPath;
178 if (infos.devPath.empty()) {
179 LOG(ERROR) << "cannot get block device of partition";
180 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
181 }
182 return USCRIPT_SUCCESS;
183 }
184
ExecuteTransferCommand(int fd,const std::vector<std::string> & lines,TransferManagerPtr tm,Uscript::UScriptContext & context,const std::string & partitionName)185 static int32_t ExecuteTransferCommand(int fd, const std::vector<std::string> &lines, TransferManagerPtr tm,
186 Uscript::UScriptContext &context, const std::string &partitionName)
187 {
188 auto transferParams = tm->GetTransferParams();
189 auto writerThreadInfo = transferParams->writerThreadInfo.get();
190
191 transferParams->storeBase = std::string("/data/updater") + partitionName + "_tmp";
192 transferParams->retryFile = std::string("/data/updater") + partitionName + "_retry";
193 LOG(INFO) << "Store base path is " << transferParams->storeBase;
194 int32_t ret = Store::CreateNewSpace(transferParams->storeBase, !transferParams->env->IsRetry());
195 if (ret == -1) {
196 LOG(ERROR) << "Error to create new store space";
197 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
198 }
199 transferParams->storeCreated = ret;
200
201 if (!tm->CommandsParser(fd, lines)) {
202 return USCRIPT_ERROR_EXECUTE;
203 }
204 pthread_mutex_lock(&writerThreadInfo->mutex);
205 if (writerThreadInfo->readyToWrite) {
206 LOG(WARNING) << "New data writer thread is still available...";
207 }
208
209 writerThreadInfo->readyToWrite = false;
210 pthread_cond_broadcast(&writerThreadInfo->cond);
211 pthread_mutex_unlock(&writerThreadInfo->mutex);
212 ret = pthread_join(transferParams->thread, nullptr);
213 std::ostringstream logMessage;
214 logMessage << "pthread join returned with " << ret;
215 if (ret != 0) {
216 LOG(WARNING) << logMessage.str();
217 }
218 if (transferParams->storeCreated != -1) {
219 Store::DoFreeSpace(transferParams->storeBase);
220 }
221 return USCRIPT_SUCCESS;
222 }
223
InitThread(const struct UpdateBlockInfo & infos,TransferManagerPtr tm)224 static int InitThread(const struct UpdateBlockInfo &infos, TransferManagerPtr tm)
225 {
226 auto transferParams = tm->GetTransferParams();
227 auto writerThreadInfo = transferParams->writerThreadInfo.get();
228 writerThreadInfo->readyToWrite = true;
229 pthread_mutex_init(&writerThreadInfo->mutex, nullptr);
230 pthread_cond_init(&writerThreadInfo->cond, nullptr);
231 pthread_attr_t attr;
232 pthread_attr_init(&attr);
233 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
234 writerThreadInfo->newPatch = infos.newDataName;
235 int error = pthread_create(&transferParams->thread, &attr, UnpackNewData, tm);
236 return error;
237 }
238
ExtractDiffPackageAndLoad(const UpdateBlockInfo & infos,Uscript::UScriptEnv & env,Uscript::UScriptContext & context)239 static int32_t ExtractDiffPackageAndLoad(const UpdateBlockInfo &infos, Uscript::UScriptEnv &env,
240 Uscript::UScriptContext &context)
241 {
242 Hpackage::PkgManager::StreamPtr outStream = nullptr;
243 LOG(DEBUG) << "partitionName is " << infos.partitionName;
244 const FileInfo *info = env.GetPkgManager()->GetFileInfo(infos.partitionName);
245 if (info == nullptr) {
246 LOG(WARNING) << "Error to get file info";
247 return USCRIPT_SUCCESS;
248 }
249 std::string diffPackage = std::string("/data/updater") + infos.partitionName;
250 int32_t ret = env.GetPkgManager()->CreatePkgStream(outStream,
251 diffPackage, info->unpackedSize, PkgStream::PkgStreamType_Write);
252 if (outStream == nullptr) {
253 LOG(ERROR) << "Error to create output stream";
254 return USCRIPT_ERROR_EXECUTE;
255 }
256
257 ret = env.GetPkgManager()->ExtractFile(infos.partitionName, outStream);
258 if (ret != USCRIPT_SUCCESS) {
259 LOG(ERROR) << "Error to extract file";
260 env.GetPkgManager()->ClosePkgStream(outStream);
261 return USCRIPT_ERROR_EXECUTE;
262 }
263 env.GetPkgManager()->ClosePkgStream(outStream);
264 std::string diffPackageZip = diffPackage + ".zip";
265 if (rename(diffPackage.c_str(), diffPackageZip.c_str()) != 0) {
266 LOG(ERROR) << "rename failed";
267 return USCRIPT_ERROR_EXECUTE;
268 }
269 LOG(DEBUG) << "Rename " << diffPackage << " to zip\nExtract " << diffPackage << " done\nReload " << diffPackageZip;
270 std::vector<std::string> diffPackageComponents;
271 ret = env.GetPkgManager()->LoadPackage(diffPackageZip, Updater::Utils::GetCertName(), diffPackageComponents);
272 if (diffPackageComponents.size() < 1) {
273 LOG(ERROR) << "Diff package is empty";
274 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
275 }
276 return USCRIPT_SUCCESS;
277 }
278
DoExecuteUpdateBlock(const UpdateBlockInfo & infos,TransferManagerPtr tm,Hpackage::PkgManager::StreamPtr & outStream,const std::vector<std::string> & lines,Uscript::UScriptContext & context)279 static int32_t DoExecuteUpdateBlock(const UpdateBlockInfo &infos, TransferManagerPtr tm,
280 Hpackage::PkgManager::StreamPtr &outStream, const std::vector<std::string> &lines, Uscript::UScriptContext &context)
281 {
282 int fd = open(infos.devPath.c_str(), O_RDWR | O_LARGEFILE);
283 auto env = tm->GetTransferParams()->env;
284 if (fd == -1) {
285 LOG(ERROR) << "Failed to open block";
286 env->GetPkgManager()->ClosePkgStream(outStream);
287 return USCRIPT_ERROR_EXECUTE;
288 }
289 int32_t ret = ExecuteTransferCommand(fd, lines, tm, context, infos.partitionName);
290 fsync(fd);
291 close(fd);
292 fd = -1;
293 env->GetPkgManager()->ClosePkgStream(outStream);
294 if (ret == USCRIPT_SUCCESS) {
295 PartitionRecord::GetInstance().RecordPartitionUpdateStatus(infos.partitionName, true);
296 }
297 return ret;
298 }
299
ExtractFileByName(Uscript::UScriptEnv & env,const std::string & fileName,Hpackage::PkgManager::StreamPtr & outStream,uint8_t * & outBuf,size_t & buffSize)300 static int32_t ExtractFileByName(Uscript::UScriptEnv &env, const std::string &fileName,
301 Hpackage::PkgManager::StreamPtr &outStream, uint8_t *&outBuf, size_t &buffSize)
302 {
303 if (env.GetPkgManager() == nullptr) {
304 LOG(ERROR) << "Error to get pkg manager";
305 return USCRIPT_ERROR_EXECUTE;
306 }
307
308 const FileInfo *info = env.GetPkgManager()->GetFileInfo(fileName);
309 if (info == nullptr) {
310 LOG(ERROR) << "GetFileInfo fail";
311 return USCRIPT_ERROR_EXECUTE;
312 }
313 auto ret = env.GetPkgManager()->CreatePkgStream(outStream,
314 fileName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
315 if (ret != USCRIPT_SUCCESS || outStream == nullptr) {
316 LOG(ERROR) << "Error to create output stream";
317 return USCRIPT_ERROR_EXECUTE;
318 }
319 ret = env.GetPkgManager()->ExtractFile(fileName, outStream);
320 if (ret != USCRIPT_SUCCESS) {
321 LOG(ERROR) << "Error to extract file";
322 env.GetPkgManager()->ClosePkgStream(outStream);
323 return USCRIPT_ERROR_EXECUTE;
324 }
325 ret = outStream->GetBuffer(outBuf, buffSize);
326 LOG(DEBUG) << "outBuf data size is: " << buffSize;
327
328 return USCRIPT_SUCCESS;
329 }
330
ExecuteUpdateBlock(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)331 static int32_t ExecuteUpdateBlock(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
332 {
333 UpdateBlockInfo infos {};
334 if (GetUpdateBlockInfo(infos, env, context) != USCRIPT_SUCCESS) {
335 return USCRIPT_ERROR_EXECUTE;
336 }
337
338 if (env.IsRetry()) {
339 LOG(DEBUG) << "Retry updater, check if current partition updatered already during last time";
340 if (PartitionRecord::GetInstance().IsPartitionUpdated(infos.partitionName)) {
341 LOG(INFO) << infos.partitionName << " already updated, skip";
342 return USCRIPT_SUCCESS;
343 }
344 }
345
346 if (ExtractDiffPackageAndLoad(infos, env, context) != USCRIPT_SUCCESS) {
347 return USCRIPT_ERROR_EXECUTE;
348 }
349
350 uint8_t *transferListBuffer = nullptr;
351 size_t transferListSize = 0;
352 Hpackage::PkgManager::StreamPtr outStream = nullptr;
353 if (ExtractFileByName(env, infos.transferName, outStream, transferListBuffer, transferListSize) != USCRIPT_SUCCESS) {
354 return USCRIPT_ERROR_EXECUTE;
355 }
356
357 std::unique_ptr<TransferManager> tm = std::make_unique<TransferManager>();
358
359 auto transferParams = tm->GetTransferParams();
360 /* Save Script Env to transfer manager */
361 transferParams->env = &env;
362
363 std::vector<std::string> lines =
364 Updater::Utils::SplitString(std::string(reinterpret_cast<const char*>(transferListBuffer)), "\n");
365 // Close stream opened before.
366 env.GetPkgManager()->ClosePkgStream(outStream);
367
368 LOG(INFO) << "Start unpack new data thread done. Get patch data: " << infos.patchDataName;
369 if (ExtractFileByName(env, infos.patchDataName, outStream,
370 transferParams->patchDataBuffer, transferParams->patchDataSize) != USCRIPT_SUCCESS) {
371 return USCRIPT_ERROR_EXECUTE;
372 }
373
374 LOG(INFO) << "Ready to start a thread to handle new data processing";
375 if (InitThread(infos, tm.get()) != 0) {
376 LOG(ERROR) << "Failed to create pthread";
377 env.GetPkgManager()->ClosePkgStream(outStream);
378 return USCRIPT_ERROR_EXECUTE;
379 }
380
381 return DoExecuteUpdateBlock(infos, tm.get(), outStream, lines, context);
382 }
383
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)384 int32_t UScriptInstructionBlockUpdate::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
385 {
386 int32_t result = ExecuteUpdateBlock(env, context);
387 context.PushParam(result);
388 return result;
389 }
390
ExecReadBlockInfo(const std::string & devPath,Uscript::UScriptContext & context,time_t & mountTime,uint16_t & mountCount)391 bool UScriptInstructionBlockCheck::ExecReadBlockInfo(const std::string &devPath, Uscript::UScriptContext &context,
392 time_t &mountTime, uint16_t &mountCount)
393 {
394 UPDATER_INIT_RECORD;
395 int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
396 if (fd == -1) {
397 LOG(ERROR) << "Failed to open file";
398 UPDATER_LAST_WORD(false);
399 return false;
400 }
401 std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
402 BlockSet blk0(std::vector<BlockPair> {BlockPair{0, 1}});
403
404 size_t pos = 0;
405 std::vector<BlockPair>::iterator it = blk0.Begin();
406 for (; it != blk0.End(); ++it) {
407 LOG(INFO) << "BlockSet::ReadDataFromBlock lseek64";
408 if (lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET) == -1) {
409 LOG(ERROR) << "Failed to seek";
410 close(fd);
411 UPDATER_LAST_WORD(false);
412 return false;
413 }
414 size_t size = (it->second - it->first) * H_BLOCK_SIZE;
415 LOG(INFO) << "BlockSet::ReadDataFromBlock Read " << size << " from block";
416 if (!Utils::ReadFully(fd, block_buff.data() + pos, size)) {
417 LOG(ERROR) << "Failed to read";
418 close(fd);
419 UPDATER_LAST_WORD(false);
420 return false;
421 }
422 pos += size;
423 }
424 close(fd);
425 mountTime = *reinterpret_cast<uint32_t *>(&block_buff[0x400 + 0x2C]);
426 mountCount = *reinterpret_cast<uint16_t *>(&block_buff[0x400 + 0x34]);
427 return true;
428 }
429
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)430 int32_t UScriptInstructionBlockCheck::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
431 {
432 if (context.GetParamCount() != 1) {
433 LOG(ERROR) << "Invalid param";
434 UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM);
435 return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
436 }
437 if (env.IsRetry()) {
438 return ReturnAndPushParam(USCRIPT_SUCCESS, context);
439 }
440 std::string partitionName;
441 int32_t ret = context.GetParam(0, partitionName);
442 if (ret != USCRIPT_SUCCESS) {
443 LOG(ERROR) << "Failed to get param";
444 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
445 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
446 }
447 auto devPath = GetBlockDeviceByMountPoint(partitionName);
448 LOG(INFO) << "UScriptInstructionBlockCheck::dev path : " << devPath;
449 time_t mountTime = 0;
450 uint16_t mountCount = 0;
451 if (devPath.empty() || (!ExecReadBlockInfo(devPath, context, mountTime, mountCount))) {
452 LOG(ERROR) << "cannot get block device of partition";
453 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
454 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
455 }
456
457 if (mountCount > 0) {
458 std::ostringstream ostr;
459 ostr << "Device was remounted R/W " << mountCount << "times\nLast remount happened on " <<
460 ctime(&mountTime) << std::endl;
461 std::string message = ostr.str();
462 env.PostMessage("ui_log", message);
463 LOG(ERROR) << message;
464 }
465 LOG(INFO) << "UScriptInstructionBlockCheck::Execute Success";
466 context.PushParam(USCRIPT_SUCCESS);
467 return USCRIPT_SUCCESS;
468 }
469
ExecReadShaInfo(Uscript::UScriptEnv & env,const std::string & devPath,const std::string & blockPairs,const std::string & contrastSha)470 int UScriptInstructionShaCheck::ExecReadShaInfo(Uscript::UScriptEnv &env, const std::string &devPath,
471 const std::string &blockPairs, const std::string &contrastSha)
472 {
473 UPDATER_INIT_RECORD;
474 int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
475 if (fd == -1) {
476 LOG(ERROR) << "Failed to open file";
477 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
478 return USCRIPT_ERROR_EXECUTE;
479 }
480
481 BlockSet blk;
482 blk.ParserAndInsert(blockPairs);
483 std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
484 SHA256_CTX ctx;
485 SHA256_Init(&ctx);
486 std::vector<BlockPair>::iterator it = blk.Begin();
487 for (; it != blk.End(); ++it) {
488 if (lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET) == -1) {
489 LOG(ERROR) << "Failed to seek";
490 close(fd);
491 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
492 return USCRIPT_ERROR_EXECUTE;
493 }
494 for (size_t i = it->first; i < it->second; ++i) {
495 if (!Utils::ReadFully(fd, block_buff.data(), H_BLOCK_SIZE)) {
496 LOG(ERROR) << "Failed to read";
497 close(fd);
498 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
499 return USCRIPT_ERROR_EXECUTE;
500 }
501 SHA256_Update(&ctx, block_buff.data(), H_BLOCK_SIZE);
502 }
503 }
504 close(fd);
505
506 uint8_t digest[SHA256_DIGEST_LENGTH];
507 SHA256_Final(digest, &ctx);
508 std::string resultSha = Utils::ConvertSha256Hex(digest, SHA256_DIGEST_LENGTH);
509 if (resultSha != contrastSha) {
510 LOG(ERROR) << "Different sha256, cannot continue";
511 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
512 env.PostMessage(UPDATER_RETRY_TAG, VERIFY_FAILED_REBOOT);
513 return USCRIPT_ERROR_EXECUTE;
514 }
515 LOG(INFO) << "UScriptInstructionShaCheck::Execute Success";
516 return USCRIPT_SUCCESS;
517 }
518
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)519 int32_t UScriptInstructionShaCheck::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
520 {
521 if (context.GetParamCount() != SHA_CHECK_PARAMS) {
522 LOG(ERROR) << "Invalid param";
523 UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM);
524 return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
525 }
526 if (env.IsRetry() && !Utils::CheckFaultInfo(VERIFY_FAILED_REBOOT)) {
527 return ReturnAndPushParam(USCRIPT_SUCCESS, context);
528 }
529
530 std::string partitionName;
531 int32_t ret = context.GetParam(0, partitionName);
532 if (ret != USCRIPT_SUCCESS) {
533 LOG(ERROR) << "Failed to get param";
534 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
535 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
536 }
537 std::string blockPairs;
538 ret = context.GetParam(1, blockPairs);
539 if (ret != USCRIPT_SUCCESS) {
540 LOG(ERROR) << "Failed to get param";
541 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
542 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
543 }
544 std::string contrastSha;
545 ret = context.GetParam(SHA_CHECK_SECOND, contrastSha);
546 if (ret != USCRIPT_SUCCESS) {
547 LOG(ERROR) << "Failed to get param";
548 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
549 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
550 }
551 auto devPath = GetBlockDeviceByMountPoint(partitionName);
552 LOG(INFO) << "UScriptInstructionShaCheck::dev path : " << devPath;
553 if (devPath.empty()) {
554 LOG(ERROR) << "cannot get block device of partition";
555 UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
556 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
557 }
558 ret = ExecReadShaInfo(env, devPath, blockPairs, contrastSha);
559 return ReturnAndPushParam(ret, context);
560 }
561 }
562