1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "update_image_block.h"
16fb299fa2Sopenharmony_ci#include <cerrno>
17fb299fa2Sopenharmony_ci#include <fcntl.h>
18fb299fa2Sopenharmony_ci#include <pthread.h>
19fb299fa2Sopenharmony_ci#include <sstream>
20fb299fa2Sopenharmony_ci#include <sys/stat.h>
21fb299fa2Sopenharmony_ci#include <sys/types.h>
22fb299fa2Sopenharmony_ci#include <unistd.h>
23fb299fa2Sopenharmony_ci#include "applypatch/block_set.h"
24fb299fa2Sopenharmony_ci#include "applypatch/store.h"
25fb299fa2Sopenharmony_ci#include "applypatch/transfer_manager.h"
26fb299fa2Sopenharmony_ci#include "applypatch/partition_record.h"
27fb299fa2Sopenharmony_ci#include "fs_manager/mount.h"
28fb299fa2Sopenharmony_ci#include "log/dump.h"
29fb299fa2Sopenharmony_ci#include "log/log.h"
30fb299fa2Sopenharmony_ci#include "updater/updater_const.h"
31fb299fa2Sopenharmony_ci#include "updater/hwfault_retry.h"
32fb299fa2Sopenharmony_ci#include "utils.h"
33fb299fa2Sopenharmony_ci
34fb299fa2Sopenharmony_ciusing namespace Uscript;
35fb299fa2Sopenharmony_ciusing namespace Hpackage;
36fb299fa2Sopenharmony_ciusing namespace Updater;
37fb299fa2Sopenharmony_ci
38fb299fa2Sopenharmony_cinamespace Updater {
39fb299fa2Sopenharmony_ciconstexpr int32_t SHA_CHECK_SECOND = 2;
40fb299fa2Sopenharmony_ciconstexpr int32_t SHA_CHECK_PARAMS = 3;
41fb299fa2Sopenharmony_ciconstexpr int32_t SHA_CHECK_TARGETPAIRS_INDEX = 3;
42fb299fa2Sopenharmony_ciconstexpr int32_t SHA_CHECK_TARGETSHA_INDEX = 4;
43fb299fa2Sopenharmony_ciconstexpr int32_t SHA_CHECK_TARGET_PARAMS = 5;
44fb299fa2Sopenharmony_cistatic int ExtractNewData(const PkgBuffer &buffer, size_t size, size_t start, bool isFinish, const void* context)
45fb299fa2Sopenharmony_ci{
46fb299fa2Sopenharmony_ci    void *p = const_cast<void *>(context);
47fb299fa2Sopenharmony_ci    WriterThreadInfo *info = static_cast<WriterThreadInfo *>(p);
48fb299fa2Sopenharmony_ci    uint8_t *addr = buffer.buffer;
49fb299fa2Sopenharmony_ci    while (size > 0) {
50fb299fa2Sopenharmony_ci        pthread_mutex_lock(&info->mutex);
51fb299fa2Sopenharmony_ci        while (info->writer == nullptr) {
52fb299fa2Sopenharmony_ci            if (!info->readyToWrite) {
53fb299fa2Sopenharmony_ci                LOG(WARNING) << "writer is not ready to write.";
54fb299fa2Sopenharmony_ci                pthread_mutex_unlock(&info->mutex);
55fb299fa2Sopenharmony_ci                return Hpackage::PKG_INVALID_STREAM;
56fb299fa2Sopenharmony_ci            }
57fb299fa2Sopenharmony_ci            pthread_cond_wait(&info->cond, &info->mutex);
58fb299fa2Sopenharmony_ci        }
59fb299fa2Sopenharmony_ci        pthread_mutex_unlock(&info->mutex);
60fb299fa2Sopenharmony_ci        size_t toWrite = std::min(size, info->writer->GetBlocksSize() - info->writer->GetTotalWritten());
61fb299fa2Sopenharmony_ci        // No more data to write.
62fb299fa2Sopenharmony_ci        if (toWrite == 0) {
63fb299fa2Sopenharmony_ci            break;
64fb299fa2Sopenharmony_ci        }
65fb299fa2Sopenharmony_ci        bool ret = info->writer->Write(addr, toWrite, nullptr);
66fb299fa2Sopenharmony_ci        std::ostringstream logMessage;
67fb299fa2Sopenharmony_ci        logMessage << "Write " << toWrite << " byte(s) failed";
68fb299fa2Sopenharmony_ci        if (!ret) {
69fb299fa2Sopenharmony_ci            LOG(ERROR) << logMessage.str();
70fb299fa2Sopenharmony_ci            return Hpackage::PKG_INVALID_STREAM;
71fb299fa2Sopenharmony_ci        }
72fb299fa2Sopenharmony_ci        size -= toWrite;
73fb299fa2Sopenharmony_ci        addr += toWrite;
74fb299fa2Sopenharmony_ci
75fb299fa2Sopenharmony_ci        if (info->writer->IsWriteDone()) {
76fb299fa2Sopenharmony_ci            pthread_mutex_lock(&info->mutex);
77fb299fa2Sopenharmony_ci            info->writer.reset();
78fb299fa2Sopenharmony_ci            pthread_cond_broadcast(&info->cond);
79fb299fa2Sopenharmony_ci            pthread_mutex_unlock(&info->mutex);
80fb299fa2Sopenharmony_ci        }
81fb299fa2Sopenharmony_ci    }
82fb299fa2Sopenharmony_ci    return Hpackage::PKG_SUCCESS;
83fb299fa2Sopenharmony_ci}
84fb299fa2Sopenharmony_ci
85fb299fa2Sopenharmony_cistatic inline void CondBroadcast(WriterThreadInfo *info)
86fb299fa2Sopenharmony_ci{
87fb299fa2Sopenharmony_ci    pthread_mutex_lock(&info->mutex);
88fb299fa2Sopenharmony_ci    info->readyToWrite = false;
89fb299fa2Sopenharmony_ci    if (info->writer != nullptr) {
90fb299fa2Sopenharmony_ci        pthread_cond_broadcast(&info->cond);
91fb299fa2Sopenharmony_ci    }
92fb299fa2Sopenharmony_ci    pthread_mutex_unlock(&info->mutex);
93fb299fa2Sopenharmony_ci}
94fb299fa2Sopenharmony_ci
95fb299fa2Sopenharmony_civoid* UnpackNewData(void *arg)
96fb299fa2Sopenharmony_ci{
97fb299fa2Sopenharmony_ci    TransferManagerPtr tm = static_cast<TransferManagerPtr>(arg);
98fb299fa2Sopenharmony_ci    WriterThreadInfo *info = tm->GetTransferParams()->writerThreadInfo.get();
99fb299fa2Sopenharmony_ci    Hpackage::PkgManager::StreamPtr stream = nullptr;
100fb299fa2Sopenharmony_ci    if (info->newPatch.empty()) {
101fb299fa2Sopenharmony_ci        LOG(ERROR) << "new patch file name is empty. thread quit.";
102fb299fa2Sopenharmony_ci        CondBroadcast(info);
103fb299fa2Sopenharmony_ci        return nullptr;
104fb299fa2Sopenharmony_ci    }
105fb299fa2Sopenharmony_ci    LOG(DEBUG) << "new patch file name: " << info->newPatch;
106fb299fa2Sopenharmony_ci    auto env = tm->GetTransferParams()->env;
107fb299fa2Sopenharmony_ci    const FileInfo *file = env->GetPkgManager()->GetFileInfo(info->newPatch);
108fb299fa2Sopenharmony_ci    if (file == nullptr) {
109fb299fa2Sopenharmony_ci        LOG(ERROR) << "Cannot get file info of :" << info->newPatch;
110fb299fa2Sopenharmony_ci        CondBroadcast(info);
111fb299fa2Sopenharmony_ci        return nullptr;
112fb299fa2Sopenharmony_ci    }
113fb299fa2Sopenharmony_ci    LOG(DEBUG) << info->newPatch << " info: size " << file->packedSize << " unpacked size " <<
114fb299fa2Sopenharmony_ci        file->unpackedSize << " name " << file->identity;
115fb299fa2Sopenharmony_ci    int32_t ret = env->GetPkgManager()->CreatePkgStream(stream, info->newPatch, ExtractNewData, info);
116fb299fa2Sopenharmony_ci    if (ret != Hpackage::PKG_SUCCESS || stream == nullptr) {
117fb299fa2Sopenharmony_ci        LOG(ERROR) << "Cannot extract " << info->newPatch << " from package.";
118fb299fa2Sopenharmony_ci        CondBroadcast(info);
119fb299fa2Sopenharmony_ci        return nullptr;
120fb299fa2Sopenharmony_ci    }
121fb299fa2Sopenharmony_ci    ret = env->GetPkgManager()->ExtractFile(info->newPatch, stream);
122fb299fa2Sopenharmony_ci    env->GetPkgManager()->ClosePkgStream(stream);
123fb299fa2Sopenharmony_ci    LOG(DEBUG) << "new data writer ending...";
124fb299fa2Sopenharmony_ci    // extract new data done.
125fb299fa2Sopenharmony_ci    // tell command.
126fb299fa2Sopenharmony_ci    CondBroadcast(info);
127fb299fa2Sopenharmony_ci    return nullptr;
128fb299fa2Sopenharmony_ci}
129fb299fa2Sopenharmony_ci
130fb299fa2Sopenharmony_cistatic int32_t ReturnAndPushParam(int32_t returnValue, Uscript::UScriptContext &context)
131fb299fa2Sopenharmony_ci{
132fb299fa2Sopenharmony_ci    context.PushParam(returnValue);
133fb299fa2Sopenharmony_ci    return returnValue;
134fb299fa2Sopenharmony_ci}
135fb299fa2Sopenharmony_ci
136fb299fa2Sopenharmony_cistruct UpdateBlockInfo {
137fb299fa2Sopenharmony_ci    std::string partitionName;
138fb299fa2Sopenharmony_ci    std::string transferName;
139fb299fa2Sopenharmony_ci    std::string newDataName;
140fb299fa2Sopenharmony_ci    std::string patchDataName;
141fb299fa2Sopenharmony_ci    std::string devPath;
142fb299fa2Sopenharmony_ci};
143fb299fa2Sopenharmony_ci
144fb299fa2Sopenharmony_cistatic int32_t GetUpdateBlockInfo(struct UpdateBlockInfo &infos, Uscript::UScriptEnv &env,
145fb299fa2Sopenharmony_ci    Uscript::UScriptContext &context)
146fb299fa2Sopenharmony_ci{
147fb299fa2Sopenharmony_ci    if (context.GetParamCount() != 4) { // 4:Determine the number of parameters
148fb299fa2Sopenharmony_ci        LOG(ERROR) << "Invalid param";
149fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
150fb299fa2Sopenharmony_ci    }
151fb299fa2Sopenharmony_ci
152fb299fa2Sopenharmony_ci    // Get partition Name first.
153fb299fa2Sopenharmony_ci    // Use partition name as zip file name. ${partition name}.zip
154fb299fa2Sopenharmony_ci    // load ${partition name}.zip from updater package.
155fb299fa2Sopenharmony_ci    // Try to unzip ${partition name}.zip, extract transfer.list, net.dat, patch.dat
156fb299fa2Sopenharmony_ci    size_t pos = 0;
157fb299fa2Sopenharmony_ci    int32_t ret = context.GetParam(pos++, infos.partitionName);
158fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
159fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to get param 1";
160fb299fa2Sopenharmony_ci        return ret;
161fb299fa2Sopenharmony_ci    }
162fb299fa2Sopenharmony_ci    ret = context.GetParam(pos++, infos.transferName);
163fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
164fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to get param 2";
165fb299fa2Sopenharmony_ci        return ret;
166fb299fa2Sopenharmony_ci    }
167fb299fa2Sopenharmony_ci    ret = context.GetParam(pos++, infos.newDataName);
168fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
169fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to get param 3";
170fb299fa2Sopenharmony_ci        return ret;
171fb299fa2Sopenharmony_ci    }
172fb299fa2Sopenharmony_ci    ret = context.GetParam(pos++, infos.patchDataName);
173fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
174fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to get param 4";
175fb299fa2Sopenharmony_ci        return ret;
176fb299fa2Sopenharmony_ci    }
177fb299fa2Sopenharmony_ci
178fb299fa2Sopenharmony_ci    LOG(INFO) << "ExecuteUpdateBlock::updating  " << infos.partitionName << " ...";
179fb299fa2Sopenharmony_ci    infos.devPath = GetBlockDeviceByMountPoint(infos.partitionName);
180fb299fa2Sopenharmony_ci    LOG(INFO) << "ExecuteUpdateBlock::updating  dev path : " << infos.devPath;
181fb299fa2Sopenharmony_ci    if (infos.devPath.empty()) {
182fb299fa2Sopenharmony_ci        LOG(ERROR) << "cannot get block device of partition";
183fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
184fb299fa2Sopenharmony_ci    }
185fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
186fb299fa2Sopenharmony_ci}
187fb299fa2Sopenharmony_ci
188fb299fa2Sopenharmony_cistatic int32_t ExecuteTransferCommand(int fd, const std::vector<std::string> &lines, TransferManagerPtr tm,
189fb299fa2Sopenharmony_ci    Uscript::UScriptContext &context, const UpdateBlockInfo &infos)
190fb299fa2Sopenharmony_ci{
191fb299fa2Sopenharmony_ci    auto transferParams = tm->GetTransferParams();
192fb299fa2Sopenharmony_ci    auto writerThreadInfo = transferParams->writerThreadInfo.get();
193fb299fa2Sopenharmony_ci
194fb299fa2Sopenharmony_ci    transferParams->storeBase = std::string("/data/updater") + infos.partitionName + "_tmp";
195fb299fa2Sopenharmony_ci    transferParams->retryFile = std::string("/data/updater") + infos.partitionName + "_retry";
196fb299fa2Sopenharmony_ci    transferParams->devPath = infos.devPath;
197fb299fa2Sopenharmony_ci    LOG(INFO) << "Store base path is " << transferParams->storeBase;
198fb299fa2Sopenharmony_ci    int32_t ret = Store::CreateNewSpace(transferParams->storeBase, !transferParams->env->IsRetry());
199fb299fa2Sopenharmony_ci    if (ret == -1) {
200fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to create new store space";
201fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
202fb299fa2Sopenharmony_ci    }
203fb299fa2Sopenharmony_ci    transferParams->storeCreated = ret;
204fb299fa2Sopenharmony_ci
205fb299fa2Sopenharmony_ci    if (!tm->CommandsParser(fd, lines)) {
206fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
207fb299fa2Sopenharmony_ci    }
208fb299fa2Sopenharmony_ci    pthread_mutex_lock(&writerThreadInfo->mutex);
209fb299fa2Sopenharmony_ci    if (writerThreadInfo->readyToWrite) {
210fb299fa2Sopenharmony_ci        LOG(WARNING) << "New data writer thread is still available...";
211fb299fa2Sopenharmony_ci    }
212fb299fa2Sopenharmony_ci
213fb299fa2Sopenharmony_ci    writerThreadInfo->readyToWrite = false;
214fb299fa2Sopenharmony_ci    pthread_cond_broadcast(&writerThreadInfo->cond);
215fb299fa2Sopenharmony_ci    pthread_mutex_unlock(&writerThreadInfo->mutex);
216fb299fa2Sopenharmony_ci    ret = pthread_join(transferParams->thread, nullptr);
217fb299fa2Sopenharmony_ci    std::ostringstream logMessage;
218fb299fa2Sopenharmony_ci    logMessage << "pthread join returned with " << ret;
219fb299fa2Sopenharmony_ci    if (ret != 0) {
220fb299fa2Sopenharmony_ci        LOG(WARNING) << logMessage.str();
221fb299fa2Sopenharmony_ci    }
222fb299fa2Sopenharmony_ci    if (transferParams->storeCreated != -1) {
223fb299fa2Sopenharmony_ci        Store::DoFreeSpace(transferParams->storeBase);
224fb299fa2Sopenharmony_ci    }
225fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
226fb299fa2Sopenharmony_ci}
227fb299fa2Sopenharmony_ci
228fb299fa2Sopenharmony_cistatic int InitThread(const struct UpdateBlockInfo &infos, TransferManagerPtr tm)
229fb299fa2Sopenharmony_ci{
230fb299fa2Sopenharmony_ci    auto transferParams = tm->GetTransferParams();
231fb299fa2Sopenharmony_ci    auto writerThreadInfo = transferParams->writerThreadInfo.get();
232fb299fa2Sopenharmony_ci    writerThreadInfo->readyToWrite = true;
233fb299fa2Sopenharmony_ci    pthread_mutex_init(&writerThreadInfo->mutex, nullptr);
234fb299fa2Sopenharmony_ci    pthread_cond_init(&writerThreadInfo->cond, nullptr);
235fb299fa2Sopenharmony_ci    pthread_attr_t attr;
236fb299fa2Sopenharmony_ci    pthread_attr_init(&attr);
237fb299fa2Sopenharmony_ci    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
238fb299fa2Sopenharmony_ci    writerThreadInfo->newPatch = infos.newDataName;
239fb299fa2Sopenharmony_ci    int error = pthread_create(&transferParams->thread, &attr, UnpackNewData, tm);
240fb299fa2Sopenharmony_ci    return error;
241fb299fa2Sopenharmony_ci}
242fb299fa2Sopenharmony_ci
243fb299fa2Sopenharmony_cistatic int32_t ExtractDiffPackageAndLoad(const UpdateBlockInfo &infos, Uscript::UScriptEnv &env,
244fb299fa2Sopenharmony_ci    Uscript::UScriptContext &context)
245fb299fa2Sopenharmony_ci{
246fb299fa2Sopenharmony_ci    Hpackage::PkgManager::StreamPtr outStream = nullptr;
247fb299fa2Sopenharmony_ci    LOG(DEBUG) << "partitionName is " << infos.partitionName;
248fb299fa2Sopenharmony_ci    const FileInfo *info = env.GetPkgManager()->GetFileInfo(infos.partitionName);
249fb299fa2Sopenharmony_ci    if (info == nullptr) {
250fb299fa2Sopenharmony_ci        LOG(WARNING) << "Error to get file info";
251fb299fa2Sopenharmony_ci        return USCRIPT_SUCCESS;
252fb299fa2Sopenharmony_ci    }
253fb299fa2Sopenharmony_ci    std::string diffPackage = std::string("/data/updater") + infos.partitionName;
254fb299fa2Sopenharmony_ci    int32_t ret = env.GetPkgManager()->CreatePkgStream(outStream,
255fb299fa2Sopenharmony_ci        diffPackage, info->unpackedSize, PkgStream::PkgStreamType_Write);
256fb299fa2Sopenharmony_ci    if (outStream == nullptr) {
257fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to create output stream";
258fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
259fb299fa2Sopenharmony_ci    }
260fb299fa2Sopenharmony_ci
261fb299fa2Sopenharmony_ci    ret = env.GetPkgManager()->ExtractFile(infos.partitionName, outStream);
262fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
263fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to extract file";
264fb299fa2Sopenharmony_ci        env.GetPkgManager()->ClosePkgStream(outStream);
265fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
266fb299fa2Sopenharmony_ci    }
267fb299fa2Sopenharmony_ci    env.GetPkgManager()->ClosePkgStream(outStream);
268fb299fa2Sopenharmony_ci    std::string diffPackageZip = diffPackage + ".zip";
269fb299fa2Sopenharmony_ci    if (rename(diffPackage.c_str(), diffPackageZip.c_str()) != 0) {
270fb299fa2Sopenharmony_ci        LOG(ERROR) << "rename failed";
271fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
272fb299fa2Sopenharmony_ci    }
273fb299fa2Sopenharmony_ci    LOG(DEBUG) << "Rename " << diffPackage << " to zip\nExtract " << diffPackage << " done\nReload " << diffPackageZip;
274fb299fa2Sopenharmony_ci    std::vector<std::string> diffPackageComponents;
275fb299fa2Sopenharmony_ci    ret = env.GetPkgManager()->LoadPackage(diffPackageZip, Updater::Utils::GetCertName(), diffPackageComponents);
276fb299fa2Sopenharmony_ci    if (diffPackageComponents.size() < 1) {
277fb299fa2Sopenharmony_ci        LOG(ERROR) << "Diff package is empty";
278fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
279fb299fa2Sopenharmony_ci    }
280fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
281fb299fa2Sopenharmony_ci}
282fb299fa2Sopenharmony_ci
283fb299fa2Sopenharmony_cistatic int32_t DoExecuteUpdateBlock(const UpdateBlockInfo &infos, TransferManagerPtr tm,
284fb299fa2Sopenharmony_ci    Hpackage::PkgManager::StreamPtr &outStream, const std::vector<std::string> &lines, Uscript::UScriptContext &context)
285fb299fa2Sopenharmony_ci{
286fb299fa2Sopenharmony_ci    int fd = open(infos.devPath.c_str(), O_RDWR | O_LARGEFILE);
287fb299fa2Sopenharmony_ci    auto env = tm->GetTransferParams()->env;
288fb299fa2Sopenharmony_ci    if (fd == -1) {
289fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to open block";
290fb299fa2Sopenharmony_ci        env->GetPkgManager()->ClosePkgStream(outStream);
291fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
292fb299fa2Sopenharmony_ci    }
293fb299fa2Sopenharmony_ci    int32_t ret = ExecuteTransferCommand(fd, lines, tm, context, infos);
294fb299fa2Sopenharmony_ci    fsync(fd);
295fb299fa2Sopenharmony_ci    close(fd);
296fb299fa2Sopenharmony_ci    fd = -1;
297fb299fa2Sopenharmony_ci    env->GetPkgManager()->ClosePkgStream(outStream);
298fb299fa2Sopenharmony_ci    if (ret == USCRIPT_SUCCESS) {
299fb299fa2Sopenharmony_ci        PartitionRecord::GetInstance().RecordPartitionUpdateStatus(infos.partitionName, true);
300fb299fa2Sopenharmony_ci    }
301fb299fa2Sopenharmony_ci    return ret;
302fb299fa2Sopenharmony_ci}
303fb299fa2Sopenharmony_ci
304fb299fa2Sopenharmony_cistatic int32_t ExtractFileByName(Uscript::UScriptEnv &env, const std::string &fileName,
305fb299fa2Sopenharmony_ci    Hpackage::PkgManager::StreamPtr &outStream, uint8_t *&outBuf, size_t &buffSize)
306fb299fa2Sopenharmony_ci{
307fb299fa2Sopenharmony_ci    if (env.GetPkgManager() == nullptr) {
308fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to get pkg manager";
309fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
310fb299fa2Sopenharmony_ci    }
311fb299fa2Sopenharmony_ci
312fb299fa2Sopenharmony_ci    const FileInfo *info = env.GetPkgManager()->GetFileInfo(fileName);
313fb299fa2Sopenharmony_ci    if (info == nullptr) {
314fb299fa2Sopenharmony_ci        LOG(ERROR) << "GetFileInfo fail";
315fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
316fb299fa2Sopenharmony_ci    }
317fb299fa2Sopenharmony_ci    auto ret = env.GetPkgManager()->CreatePkgStream(outStream,
318fb299fa2Sopenharmony_ci        fileName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
319fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS || outStream == nullptr) {
320fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to create output stream";
321fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
322fb299fa2Sopenharmony_ci    }
323fb299fa2Sopenharmony_ci    ret = env.GetPkgManager()->ExtractFile(fileName, outStream);
324fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
325fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to extract file";
326fb299fa2Sopenharmony_ci        env.GetPkgManager()->ClosePkgStream(outStream);
327fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
328fb299fa2Sopenharmony_ci    }
329fb299fa2Sopenharmony_ci    ret = outStream->GetBuffer(outBuf, buffSize);
330fb299fa2Sopenharmony_ci    LOG(DEBUG) << "outBuf data size is: " << buffSize;
331fb299fa2Sopenharmony_ci
332fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
333fb299fa2Sopenharmony_ci}
334fb299fa2Sopenharmony_ci
335fb299fa2Sopenharmony_cistatic int32_t ExecuteUpdateBlock(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
336fb299fa2Sopenharmony_ci{
337fb299fa2Sopenharmony_ci    UpdateBlockInfo infos {};
338fb299fa2Sopenharmony_ci    if (GetUpdateBlockInfo(infos, env, context) != USCRIPT_SUCCESS) {
339fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
340fb299fa2Sopenharmony_ci    }
341fb299fa2Sopenharmony_ci
342fb299fa2Sopenharmony_ci    if (env.IsRetry()) {
343fb299fa2Sopenharmony_ci        LOG(DEBUG) << "Retry updater, check if current partition updatered already during last time";
344fb299fa2Sopenharmony_ci        if (PartitionRecord::GetInstance().IsPartitionUpdated(infos.partitionName)) {
345fb299fa2Sopenharmony_ci            LOG(INFO) << infos.partitionName << " already updated, skip";
346fb299fa2Sopenharmony_ci            return USCRIPT_SUCCESS;
347fb299fa2Sopenharmony_ci        }
348fb299fa2Sopenharmony_ci    }
349fb299fa2Sopenharmony_ci
350fb299fa2Sopenharmony_ci    if (ExtractDiffPackageAndLoad(infos, env, context) != USCRIPT_SUCCESS) {
351fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
352fb299fa2Sopenharmony_ci    }
353fb299fa2Sopenharmony_ci
354fb299fa2Sopenharmony_ci    uint8_t *transferListBuffer = nullptr;
355fb299fa2Sopenharmony_ci    size_t transferListSize = 0;
356fb299fa2Sopenharmony_ci    Hpackage::PkgManager::StreamPtr outStream = nullptr;
357fb299fa2Sopenharmony_ci    if (ExtractFileByName(env, infos.transferName, outStream,
358fb299fa2Sopenharmony_ci                          transferListBuffer, transferListSize) != USCRIPT_SUCCESS) {
359fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
360fb299fa2Sopenharmony_ci    }
361fb299fa2Sopenharmony_ci
362fb299fa2Sopenharmony_ci    std::unique_ptr<TransferManager> tm = std::make_unique<TransferManager>();
363fb299fa2Sopenharmony_ci
364fb299fa2Sopenharmony_ci    auto transferParams = tm->GetTransferParams();
365fb299fa2Sopenharmony_ci    /* Save Script Env to transfer manager */
366fb299fa2Sopenharmony_ci    transferParams->env = &env;
367fb299fa2Sopenharmony_ci
368fb299fa2Sopenharmony_ci    transferParams->canWrite = true;
369fb299fa2Sopenharmony_ci    std::vector<std::string> lines =
370fb299fa2Sopenharmony_ci        Updater::Utils::SplitString(std::string(reinterpret_cast<const char*>(transferListBuffer)), "\n");
371fb299fa2Sopenharmony_ci    // Close stream opened before.
372fb299fa2Sopenharmony_ci    env.GetPkgManager()->ClosePkgStream(outStream);
373fb299fa2Sopenharmony_ci
374fb299fa2Sopenharmony_ci    LOG(INFO) << "Start unpack new data thread done. Get patch data: " << infos.patchDataName;
375fb299fa2Sopenharmony_ci    if (ExtractFileByName(env, infos.patchDataName, outStream,
376fb299fa2Sopenharmony_ci        transferParams->patchDataBuffer, transferParams->patchDataSize) != USCRIPT_SUCCESS) {
377fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
378fb299fa2Sopenharmony_ci    }
379fb299fa2Sopenharmony_ci
380fb299fa2Sopenharmony_ci    LOG(INFO) << "Ready to start a thread to handle new data processing";
381fb299fa2Sopenharmony_ci    if (InitThread(infos, tm.get()) != 0) {
382fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to create pthread";
383fb299fa2Sopenharmony_ci        env.GetPkgManager()->ClosePkgStream(outStream);
384fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
385fb299fa2Sopenharmony_ci    }
386fb299fa2Sopenharmony_ci
387fb299fa2Sopenharmony_ci    return DoExecuteUpdateBlock(infos, tm.get(), outStream, lines, context);
388fb299fa2Sopenharmony_ci}
389fb299fa2Sopenharmony_ci
390fb299fa2Sopenharmony_ciint32_t UScriptInstructionBlockUpdate::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
391fb299fa2Sopenharmony_ci{
392fb299fa2Sopenharmony_ci    int32_t result = ExecuteUpdateBlock(env, context);
393fb299fa2Sopenharmony_ci    context.PushParam(result);
394fb299fa2Sopenharmony_ci    return result;
395fb299fa2Sopenharmony_ci}
396fb299fa2Sopenharmony_ci
397fb299fa2Sopenharmony_cibool UScriptInstructionBlockCheck::ExecReadBlockInfo(const std::string &devPath, Uscript::UScriptContext &context,
398fb299fa2Sopenharmony_ci    time_t &mountTime, uint16_t &mountCount)
399fb299fa2Sopenharmony_ci{
400fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
401fb299fa2Sopenharmony_ci    int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
402fb299fa2Sopenharmony_ci    if (fd == -1) {
403fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to open file";
404fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(false);
405fb299fa2Sopenharmony_ci        return false;
406fb299fa2Sopenharmony_ci    }
407fb299fa2Sopenharmony_ci    std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
408fb299fa2Sopenharmony_ci    BlockSet blk0(std::vector<BlockPair> {BlockPair{0, 1}});
409fb299fa2Sopenharmony_ci
410fb299fa2Sopenharmony_ci    size_t pos = 0;
411fb299fa2Sopenharmony_ci    std::vector<BlockPair>::iterator it = blk0.Begin();
412fb299fa2Sopenharmony_ci    for (; it != blk0.End(); ++it) {
413fb299fa2Sopenharmony_ci        LOG(INFO) << "BlockSet::ReadDataFromBlock lseek64";
414fb299fa2Sopenharmony_ci        if (lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET) == -1) {
415fb299fa2Sopenharmony_ci            LOG(ERROR) << "Failed to seek";
416fb299fa2Sopenharmony_ci            close(fd);
417fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(false);
418fb299fa2Sopenharmony_ci            return false;
419fb299fa2Sopenharmony_ci        }
420fb299fa2Sopenharmony_ci        size_t size = (it->second - it->first) * H_BLOCK_SIZE;
421fb299fa2Sopenharmony_ci        LOG(INFO) << "BlockSet::ReadDataFromBlock Read " << size << " from block";
422fb299fa2Sopenharmony_ci        if (!Utils::ReadFully(fd, block_buff.data() + pos, size)) {
423fb299fa2Sopenharmony_ci            LOG(ERROR) << "Failed to read";
424fb299fa2Sopenharmony_ci            close(fd);
425fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(false);
426fb299fa2Sopenharmony_ci            return false;
427fb299fa2Sopenharmony_ci        }
428fb299fa2Sopenharmony_ci        pos += size;
429fb299fa2Sopenharmony_ci    }
430fb299fa2Sopenharmony_ci    close(fd);
431fb299fa2Sopenharmony_ci    mountTime = *reinterpret_cast<uint32_t *>(&block_buff[0x400 + 0x2C]);
432fb299fa2Sopenharmony_ci    mountCount = *reinterpret_cast<uint16_t *>(&block_buff[0x400 + 0x34]);
433fb299fa2Sopenharmony_ci    return true;
434fb299fa2Sopenharmony_ci}
435fb299fa2Sopenharmony_ci
436fb299fa2Sopenharmony_ciint32_t UScriptInstructionBlockCheck::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
437fb299fa2Sopenharmony_ci{
438fb299fa2Sopenharmony_ci    if (context.GetParamCount() != 1) {
439fb299fa2Sopenharmony_ci        LOG(ERROR) << "Invalid param";
440fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM);
441fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
442fb299fa2Sopenharmony_ci    }
443fb299fa2Sopenharmony_ci    if (env.IsRetry()) {
444fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_SUCCESS, context);
445fb299fa2Sopenharmony_ci    }
446fb299fa2Sopenharmony_ci    std::string partitionName;
447fb299fa2Sopenharmony_ci    int32_t ret = context.GetParam(0, partitionName);
448fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
449fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to get param";
450fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
451fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
452fb299fa2Sopenharmony_ci    }
453fb299fa2Sopenharmony_ci    auto devPath = GetBlockDeviceByMountPoint(partitionName);
454fb299fa2Sopenharmony_ci    LOG(INFO) << "UScriptInstructionBlockCheck::dev path : " << devPath;
455fb299fa2Sopenharmony_ci    time_t mountTime = 0;
456fb299fa2Sopenharmony_ci    uint16_t mountCount = 0;
457fb299fa2Sopenharmony_ci    if (devPath.empty() || (!ExecReadBlockInfo(devPath, context, mountTime, mountCount))) {
458fb299fa2Sopenharmony_ci        LOG(ERROR) << "cannot get block device of partition";
459fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
460fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
461fb299fa2Sopenharmony_ci    }
462fb299fa2Sopenharmony_ci
463fb299fa2Sopenharmony_ci    if (mountCount > 0) {
464fb299fa2Sopenharmony_ci        std::ostringstream ostr;
465fb299fa2Sopenharmony_ci        ostr << "Device was remounted R/W " << mountCount << "times\nLast remount happened on " <<
466fb299fa2Sopenharmony_ci            ctime(&mountTime) << std::endl;
467fb299fa2Sopenharmony_ci        std::string message = ostr.str();
468fb299fa2Sopenharmony_ci        env.PostMessage("ui_log", message);
469fb299fa2Sopenharmony_ci        LOG(ERROR) << message;
470fb299fa2Sopenharmony_ci    }
471fb299fa2Sopenharmony_ci    LOG(INFO) << "UScriptInstructionBlockCheck::Execute Success";
472fb299fa2Sopenharmony_ci    context.PushParam(USCRIPT_SUCCESS);
473fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
474fb299fa2Sopenharmony_ci}
475fb299fa2Sopenharmony_ci
476fb299fa2Sopenharmony_cistatic std::string GetPartName(const std::string &partitionName)
477fb299fa2Sopenharmony_ci{
478fb299fa2Sopenharmony_ci    if (partitionName.empty()) {
479fb299fa2Sopenharmony_ci        return "";
480fb299fa2Sopenharmony_ci    }
481fb299fa2Sopenharmony_ci    return partitionName[0] == '/' ? partitionName.substr(1) : partitionName;
482fb299fa2Sopenharmony_ci}
483fb299fa2Sopenharmony_ci
484fb299fa2Sopenharmony_ciint32_t UScriptInstructionShaCheck::DoBlocksVerify(Uscript::UScriptEnv &env, const std::string &partitionName,
485fb299fa2Sopenharmony_ci    const std::string &devPath)
486fb299fa2Sopenharmony_ci{
487fb299fa2Sopenharmony_ci    UpdateBlockInfo infos {};
488fb299fa2Sopenharmony_ci    infos.partitionName = partitionName;
489fb299fa2Sopenharmony_ci    infos.transferName = GetPartName(partitionName) + ".transfer.list";
490fb299fa2Sopenharmony_ci    uint8_t *transferListBuffer = nullptr;
491fb299fa2Sopenharmony_ci    size_t transferListSize = 0;
492fb299fa2Sopenharmony_ci    Hpackage::PkgManager::StreamPtr outStream = nullptr;
493fb299fa2Sopenharmony_ci
494fb299fa2Sopenharmony_ci    if (ExtractFileByName(env, infos.transferName, outStream,
495fb299fa2Sopenharmony_ci                          transferListBuffer, transferListSize) != USCRIPT_SUCCESS) {
496fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to extract " << infos.transferName;
497fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
498fb299fa2Sopenharmony_ci    }
499fb299fa2Sopenharmony_ci
500fb299fa2Sopenharmony_ci    std::vector<std::string> lines =
501fb299fa2Sopenharmony_ci        Updater::Utils::SplitString(std::string(reinterpret_cast<const char*>(transferListBuffer)), "\n");
502fb299fa2Sopenharmony_ci    // Close stream opened before.
503fb299fa2Sopenharmony_ci    env.GetPkgManager()->ClosePkgStream(outStream);
504fb299fa2Sopenharmony_ci
505fb299fa2Sopenharmony_ci    std::unique_ptr<TransferManager> tm = std::make_unique<TransferManager>();
506fb299fa2Sopenharmony_ci    auto transferParams = tm->GetTransferParams();
507fb299fa2Sopenharmony_ci    transferParams->env = &env;
508fb299fa2Sopenharmony_ci    transferParams->canWrite = false;
509fb299fa2Sopenharmony_ci    transferParams->devPath = devPath;
510fb299fa2Sopenharmony_ci    transferParams->storeBase = std::string("/data/updater") + partitionName + "_tmp";
511fb299fa2Sopenharmony_ci    transferParams->retryFile = std::string("/data/updater") + partitionName + "_retry";
512fb299fa2Sopenharmony_ci
513fb299fa2Sopenharmony_ci    LOG(INFO) << "Store base path is " << transferParams->storeBase;
514fb299fa2Sopenharmony_ci    transferParams->storeCreated = Store::CreateNewSpace(transferParams->storeBase, !transferParams->env->IsRetry());
515fb299fa2Sopenharmony_ci    if (transferParams->storeCreated == -1) {
516fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to create new store space";
517fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
518fb299fa2Sopenharmony_ci    }
519fb299fa2Sopenharmony_ci    int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
520fb299fa2Sopenharmony_ci    if (fd == -1) {
521fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to open block";
522fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
523fb299fa2Sopenharmony_ci    }
524fb299fa2Sopenharmony_ci    if (!tm->CommandsParser(fd, lines)) {
525fb299fa2Sopenharmony_ci        close(fd);
526fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to block verify";
527fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
528fb299fa2Sopenharmony_ci    }
529fb299fa2Sopenharmony_ci    if (transferParams->storeCreated != -1) {
530fb299fa2Sopenharmony_ci        Store::DoFreeSpace(transferParams->storeBase);
531fb299fa2Sopenharmony_ci    }
532fb299fa2Sopenharmony_ci    close(fd);
533fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
534fb299fa2Sopenharmony_ci}
535fb299fa2Sopenharmony_ci
536fb299fa2Sopenharmony_cibool UScriptInstructionShaCheck::IsTargetShaDiff(const std::string &devPath, const ShaInfo &shaInfo)
537fb299fa2Sopenharmony_ci{
538fb299fa2Sopenharmony_ci    std::string tgtResultSha = CalculateBlockSha(devPath, shaInfo.targetPairs);
539fb299fa2Sopenharmony_ci    if (tgtResultSha.empty()) {
540fb299fa2Sopenharmony_ci        LOG(WARNING) << "target sha is empty";
541fb299fa2Sopenharmony_ci        return true;
542fb299fa2Sopenharmony_ci    }
543fb299fa2Sopenharmony_ci    LOG(INFO) << "tgtResultSha: " << tgtResultSha << ", shaInfo.targetSha: " << shaInfo.targetSha;
544fb299fa2Sopenharmony_ci    return (tgtResultSha != shaInfo.targetSha);
545fb299fa2Sopenharmony_ci}
546fb299fa2Sopenharmony_ci
547fb299fa2Sopenharmony_ciint UScriptInstructionShaCheck::ExecReadShaInfo(Uscript::UScriptEnv &env, const std::string &devPath,
548fb299fa2Sopenharmony_ci    const ShaInfo &shaInfo, const std::string &partitionName)
549fb299fa2Sopenharmony_ci{
550fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
551fb299fa2Sopenharmony_ci    std::string resultSha = CalculateBlockSha(devPath, shaInfo.blockPairs);
552fb299fa2Sopenharmony_ci    if (resultSha != shaInfo.contrastSha && IsTargetShaDiff(devPath, shaInfo)) {
553fb299fa2Sopenharmony_ci        if (DoBlocksVerify(env, partitionName, devPath) != USCRIPT_SUCCESS) {
554fb299fa2Sopenharmony_ci            LOG(ERROR) << "Different sha256, cannot continue";
555fb299fa2Sopenharmony_ci            LOG(ERROR) << "blockPairs:" << shaInfo.blockPairs;
556fb299fa2Sopenharmony_ci            LOG(ERROR) << "resultSha: " << resultSha << ", shaInfo.contrastSha: " << shaInfo.contrastSha;
557fb299fa2Sopenharmony_ci            PrintAbnormalBlockHash(devPath, shaInfo.blockPairs);
558fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(devPath.substr(devPath.find_last_of("/") + 1), USCRIPT_ERROR_EXECUTE);
559fb299fa2Sopenharmony_ci            env.PostMessage(UPDATER_RETRY_TAG, VERIFY_FAILED_REBOOT);
560fb299fa2Sopenharmony_ci            return USCRIPT_ERROR_EXECUTE;
561fb299fa2Sopenharmony_ci        }
562fb299fa2Sopenharmony_ci    }
563fb299fa2Sopenharmony_ci    LOG(INFO) << "UScriptInstructionShaCheck::Execute Success";
564fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
565fb299fa2Sopenharmony_ci}
566fb299fa2Sopenharmony_ci
567fb299fa2Sopenharmony_civoid UScriptInstructionShaCheck::PrintAbnormalBlockHash(const std::string &devPath, const std::string &blockPairs)
568fb299fa2Sopenharmony_ci{
569fb299fa2Sopenharmony_ci    int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
570fb299fa2Sopenharmony_ci    if (fd == -1) {
571fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to open file " << devPath;
572fb299fa2Sopenharmony_ci        return;
573fb299fa2Sopenharmony_ci    }
574fb299fa2Sopenharmony_ci
575fb299fa2Sopenharmony_ci    BlockSet blk;
576fb299fa2Sopenharmony_ci    blk.ParserAndInsert(blockPairs);
577fb299fa2Sopenharmony_ci    std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
578fb299fa2Sopenharmony_ci    std::vector<BlockPair>::iterator it = blk.Begin();
579fb299fa2Sopenharmony_ci    for (; it != blk.End(); ++it) {
580fb299fa2Sopenharmony_ci        if (lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET) == -1) {
581fb299fa2Sopenharmony_ci            LOG(ERROR) << "Failed to seek";
582fb299fa2Sopenharmony_ci            close(fd);
583fb299fa2Sopenharmony_ci            return;
584fb299fa2Sopenharmony_ci        }
585fb299fa2Sopenharmony_ci        SHA256_CTX ctx;
586fb299fa2Sopenharmony_ci        SHA256_Init(&ctx);
587fb299fa2Sopenharmony_ci        for (size_t i = it->first; i < it->second; ++i) {
588fb299fa2Sopenharmony_ci            if (!Utils::ReadFully(fd, block_buff.data(), H_BLOCK_SIZE)) {
589fb299fa2Sopenharmony_ci                LOG(ERROR) << "Failed to read";
590fb299fa2Sopenharmony_ci                close(fd);
591fb299fa2Sopenharmony_ci                return;
592fb299fa2Sopenharmony_ci            }
593fb299fa2Sopenharmony_ci            SHA256_Update(&ctx, block_buff.data(), H_BLOCK_SIZE);
594fb299fa2Sopenharmony_ci        }
595fb299fa2Sopenharmony_ci        uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
596fb299fa2Sopenharmony_ci        SHA256_Final(digest, &ctx);
597fb299fa2Sopenharmony_ci        LOG(ERROR) << "block id:" << it->first << "-" << it->second <<
598fb299fa2Sopenharmony_ci            " hex:" << Utils::ConvertSha256Hex(digest, SHA256_DIGEST_LENGTH);
599fb299fa2Sopenharmony_ci    }
600fb299fa2Sopenharmony_ci    close(fd);
601fb299fa2Sopenharmony_ci}
602fb299fa2Sopenharmony_ci
603fb299fa2Sopenharmony_cistd::string UScriptInstructionShaCheck::CalculateBlockSha(const std::string &devPath, const std::string &blockPairs)
604fb299fa2Sopenharmony_ci{
605fb299fa2Sopenharmony_ci    if (blockPairs.empty()) {
606fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to get blockPairs";
607fb299fa2Sopenharmony_ci        return "";
608fb299fa2Sopenharmony_ci    }
609fb299fa2Sopenharmony_ci
610fb299fa2Sopenharmony_ci    int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
611fb299fa2Sopenharmony_ci    if (fd == -1) {
612fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to open file";
613fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
614fb299fa2Sopenharmony_ci        return "";
615fb299fa2Sopenharmony_ci    }
616fb299fa2Sopenharmony_ci
617fb299fa2Sopenharmony_ci    BlockSet blk;
618fb299fa2Sopenharmony_ci    blk.ParserAndInsert(blockPairs);
619fb299fa2Sopenharmony_ci    std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
620fb299fa2Sopenharmony_ci    SHA256_CTX ctx;
621fb299fa2Sopenharmony_ci    SHA256_Init(&ctx);
622fb299fa2Sopenharmony_ci    std::vector<BlockPair>::iterator it = blk.Begin();
623fb299fa2Sopenharmony_ci    for (; it != blk.End(); ++it) {
624fb299fa2Sopenharmony_ci        if (lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET) == -1) {
625fb299fa2Sopenharmony_ci            LOG(ERROR) << "Failed to seek";
626fb299fa2Sopenharmony_ci            close(fd);
627fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
628fb299fa2Sopenharmony_ci            return "";
629fb299fa2Sopenharmony_ci        }
630fb299fa2Sopenharmony_ci        for (size_t i = it->first; i < it->second; ++i) {
631fb299fa2Sopenharmony_ci            if (!Utils::ReadFully(fd, block_buff.data(), H_BLOCK_SIZE)) {
632fb299fa2Sopenharmony_ci                LOG(ERROR) << "Failed to read";
633fb299fa2Sopenharmony_ci                close(fd);
634fb299fa2Sopenharmony_ci                UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
635fb299fa2Sopenharmony_ci                return "";
636fb299fa2Sopenharmony_ci            }
637fb299fa2Sopenharmony_ci            SHA256_Update(&ctx, block_buff.data(), H_BLOCK_SIZE);
638fb299fa2Sopenharmony_ci        }
639fb299fa2Sopenharmony_ci    }
640fb299fa2Sopenharmony_ci    close(fd);
641fb299fa2Sopenharmony_ci
642fb299fa2Sopenharmony_ci    uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
643fb299fa2Sopenharmony_ci    SHA256_Final(digest, &ctx);
644fb299fa2Sopenharmony_ci    return Utils::ConvertSha256Hex(digest, SHA256_DIGEST_LENGTH);
645fb299fa2Sopenharmony_ci}
646fb299fa2Sopenharmony_ci
647fb299fa2Sopenharmony_ciint32_t UScriptInstructionShaCheck::SetShaInfo(Uscript::UScriptContext &context, ShaInfo &shaInfo)
648fb299fa2Sopenharmony_ci{
649fb299fa2Sopenharmony_ci    int32_t ret = context.GetParam(1, shaInfo.blockPairs);
650fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
651fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to get param blockPairs";
652fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
653fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
654fb299fa2Sopenharmony_ci    }
655fb299fa2Sopenharmony_ci
656fb299fa2Sopenharmony_ci    ret = context.GetParam(SHA_CHECK_SECOND, shaInfo.contrastSha);
657fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
658fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to get param contrastSha";
659fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
660fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
661fb299fa2Sopenharmony_ci    }
662fb299fa2Sopenharmony_ci
663fb299fa2Sopenharmony_ci    // Only three parameters can be obtained for the upgrade package of an earlier version.
664fb299fa2Sopenharmony_ci    ret = context.GetParam(SHA_CHECK_TARGETPAIRS_INDEX, shaInfo.targetPairs);
665fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
666fb299fa2Sopenharmony_ci        LOG(WARNING) << "Failed to get param targetPairs";
667fb299fa2Sopenharmony_ci    }
668fb299fa2Sopenharmony_ci
669fb299fa2Sopenharmony_ci    ret = context.GetParam(SHA_CHECK_TARGETSHA_INDEX, shaInfo.targetSha);
670fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
671fb299fa2Sopenharmony_ci        LOG(WARNING) << "Failed to get param targetSha";
672fb299fa2Sopenharmony_ci    }
673fb299fa2Sopenharmony_ci
674fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
675fb299fa2Sopenharmony_ci}
676fb299fa2Sopenharmony_ci
677fb299fa2Sopenharmony_ciint32_t UScriptInstructionShaCheck::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
678fb299fa2Sopenharmony_ci{
679fb299fa2Sopenharmony_ci    int32_t paramCount = context.GetParamCount();
680fb299fa2Sopenharmony_ci    if (paramCount != SHA_CHECK_PARAMS && paramCount != SHA_CHECK_TARGET_PARAMS) {
681fb299fa2Sopenharmony_ci        LOG(ERROR) << "Invalid param";
682fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM);
683fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
684fb299fa2Sopenharmony_ci    }
685fb299fa2Sopenharmony_ci    if (env.IsRetry() && !Utils::CheckFaultInfo(VERIFY_FAILED_REBOOT)) {
686fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_SUCCESS, context);
687fb299fa2Sopenharmony_ci    }
688fb299fa2Sopenharmony_ci
689fb299fa2Sopenharmony_ci    std::string partitionName;
690fb299fa2Sopenharmony_ci    int32_t ret = context.GetParam(0, partitionName);
691fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
692fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to get param";
693fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
694fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
695fb299fa2Sopenharmony_ci    }
696fb299fa2Sopenharmony_ci
697fb299fa2Sopenharmony_ci    ShaInfo shaInfo {};
698fb299fa2Sopenharmony_ci    ret = SetShaInfo(context, shaInfo);
699fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
700fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to set sha info";
701fb299fa2Sopenharmony_ci        return ReturnAndPushParam(ret, context);
702fb299fa2Sopenharmony_ci    }
703fb299fa2Sopenharmony_ci
704fb299fa2Sopenharmony_ci    auto devPath = GetBlockDeviceByMountPoint(partitionName);
705fb299fa2Sopenharmony_ci    LOG(INFO) << "UScriptInstructionShaCheck::dev path : " << devPath;
706fb299fa2Sopenharmony_ci    if (devPath.empty()) {
707fb299fa2Sopenharmony_ci        LOG(ERROR) << "cannot get block device of partition";
708fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE);
709fb299fa2Sopenharmony_ci        return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
710fb299fa2Sopenharmony_ci    }
711fb299fa2Sopenharmony_ci    ret = ExecReadShaInfo(env, devPath, shaInfo, partitionName);
712fb299fa2Sopenharmony_ci    return ReturnAndPushParam(ret, context);
713fb299fa2Sopenharmony_ci}
714fb299fa2Sopenharmony_ci}
715