• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "daemon_updater.h"
16 #include "daemon_common.h"
17 #include "flashd/flashd.h"
18 #include "flash_utils.h"
19 #include "flash_define.h"
20 
21 namespace Hdc {
DaemonUpdater(HTaskInfo hTaskInfo)22 DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo)
23 {
24     commandBegin = CMD_UPDATER_BEGIN;
25     commandData = CMD_UPDATER_DATA;
26 }
27 
~DaemonUpdater()28 DaemonUpdater::~DaemonUpdater()
29 {
30     WRITE_LOG(LOG_DEBUG, "~DaemonUpdater refCount %d", refCount);
31 }
32 
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)33 bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
34 {
35 #ifndef UPDATER_UT
36     if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) {
37         return false;
38     }
39 #endif
40     if (flashHandle_ == nullptr) {
41         int ret = flashd::CreateFlashInstance(&flashHandle_, errorMsg_,
42             [&](uint32_t type, size_t dataLen, const void *context) {
43                 SendProgress(dataLen);
44             });
45         FLASHDAEMON_CHECK(ret == 0, AsyncUpdateFinish(command, -1, errorMsg_);
46             return false, "Faild to create flashd");
47     }
48     switch (command) {
49         case CMD_UPDATER_DATA: {
50             const uint8_t payloadPrefixReserve = 64;
51             string serialStrring((char *)payload, payloadPrefixReserve);
52             TransferPayload pld {};
53             SerialStruct::ParseFromString(pld, serialStrring);
54 #ifdef UPDATER_UT
55             pld.uncompressSize = pld.compressSize;
56 #endif
57             SendProgress(pld.uncompressSize);
58             break;
59         }
60         case CMD_UPDATER_CHECK: {
61             ProcessUpdateCheck(payload, payloadSize);
62             break;
63         }
64         case CMD_UPDATER_ERASE: {
65             std::string param(reinterpret_cast<char *>(payload), payloadSize);
66             RunUpdateShell(flashd::UPDATEMOD_ERASE, param, "");
67             TaskFinish();
68             break;
69         }
70         case CMD_UPDATER_FORMAT: {
71             std::string param(reinterpret_cast<char *>(payload), payloadSize);
72             RunUpdateShell(flashd::UPDATEMOD_FORMAT, param, "");
73             TaskFinish();
74             break;
75         }
76         default:
77             WRITE_LOG(LOG_FATAL, "CommandDispatch command %d", command);
78             return false;
79     }
80     return true;
81 };
82 
ProcessUpdateCheck(const uint8_t * payload,const int payloadSize)83 void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payloadSize)
84 {
85     uint64_t realSize = 0;
86     int ret = memcpy_s(&realSize, sizeof(realSize), payload, sizeof(realSize));
87     FLASHDAEMON_CHECK(ret == 0, return, "Faild to memcpy");
88     string bufString((char *)payload + sizeof(realSize), payloadSize - sizeof(realSize));
89     SerialStruct::ParseFromString(ctxNow.transferConfig, bufString);
90     ctxNow.master = false;
91     ctxNow.fsOpenReq.data = &ctxNow;
92     ctxNow.transferBegin = Base::GetRuntimeMSec();
93     ctxNow.fileSize = ctxNow.transferConfig.fileSize;
94     percentage_ = -1;
95 
96     WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck local function %s size %llu realSize %llu",
97         ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize);
98     uint8_t type = flashd::UPDATEMOD_FLASH;
99     if (ctxNow.transferConfig.functionName == CMDSTR_UPDATE_SYSTEM) {
100         type = flashd::UPDATEMOD_UPDATE;
101         totalSize_ = static_cast<double>(ctxNow.fileSize);
102         if (!MatchPackageExtendName(ctxNow.transferConfig.optionalName, ".bin")) {
103             totalSize_ += static_cast<double>(realSize); // for decode from zip
104         }
105         totalSize_ += static_cast<double>(realSize); // for verify
106         totalSize_ += static_cast<double>(realSize); // for read to partition
107         totalSize_ += static_cast<double>(realSize); // for write partition
108     } else if (ctxNow.transferConfig.functionName == CMDSTR_FLASH_PARTITION) {
109         totalSize_ = static_cast<double>(ctxNow.fileSize);
110         type = flashd::UPDATEMOD_FLASH;
111     } else {
112         WRITE_LOG(LOG_FATAL, "ProcessUpdateCheck local function %s size %lu realSize %lu",
113             ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize);
114         AsyncUpdateFinish(type, -1, "Invalid command");
115         return;
116     }
117     ctxNow.localPath = ctxNow.transferConfig.optionalName;
118     ret = flashd::DoUpdaterPrepare(flashHandle_, type, ctxNow.transferConfig.options, ctxNow.localPath);
119     if (ret == 0) {
120         refCount++;
121         WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck localPath %s", ctxNow.localPath.c_str());
122 #ifndef UPDATER_UT
123         uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(),
124             UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen);
125 #endif
126     }
127     FLASHDAEMON_CHECK(ret == 0, AsyncUpdateFinish(type, ret, errorMsg_), "Faild to prepare for %d", type);
128 }
129 
RunUpdateShell(uint8_t type,const std::string & options,const std::string & package)130 void DaemonUpdater::RunUpdateShell(uint8_t type, const std::string &options, const std::string &package)
131 {
132     int ret = flashd::DoUpdaterFlash(flashHandle_, type, options, package);
133     AsyncUpdateFinish(type, ret, errorMsg_);
134 }
135 
SendProgress(size_t dataLen)136 void DaemonUpdater::SendProgress(size_t dataLen)
137 {
138     currSize_ += dataLen;
139     int32_t percentage = static_cast<int32_t>(currSize_ * (flashd::PERCENT_FINISH - 1) / totalSize_);
140     if (static_cast<uint32_t>(percentage) >= flashd::PERCENT_FINISH) {
141         WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage %d", currSize_, percentage);
142         return;
143     }
144     if (percentage_ < percentage) {
145         percentage_ = percentage;
146         WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage_ %d", currSize_, percentage_);
147         SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t));
148     }
149 }
150 
WhenTransferFinish(CtxFile * context)151 void DaemonUpdater::WhenTransferFinish(CtxFile *context)
152 {
153     uint64_t nMSec = Base::GetRuntimeMSec() - context->transferBegin;
154     double fRate = static_cast<double>(context->indexIO) / nMSec; // / /1000 * 1000 = 0
155     WRITE_LOG(LOG_DEBUG, "File for %s transfer finish Size:%lld time:%lldms rate:%.2lfkB/s",
156               ctxNow.transferConfig.functionName.c_str(), context->indexIO, nMSec, fRate);
157 
158     int ret = 0;
159     uint8_t type = flashd::UPDATEMOD_UPDATE;
160     if (ctxNow.transferConfig.functionName == CMDSTR_UPDATE_SYSTEM) {
161         type = flashd::UPDATEMOD_UPDATE;
162         ret = flashd::DoUpdaterFlash(flashHandle_, type, ctxNow.transferConfig.options, ctxNow.localPath);
163     } else if (ctxNow.transferConfig.functionName == CMDSTR_FLASH_PARTITION) {
164         type = flashd::UPDATEMOD_FLASH;
165     }
166     AsyncUpdateFinish(type, ret, errorMsg_);
167     TaskFinish();
168 }
169 
AsyncUpdateFinish(uint8_t type,int32_t retCode,const string & result)170 void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t retCode, const string &result)
171 {
172     WRITE_LOG(LOG_DEBUG, "AsyncUpdateFinish retCode %d result %s", retCode, result.c_str());
173     uint32_t percentage = (retCode != 0) ? flashd::PERCENT_CLEAR : flashd::PERCENT_FINISH;
174     SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t));
175     (void)flashd::DoUpdaterFinish(flashHandle_, type, ctxNow.localPath);
176 
177     string echo = result;
178     echo = Base::ReplaceAll(echo, "\n", " ");
179     vector<uint8_t> vecBuf;
180     vecBuf.push_back(type);
181     if (retCode != 0) {
182         vecBuf.push_back(MSG_FAIL);
183     } else {
184         vecBuf.push_back(MSG_OK);
185     }
186     vecBuf.insert(vecBuf.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size());
187     SendToAnother(CMD_UPDATER_FINISH, vecBuf.data(), vecBuf.size());
188 }
189 
190 #ifdef UPDATER_UT
DoTransferFinish()191 void DaemonUpdater::DoTransferFinish()
192 {
193     WhenTransferFinish(&ctxNow);
194 }
195 #endif
196 } // namespace Hdc