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