1 /*
2 * Copyright (c) 2022 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
17 #include "daemon_common.h"
18 #include "flashd_define.h"
19 #include "hdi/client/update_hdi_client.h"
20 #include "updater/updater.h"
21 #include "updater/updater_const.h"
22 using namespace std;
23 namespace Hdc {
24 namespace {
25 constexpr uint8_t PAYLOAD_FIX_RESERVER = 64;
26 }
27
28 std::atomic<bool> DaemonUpdater::isRunning_ = false;
29
DaemonUpdater(HTaskInfo hTaskInfo)30 DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo)
31 {
32 commandBegin = CMD_UPDATER_BEGIN;
33 commandData = CMD_UPDATER_DATA;
34 }
35
~DaemonUpdater()36 DaemonUpdater::~DaemonUpdater()
37 {
38 FLASHD_LOGI("~DaemonUpdater refCount %d", refCount);
39 }
40
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)41 bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
42 {
43 if (IsDeviceLocked()) {
44 std::string echo = "operation is not allowed";
45 vector<uint8_t> buffer;
46 buffer.push_back(command);
47 buffer.push_back(Hdc::MSG_FAIL);
48 buffer.insert(buffer.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size());
49 SendToAnother(Hdc::CMD_UPDATER_FINISH, buffer.data(), buffer.size());
50 FLASHD_LOGE("The devic is locked and operation is not allowed");
51 return false;
52 }
53
54 if (!isInit_) {
55 Init();
56 isInit_ = true;
57 }
58
59 auto iter = cmdFunc_.find(command);
60 if (iter == cmdFunc_.end()) {
61 FLASHD_LOGE("command is invalid, command = %d", command);
62 return false;
63 }
64 iter->second(payload, payloadSize);
65 return true;
66 }
67
SendToHost(Flashd::CmdType type,Flashd::UpdaterState state,const std::string & msg)68 bool DaemonUpdater::SendToHost(Flashd::CmdType type, Flashd::UpdaterState state, const std::string &msg)
69 {
70 if (!DaemonUpdater::isRunning_) {
71 FLASHD_LOGW("flasd is not runing");
72 return true;
73 }
74
75 if (state == Flashd::UpdaterState::DOING) {
76 uint32_t temp = 0;
77 std::stringstream percentageStream(msg);
78 if (!(percentageStream >> temp)) {
79 temp = 0;
80 }
81 uint8_t percentage = static_cast<uint8_t>(temp);
82 SendToAnother(Hdc::CMD_UPDATER_PROGRESS, &percentage, sizeof(percentage));
83 return true;
84 }
85
86 if (state == Flashd::UpdaterState::FAIL || state == Flashd::UpdaterState::SUCCESS) {
87 uint8_t percentage = (state == Flashd::UpdaterState::SUCCESS) ? Flashd::PERCENT_FINISH : Flashd::PERCENT_CLEAR;
88 SendToAnother(Hdc::CMD_UPDATER_PROGRESS, &percentage, sizeof(percentage));
89
90 std::string echo = Hdc::Base::ReplaceAll(msg, "\n", " ");
91 vector<uint8_t> buffer;
92 buffer.push_back(static_cast<uint8_t>(type));
93 buffer.push_back((state == Flashd::UpdaterState::SUCCESS) ? Hdc::MSG_OK : Hdc::MSG_FAIL);
94 buffer.insert(buffer.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size());
95 SendToAnother(Hdc::CMD_UPDATER_FINISH, buffer.data(), buffer.size());
96 TaskFinish();
97 if (commander_ != nullptr) {
98 commander_->PostCommand();
99 }
100 DaemonUpdater::isRunning_ = false;
101 }
102 return true;
103 }
104
CreateCommander(const std::string & cmd)105 std::unique_ptr<Flashd::Commander> DaemonUpdater::CreateCommander(const std::string &cmd)
106 {
107 if (DaemonUpdater::isRunning_) {
108 FLASHD_LOGE("flashd has been running");
109 return nullptr;
110 }
111 DaemonUpdater::isRunning_ = true;
112 auto callback = [this](Flashd::CmdType type, Flashd::UpdaterState state, const std::string &msg) {
113 SendToHost(type, state, msg);
114 };
115 return Flashd::CommanderFactory::GetInstance().CreateCommander(cmd, callback);
116 }
117
CheckCommand(const uint8_t * payload,int payloadSize)118 void DaemonUpdater::CheckCommand(const uint8_t *payload, int payloadSize)
119 {
120 if (payloadSize < static_cast<int>(sizeof(int64_t))) {
121 FLASHD_LOGE("payloadSize is invalid");
122 return;
123 }
124
125 string bufString(reinterpret_cast<const char *>(payload + sizeof(int64_t)), payloadSize - sizeof(int64_t));
126 SerialStruct::ParseFromString(ctxNow.transferConfig, bufString);
127
128 ctxNow.master = false;
129 ctxNow.fsOpenReq.data = &ctxNow;
130 ctxNow.fileSize = ctxNow.transferConfig.fileSize;
131
132 FLASHD_LOGI("functionName = %s, options = %s, fileSize = %u", ctxNow.transferConfig.functionName.c_str(),
133 ctxNow.transferConfig.options.c_str(), ctxNow.transferConfig.fileSize);
134
135 commander_ = CreateCommander(ctxNow.transferConfig.functionName.c_str());
136 if (commander_ == nullptr) {
137 FLASHD_LOGE("commander_ is null for cmd = %s", ctxNow.transferConfig.functionName.c_str());
138 return;
139 }
140 commander_->DoCommand(ctxNow.transferConfig.options, ctxNow.transferConfig.fileSize);
141
142 SendToAnother(commandBegin, nullptr, 0);
143 refCount++;
144 }
145
DataCommand(const uint8_t * payload,int payloadSize) const146 void DaemonUpdater::DataCommand(const uint8_t *payload, int payloadSize) const
147 {
148 if (commander_ == nullptr) {
149 FLASHD_LOGE("commander_ is null");
150 return;
151 }
152
153 if (payloadSize <= PAYLOAD_FIX_RESERVER) {
154 FLASHD_LOGE("payloadSize is invaild");
155 return;
156 }
157
158 string serialStrring(reinterpret_cast<const char *>(payload), PAYLOAD_FIX_RESERVER);
159 TransferPayload pld = {};
160 SerialStruct::ParseFromString(pld, serialStrring);
161 commander_->DoCommand(payload + PAYLOAD_FIX_RESERVER, pld.uncompressSize);
162 }
163
EraseCommand(const uint8_t * payload,int payloadSize)164 void DaemonUpdater::EraseCommand(const uint8_t *payload, int payloadSize)
165 {
166 commander_ = CreateCommander(CMDSTR_ERASE_PARTITION);
167 if (commander_ == nullptr) {
168 FLASHD_LOGE("commander_ is null for cmd = %s", CMDSTR_ERASE_PARTITION);
169 return;
170 }
171 commander_->DoCommand(payload, payloadSize);
172 }
173
FormatCommand(const uint8_t * payload,int payloadSize)174 void DaemonUpdater::FormatCommand(const uint8_t *payload, int payloadSize)
175 {
176 commander_ = CreateCommander(CMDSTR_FORMAT_PARTITION);
177 if (commander_ == nullptr) {
178 FLASHD_LOGE("commander_ is null for cmd = %s", CMDSTR_FORMAT_PARTITION);
179 return;
180 }
181 commander_->DoCommand(payload, payloadSize);
182 }
183
Init()184 void DaemonUpdater::Init()
185 {
186 cmdFunc_.emplace(CMD_UPDATER_CHECK, bind(&DaemonUpdater::CheckCommand, this, placeholders::_1, placeholders::_2));
187 cmdFunc_.emplace(CMD_UPDATER_DATA, bind(&DaemonUpdater::DataCommand, this, placeholders::_1, placeholders::_2));
188 cmdFunc_.emplace(CMD_UPDATER_ERASE, bind(&DaemonUpdater::EraseCommand, this, placeholders::_1, placeholders::_2));
189 cmdFunc_.emplace(CMD_UPDATER_FORMAT, bind(&DaemonUpdater::FormatCommand, this, placeholders::_1, placeholders::_2));
190 }
191
IsDeviceLocked() const192 bool DaemonUpdater::IsDeviceLocked() const
193 {
194 bool isLocked = true;
195 if (auto ret = Updater::UpdateHdiClient::GetInstance().GetLockStatus(isLocked); ret != 0) {
196 FLASHD_LOGE("GetLockStatus fail, ret = %d", ret);
197 return true;
198 }
199 return isLocked;
200 }
201 } // namespace Hdc