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