1 /*
2 * Copyright (c) 2021-2023 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 <chrono>
16 #include <regex>
17 #include <thread>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <sched.h>
21 #include <sys/mount.h>
22 #include <sys/stat.h>
23 #include <sys/statvfs.h>
24 #include <sys/syscall.h>
25
26 #include "applypatch/partition_record.h"
27 #include "flashd/flashd.h"
28 #include "log/log.h"
29 #include "misc_info/misc_info.h"
30 #include "package/pkg_manager.h"
31 #include "securec.h"
32 #include "updater/hardware_fault_retry.h"
33 #include "updater/updater.h"
34 #include "updater/updater_const.h"
35 #include "updater_main.h"
36 #include "utils.h"
37
38 namespace Updater {
39 using namespace Hpackage;
40 using namespace Updater::Utils;
41
DeleteInstallTimeFile()42 void DeleteInstallTimeFile()
43 {
44 const std::string installTimeFilePath = std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE);
45 if (access(installTimeFilePath.c_str(), F_OK) != -1) {
46 (void)DeleteFile(installTimeFilePath);
47 LOG(INFO) << "delete install time file";
48 }
49 }
50
IsDouble(const std::string & str)51 bool IsDouble(const std::string& str)
52 {
53 std::regex pattern("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
54 if (!std::regex_match(str, pattern)) {
55 LOG(ERROR) << "match double failed";
56 return false;
57 }
58 return true;
59 }
60
WriteInstallTime(UpdaterParams & upParams)61 void WriteInstallTime(UpdaterParams &upParams)
62 {
63 std::ofstream ofs;
64 ofs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::app | std::ios::out);
65 if (!ofs.is_open()) {
66 LOG(ERROR) << "open install time file fail";
67 return;
68 }
69 ofs << DurationToString(upParams.installTime, upParams.pkgLocation) << "\n";
70 }
71
ReadInstallTime(UpdaterParams & upParams)72 void ReadInstallTime(UpdaterParams &upParams)
73 {
74 std::ifstream ifs;
75 std::string buf;
76 ifs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::in);
77 if (!ifs.is_open()) {
78 LOG(ERROR) << "read install time file fail";
79 return;
80 }
81 unsigned int index = 0;
82 while (getline(ifs, buf)) {
83 if (index >= upParams.pkgLocation) {
84 break;
85 }
86 if (IsDouble(buf)) {
87 double timeDistance = 0;
88 if (!Utils::ConvertToDouble(buf, timeDistance)) {
89 LOG(ERROR) << "ConvertToDouble failed";
90 return;
91 }
92 upParams.installTime[index++] = std::chrono::duration<double>(timeDistance);
93 } else {
94 LOG(ERROR) << "read install time is invalid";
95 }
96 }
97 }
98
DeleteUpdaterPath(const std::string & path)99 bool DeleteUpdaterPath(const std::string &path)
100 {
101 auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
102 if (pDir == nullptr) {
103 LOG(INFO) << "Can not open dir";
104 return true;
105 }
106 bool sdcardTmp = false;
107 if (path.find("sdcard") != std::string::npos) {
108 sdcardTmp = true;
109 }
110 struct dirent *dp = nullptr;
111 while ((dp = readdir(pDir.get())) != nullptr) {
112 std::string currentName(dp->d_name);
113 if (currentName[0] == '.' || (currentName.compare("log") == 0) ||
114 (currentName.compare(UPDATER_RESULT_FILE) == 0) ||
115 (currentName.compare(UPDATER_LOCALE_FILE) == 0) ||
116 (currentName.compare(MODULE_UPDATE_RESULT_FILE) == 0) ||
117 (currentName.compare(UPLOAD_LOG_TIME_FILE) == 0) ||
118 (currentName.compare(INSTALL_TIME_FILE) == 0) ||
119 (currentName.compare(ROLLBACK_FILE) == 0)) {
120 continue;
121 }
122 if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) {
123 continue;
124 }
125 std::string tmpName(path);
126 tmpName.append("/" + currentName);
127 if (IsDirExist(tmpName)) {
128 DeleteUpdaterPath(tmpName);
129 }
130 #ifndef UPDATER_UT
131 remove(tmpName.c_str());
132 #endif
133 }
134 return true;
135 }
136
ClearMisc()137 bool ClearMisc()
138 {
139 struct UpdateMessage cleanBoot {};
140 if (!WriteUpdaterMiscMsg(cleanBoot)) {
141 LOG(ERROR) << "ClearMisc clear boot message to misc failed";
142 return false;
143 }
144 auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
145 if (miscBlockDev.empty()) {
146 LOG(INFO) << "cannot get block device of partition";
147 miscBlockDev = MISC_FILE;
148 }
149 LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
150 auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
151 if (fp == nullptr) {
152 LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
153 return false;
154 }
155 if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
156 LOG(ERROR) << "ClearMisc fseek failed";
157 return false;
158 }
159 off_t clearOffset = 0;
160 if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
161 LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
162 return false;
163 }
164
165 struct PartitionRecordInfo cleanPartition {};
166 for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
167 sizeof(PartitionRecordInfo)) {
168 if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
169 LOG(ERROR) << "ClearMisc fseek failed";
170 return false;
171 }
172 if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
173 LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
174 return false;
175 }
176 }
177 return true;
178 }
179
IsSDCardExist(const std::string & sdcardPath)180 bool IsSDCardExist(const std::string &sdcardPath)
181 {
182 // Record system error codes.
183 int save_errno = errno;
184 struct stat st {};
185 if (stat(sdcardPath.c_str(), &st) < 0) {
186 return false;
187 } else {
188 errno = save_errno;
189 return true;
190 }
191 }
192
IsMountDataAndSaveLogs(void)193 bool IsMountDataAndSaveLogs(void)
194 {
195 bool isSdCardMode = CheckUpdateMode(SDCARD_MODE);
196 bool isUsbMode = CheckUpdateMode(USB_MODE);
197 bool isSdCardIntralMode = CheckUpdateMode(SDCARD_INTRAL_MODE);
198 bool isLogMounted = GetMountStatusForMountPoint("/log") == MountStatus::MOUNT_MOUNTED;
199 bool isDataAlreadyMounted = GetMountStatusForMountPoint("/data") == MountStatus::MOUNT_MOUNTED;
200 return (!(isSdCardMode || isUsbMode) && (isDataAlreadyMounted || !isLogMounted)) || isSdCardIntralMode;
201 }
202
DeleteUpdaterTmpFiles()203 static void DeleteUpdaterTmpFiles()
204 {
205 if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) {
206 LOG(ERROR) << "DeleteUpdaterPath failed";
207 }
208 if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) {
209 LOG(ERROR) << "Delete sdcard path failed";
210 }
211 if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) {
212 LOG(ERROR) << "DeleteUpdaterPath failed";
213 }
214 }
215
PostUpdater(bool clearMisc)216 void PostUpdater(bool clearMisc)
217 {
218 STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
219 bool isMountDataAndSaveLogs = IsMountDataAndSaveLogs();
220 (void)SetupPartitions(isMountDataAndSaveLogs);
221 UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
222 // clear update misc partition.
223 if (clearMisc && !ClearMisc()) {
224 LOG(ERROR) << "PostUpdater clear misc failed";
225 }
226 if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) {
227 LOG(ERROR) << "Delete command failed";
228 }
229 if (!HardwareFaultRetry::GetInstance().IsRetry()) {
230 DeleteUpdaterTmpFiles();
231 }
232 if (isMountDataAndSaveLogs) {
233 SaveLogs();
234 }
235 }
236
InitMode(void) const237 void BootMode::InitMode(void) const
238 {
239 InitLogger(modeName);
240 #ifdef UPDATER_BUILD_VARIANT_USER
241 SetLogLevel(INFO);
242 #else
243 SetLogLevel(DEBUG);
244 #endif
245 LoadFstab();
246 STAGE(UPDATE_STAGE_OUT) << "Start " << modeName;
247 SetParameter(modePara.c_str(), "1");
248 }
249
IsUpdater(const UpdateMessage & boot)250 bool IsUpdater(const UpdateMessage &boot)
251 {
252 return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0;
253 }
254
IsFlashd(const UpdateMessage & boot)255 bool IsFlashd(const UpdateMessage &boot)
256 {
257 return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0;
258 }
259
GetBootModes(void)260 std::vector<BootMode> &GetBootModes(void)
261 {
262 static std::vector<BootMode> bootModes {};
263 return bootModes;
264 }
265
RegisterMode(const BootMode & mode)266 void RegisterMode(const BootMode &mode)
267 {
268 GetBootModes().push_back(mode);
269 }
270
SelectMode(const UpdateMessage & boot)271 std::optional<BootMode> SelectMode(const UpdateMessage &boot)
272 {
273 const auto &modes = GetBootModes();
274
275 // select modes by bootMode.cond which would check misc message
276 auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) {
277 if (bootMode.cond != nullptr && bootMode.cond(boot)) {
278 LOG(INFO) << "condition for mode " << bootMode.modeName << " is satisfied";
279 return true;
280 }
281 LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied";
282 return false;
283 });
284 // misc check failed for each mode, then enter updater mode
285 if (it == modes.end() || it->entryFunc == nullptr) {
286 LOG(WARNING) << "find valid mode failed, enter updater Mode";
287 return std::nullopt;
288 }
289
290 LOG(INFO) << "enter " << it->modeName << " mode";
291 return *it;
292 }
293
SetCpuAffinityByPid(const UpdaterParams & upParams,unsigned int reservedCores)294 bool SetCpuAffinityByPid(const UpdaterParams &upParams, unsigned int reservedCores)
295 {
296 static std::mutex setAffinityLock;
297 std::lock_guard<std::mutex> lock(setAffinityLock);
298 std::vector<std::string> binaryTids = upParams.binaryTids;
299 if (upParams.binaryPid == -1 || std::find(
300 binaryTids.begin(), binaryTids.end(), std::to_string(upParams.binaryPid)) == binaryTids.end()) {
301 LOG(WARNING) << "invalid binaryPid:" << upParams.binaryPid;
302 return false;
303 }
304 unsigned int coreCount = std::thread::hardware_concurrency();
305 LOG(INFO) << "coreCount:" << coreCount << ", reservedCores:" << reservedCores;
306 if (coreCount <= reservedCores) {
307 LOG(WARNING) << "coreCount:" << coreCount << " <= " << reservedCores;
308 return false;
309 }
310 cpu_set_t mask;
311 CPU_ZERO(&mask);
312 for (unsigned int i = 0; i < coreCount - reservedCores; i++) {
313 CPU_SET(i, &mask);
314 }
315 int syscallRes;
316 for (auto &str : binaryTids) {
317 int32_t temp = -1;
318 if (!Utils::ConvertToLong(str, temp)) {
319 LOG(ERROR) << "ConvertToLong failed:" << str;
320 continue;
321 }
322 pid_t tid = static_cast<pid_t>(temp);
323 syscallRes = syscall(__NR_sched_setaffinity, tid, sizeof(mask), &mask);
324 LOG(INFO) << "setaffinity tid:" << tid;
325 if (syscallRes != 0) {
326 LOG(ERROR) << "set affinity faild:" << syscallRes;
327 }
328 }
329 return true;
330 }
331
UpdateBinaryTids(const std::vector<std::string> & output,UpdaterParams & upParams)332 void UpdateBinaryTids(const std::vector<std::string> &output, UpdaterParams &upParams)
333 {
334 if (output.size() < DEFAULT_PROCESS_NUM) {
335 LOG(ERROR) << "check output fail";
336 return;
337 }
338 auto outputInfo = Trim(output[1]);
339 LOG(INFO) << "binary tids:" << outputInfo;
340 upParams.binaryTids = SplitString(outputInfo, ",");
341 if (upParams.isLoadReduction) {
342 unsigned int coreCount = std::thread::hardware_concurrency();
343 unsigned int reservedCores = coreCount - LITTLE_CPU_CORES;
344 SetCpuAffinityByPid(upParams, reservedCores);
345 }
346 }
347 } // namespace Updater
348