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" 22using namespace std; 23namespace Hdc { 24namespace { 25constexpr uint8_t PAYLOAD_FIX_RESERVER = 64; 26} 27 28std::atomic<bool> DaemonUpdater::isRunning_ = false; 29 30DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) 31{ 32 commandBegin = CMD_UPDATER_BEGIN; 33 commandData = CMD_UPDATER_DATA; 34} 35 36DaemonUpdater::~DaemonUpdater() 37{ 38 FLASHD_LOGI("~DaemonUpdater refCount %d", refCount); 39} 40 41bool 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 68bool 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 105std::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 118void 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 146void 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 164void 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 174void 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 184void 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 192bool 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 202InvalidDaemon::InvalidDaemon(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) 203{ 204 FLASHD_LOGI("InvalidDaemon init"); 205} 206 207InvalidDaemon::~InvalidDaemon() 208{ 209 FLASHD_LOGI("~InvalidDaemon refCount %d", refCount); 210} 211 212bool InvalidDaemon::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) 213{ 214 std::string echo = "operation is not allowed"; 215 vector<uint8_t> buffer; 216 buffer.push_back(command); 217 buffer.push_back(Hdc::MSG_FAIL); 218 buffer.insert(buffer.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size()); 219 LogMsg(MSG_FAIL, "Operation is not allowed"); 220 TaskFinish(); 221 FLASHD_LOGE("The operation is not allowed"); 222 return false; 223} 224} // namespace Hdc