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 "updater_main.h"
16 #include <chrono>
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <getopt.h>
20 #include <libgen.h>
21 #include <string>
22 #include <sys/mount.h>
23 #include <sys/reboot.h>
24 #include <sys/stat.h>
25 #include <sys/statvfs.h>
26 #include <sys/syscall.h>
27 #include <thread>
28 #include <unistd.h>
29 #include <vector>
30 #include "applypatch/partition_record.h"
31 #include "cert_verify.h"
32 #include "flashd/flashd.h"
33 #include "fs_manager/mount.h"
34 #include "include/updater/updater.h"
35 #include "language/language_ui.h"
36 #include "log/dump.h"
37 #include "log/log.h"
38 #include "misc_info/misc_info.h"
39 #include "package/pkg_manager.h"
40 #include "pkg_manager.h"
41 #include "pkg_utils.h"
42 #include "securec.h"
43 #include "updater/updater_const.h"
44 #include "updater_ui_stub.h"
45 #include "utils.h"
46
47 namespace Updater {
48 using Utils::String2Int;
49 using namespace Hpackage;
50 using namespace Updater::Utils;
51 using namespace std::literals::chrono_literals;
52
53 [[maybe_unused]] constexpr int DISPLAY_TIME = 1000 * 1000;
54 constexpr struct option OPTIONS[] = {
55 { "update_package", required_argument, nullptr, 0 },
56 { "retry_count", required_argument, nullptr, 0 },
57 { "factory_wipe_data", no_argument, nullptr, 0 },
58 { "user_wipe_data", no_argument, nullptr, 0 },
59 { "upgraded_pkg_num", required_argument, nullptr, 0 },
60 { nullptr, 0, nullptr, 0 },
61 };
62 constexpr float VERIFY_PERCENT = 0.05;
63
SetMessageToMisc(const int message,const std::string headInfo)64 static void SetMessageToMisc(const int message, const std::string headInfo)
65 {
66 if (headInfo.empty()) {
67 return;
68 }
69 std::vector<std::string> args = ParseParams(0, nullptr);
70 struct UpdateMessage msg {};
71 if (strncpy_s(msg.command, sizeof(msg.command), "boot_updater", strlen("boot_updater") + 1) != EOK) {
72 LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
73 return;
74 }
75 for (const auto& arg : args) {
76 if (arg.find(headInfo) == std::string::npos) {
77 if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) {
78 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
79 return;
80 }
81 if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) {
82 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
83 return;
84 }
85 }
86 }
87 char buffer[128] {}; // 128 : set headInfo size
88 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d", headInfo.c_str(), message) == -1) {
89 LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
90 return;
91 }
92 if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) {
93 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
94 return;
95 }
96 if (WriteUpdaterMiscMsg(msg) != true) {
97 LOG(ERROR) << "Write command to misc failed.";
98 }
99 }
100
DoFactoryReset(FactoryResetMode mode,const std::string & path)101 static int DoFactoryReset(FactoryResetMode mode, const std::string &path)
102 {
103 if (mode == USER_WIPE_DATA) {
104 STAGE(UPDATE_STAGE_BEGIN) << "User FactoryReset";
105 LOG(INFO) << "Begin erasing /data";
106 if (FormatPartition(path, true) != 0) {
107 LOG(ERROR) << "User level FactoryReset failed";
108 STAGE(UPDATE_STAGE_FAIL) << "User FactoryReset";
109 ERROR_CODE(CODE_FACTORY_RESET_FAIL);
110 return 1;
111 }
112 LOG(INFO) << "User level FactoryReset success";
113 STAGE(UPDATE_STAGE_SUCCESS) << "User FactoryReset";
114 }
115 return 0;
116 }
117
FactoryReset(FactoryResetMode mode,const std::string & path)118 int FactoryReset(FactoryResetMode mode, const std::string &path)
119 {
120 return DoFactoryReset(mode, path);
121 }
122
OtaUpdatePreCheck(PkgManager::PkgManagerPtr pkgManager,const std::string & packagePath)123 static int OtaUpdatePreCheck(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath)
124 {
125 UPDATER_INIT_RECORD;
126 if (pkgManager == nullptr) {
127 LOG(ERROR) << "Fail to GetPackageInstance";
128 UPDATER_LAST_WORD(PKG_INVALID_FILE);
129 return UPDATE_CORRUPT;
130 }
131 char realPath[PATH_MAX + 1] = {0};
132 if (realpath(packagePath.c_str(), realPath) == nullptr) {
133 LOG(ERROR) << "realpath error";
134 UPDATER_LAST_WORD(PKG_INVALID_FILE);
135 return PKG_INVALID_FILE;
136 }
137 if (access(realPath, F_OK) != 0) {
138 LOG(ERROR) << "package does not exist!";
139 UPDATER_LAST_WORD(PKG_INVALID_FILE);
140 return PKG_INVALID_FILE;
141 }
142
143 int32_t ret = pkgManager->VerifyOtaPackage(packagePath);
144 if (ret != PKG_SUCCESS) {
145 LOG(INFO) << "VerifyOtaPackage fail ret :"<< ret;
146 UPDATER_LAST_WORD(ret);
147 return ret;
148 }
149
150 return PKG_SUCCESS;
151 }
152
VerifyPackages(const UpdaterParams & upParams)153 static UpdaterStatus VerifyPackages(const UpdaterParams &upParams)
154 {
155 LOG(INFO) << "Verify packages start...";
156 UPDATER_UI_INSTANCE.ShowProgressPage();
157 UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKG));
158
159 UPDATER_UI_INSTANCE.ShowProgress(0.0);
160 for (unsigned int i = upParams.pkgLocation; i < upParams.updatePackage.size(); i++) {
161 LOG(INFO) << "Verify package:" << upParams.updatePackage[i];
162 PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
163 int32_t verifyret = OtaUpdatePreCheck(manager, upParams.updatePackage[i]);
164 PkgManager::ReleasePackageInstance(manager);
165
166 if (verifyret != PKG_SUCCESS) {
167 UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
168 UPDATER_LAST_WORD(UPDATE_CORRUPT);
169 return UPDATE_CORRUPT;
170 }
171 }
172
173 ProgressSmoothHandler(0, static_cast<int>(VERIFY_PERCENT * FULL_PERCENT_PROGRESS));
174 LOG(INFO) << "Verify packages successfull...";
175 return UPDATE_SUCCESS;
176 }
177
UpdaterFromSdcard()178 UpdaterStatus UpdaterFromSdcard()
179 {
180 #ifndef UPDATER_UT
181 // sdcard fsType only support ext4/vfat
182 auto sdParam = "updater.data.configs";
183 Flashd::SetParameter(sdParam, "1");
184 std::string sdcardStr = GetBlockDeviceByMountPoint(SDCARD_PATH);
185 if (!IsSDCardExist(sdcardStr)) {
186 UPDATER_UI_INSTANCE.ShowLog(
187 (errno == ENOENT) ? TR(LOG_SDCARD_NOTFIND) : TR(LOG_SDCARD_ABNORMAL), true);
188 return UPDATE_ERROR;
189 }
190 if (MountForPath(SDCARD_PATH) != 0) {
191 int ret = mount(sdcardStr.c_str(), SDCARD_PATH, "vfat", 0, NULL);
192 if (ret != 0) {
193 LOG(WARNING) << "MountForPath /sdcard failed!";
194 return UPDATE_ERROR;
195 }
196 }
197 #endif
198 if (access(SDCARD_CARD_PKG_PATH, 0) != 0) {
199 LOG(ERROR) << "package is not exist";
200 UPDATER_UI_INSTANCE.ShowLog(TR(LOG_NOPKG), true);
201 return UPDATE_ERROR;
202 }
203
204 PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance();
205 if (pkgManager == nullptr) {
206 LOG(ERROR) << "pkgManager is nullptr";
207 return UPDATE_ERROR;
208 }
209 UpdaterParams upParams {
210 false, false, 0, 0, 1, 0, {SDCARD_CARD_PKG_PATH}
211 };
212 // verify packages first
213 if (VerifyPackages(upParams) != UPDATE_SUCCESS) {
214 PkgManager::ReleasePackageInstance(pkgManager);
215 return UPDATE_ERROR;
216 }
217 upParams.initialProgress += VERIFY_PERCENT;
218
219 STAGE(UPDATE_STAGE_BEGIN) << "UpdaterFromSdcard";
220 LOG(INFO) << "UpdaterFromSdcard start, sdcard updaterPath : " << upParams.updatePackage[upParams.pkgLocation];
221 UPDATER_UI_INSTANCE.ShowLog(TR(LOG_SDCARD_NOTMOVE));
222 UpdaterStatus updateRet = DoInstallUpdaterPackage(pkgManager, upParams, SDCARD_UPDATE);
223 if (updateRet != UPDATE_SUCCESS) {
224 UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
225 UPDATER_UI_INSTANCE.ShowLog(TR(LOG_SDCARD_FAIL));
226 STAGE(UPDATE_STAGE_FAIL) << "UpdaterFromSdcard failed";
227 } else {
228 LOG(INFO) << "Update from SD Card successfully!";
229 STAGE(UPDATE_STAGE_SUCCESS) << "UpdaterFromSdcard success";
230 }
231 PkgManager::ReleasePackageInstance(pkgManager);
232 return updateRet;
233 }
234
GetBatteryCapacity(int & capacity)235 bool GetBatteryCapacity(int &capacity)
236 {
237 const static std::vector<const char *> vec = {
238 "/sys/class/power_supply/battery/capacity",
239 "/sys/class/power_supply/Battery/capacity"
240 };
241 for (auto &it : vec) {
242 std::ifstream ifs { it };
243 if (!ifs.is_open()) {
244 continue;
245 }
246
247 int tmpCapacity = 0;
248 ifs >> tmpCapacity;
249 if ((ifs.fail()) || (ifs.bad())) {
250 continue;
251 }
252
253 capacity = tmpCapacity;
254 return true;
255 }
256
257 return false;
258 }
259
IsBatteryCapacitySufficient()260 bool IsBatteryCapacitySufficient()
261 {
262 static constexpr auto levelIdx = "lowBatteryLevel";
263 static constexpr auto jsonPath = "/etc/product_cfg.json";
264
265 int capacity = 0;
266 bool ret = GetBatteryCapacity(capacity);
267 if (!ret) {
268 return true; /* maybe no battery or err value return default true */
269 }
270
271 JsonNode node { Fs::path { jsonPath }};
272 auto item = node[levelIdx].As<int>();
273 if (!item.has_value()) {
274 return true; /* maybe no value return default true */
275 }
276
277 int lowLevel = *item;
278 if (lowLevel > 100 || lowLevel < 0) { /* full percent is 100 */
279 LOG(ERROR) << "load battery level error:" << lowLevel;
280 return false; /* config err not allow to update */
281 }
282
283 LOG(INFO) << "current capacity:" << capacity << ", low level:" << lowLevel;
284
285 return capacity > lowLevel;
286 }
287
InstallUpdaterPackage(UpdaterParams & upParams,PkgManager::PkgManagerPtr manager)288 static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, PkgManager::PkgManagerPtr manager)
289 {
290 UPDATER_INIT_RECORD;
291 UpdaterStatus status = UPDATE_UNKNOWN;
292 STAGE(UPDATE_STAGE_BEGIN) << "Install package";
293 if (upParams.retryCount == 0) {
294 // First time enter updater, record retryCount in case of abnormal reset.
295 if (!PartitionRecord::GetInstance().ClearRecordPartitionOffset()) {
296 LOG(ERROR) << "ClearRecordPartitionOffset failed";
297 return UPDATE_ERROR;
298 }
299 SetMessageToMisc(upParams.retryCount + 1, "retry_count");
300 }
301 status = DoInstallUpdaterPackage(manager, upParams, HOTA_UPDATE);
302 if (status != UPDATE_SUCCESS) {
303 UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
304 UPDATER_UI_INSTANCE.ShowLog(TR(LOG_UPDFAIL));
305 STAGE(UPDATE_STAGE_FAIL) << "Install failed";
306 if (status == UPDATE_RETRY && upParams.retryCount < MAX_RETRY_COUNT) {
307 upParams.retryCount += 1;
308 UPDATER_UI_INSTANCE.ShowFailedPage();
309 SetMessageToMisc(upParams.retryCount, "retry_count");
310 Utils::DoReboot("updater");
311 }
312 } else {
313 LOG(INFO) << "Install package success.";
314 STAGE(UPDATE_STAGE_SUCCESS) << "Install package";
315 }
316 return status;
317 }
318
CalcProgress(const UpdaterParams & upParams,std::vector<double> & pkgStartPosition,double & updateStartPosition)319 static UpdaterStatus CalcProgress(const UpdaterParams &upParams,
320 std::vector<double> &pkgStartPosition, double &updateStartPosition)
321 {
322 int64_t allPkgSize = 0;
323 std::vector<int64_t> everyPkgSize;
324 for (const auto &path : upParams.updatePackage) {
325 char realPath[PATH_MAX + 1] = {0};
326 if (realpath(path.c_str(), realPath) == nullptr) {
327 LOG(ERROR) << "Can not find updatePackage : " << path;
328 return UPDATE_ERROR;
329 }
330 struct stat st {};
331 if (stat(realPath, &st) == 0) {
332 everyPkgSize.push_back(st.st_size);
333 allPkgSize += st.st_size;
334 LOG(INFO) << "pkg " << path << " size is:" << st.st_size;
335 }
336 }
337 pkgStartPosition.push_back(VERIFY_PERCENT);
338 if (allPkgSize == 0) {
339 LOG(ERROR) << "All packages's size is 0.";
340 return UPDATE_ERROR;
341 }
342 int64_t startSize = 0;
343 for (auto size : everyPkgSize) {
344 startSize += size;
345 float percent = static_cast<double>(startSize) / static_cast<double>(allPkgSize) + VERIFY_PERCENT;
346 percent = (percent > 1.0) ? 1.0 : percent; // 1.0 : 100%
347 LOG(INFO) << "percent is:" << percent;
348 pkgStartPosition.push_back(percent);
349 }
350
351 updateStartPosition = pkgStartPosition[upParams.pkgLocation];
352 return UPDATE_SUCCESS;
353 }
354
PreUpdatePackages(UpdaterParams & upParams)355 static UpdaterStatus PreUpdatePackages(UpdaterParams &upParams)
356 {
357 LOG(INFO) << "start to update packages, start index:" << upParams.pkgLocation;
358 for (unsigned int i = 0; i < upParams.updatePackage.size(); i++) {
359 LOG(INFO) << "package " << i << ":" << upParams.updatePackage[i] <<
360 " precent:" << upParams.currentPercentage;
361 }
362
363 UpdaterStatus status = UPDATE_UNKNOWN;
364 if (SetupPartitions() != 0) {
365 UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
366 return UPDATE_ERROR;
367 }
368 const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
369 if (access(resultPath.c_str(), F_OK) != -1) {
370 (void)DeleteFile(resultPath);
371 }
372
373 // verify packages first
374 if (VerifyPackages(upParams) != UPDATE_SUCCESS) {
375 return UPDATE_ERROR;
376 }
377
378 // Only handle UPATE_ERROR and UPDATE_SUCCESS here.Let package verify handle others.
379 if (IsSpaceCapacitySufficient(upParams.updatePackage) == UPDATE_ERROR) {
380 return status;
381 }
382 if (upParams.retryCount == 0 && !IsBatteryCapacitySufficient()) {
383 UPDATER_UI_INSTANCE.ShowUpdInfo(TR(LOG_LOWPOWER));
384 UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
385 UPDATER_LAST_WORD(UPDATE_ERROR);
386 LOG(ERROR) << "Battery is not sufficient for install package.";
387 return UPDATE_SKIP;
388 }
389 return UPDATE_SUCCESS;
390 }
391
DoUpdatePackages(UpdaterParams & upParams)392 static UpdaterStatus DoUpdatePackages(UpdaterParams &upParams)
393 {
394 UpdaterStatus status = UPDATE_UNKNOWN;
395 std::vector<double> pkgStartPosition {};
396 double updateStartPosition;
397 status = CalcProgress(upParams, pkgStartPosition, updateStartPosition);
398 if (status != UPDATE_SUCCESS) {
399 return status;
400 }
401 UPDATER_UI_INSTANCE.ShowProgress(updateStartPosition * FULL_PERCENT_PROGRESS);
402 for (; upParams.pkgLocation < upParams.updatePackage.size(); upParams.pkgLocation++) {
403 PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
404 upParams.currentPercentage = pkgStartPosition[upParams.pkgLocation + 1] -
405 pkgStartPosition[upParams.pkgLocation];
406 upParams.initialProgress = pkgStartPosition[upParams.pkgLocation];
407 LOG(INFO) << "InstallUpdaterPackage pkg is " << upParams.updatePackage[upParams.pkgLocation] <<
408 " percent:" << upParams.initialProgress << "~" << pkgStartPosition[upParams.pkgLocation + 1];
409
410 status = InstallUpdaterPackage(upParams, manager);
411 SetMessageToMisc(upParams.pkgLocation + 1, "upgraded_pkg_num");
412 ProgressSmoothHandler(
413 static_cast<int>(upParams.initialProgress * FULL_PERCENT_PROGRESS +
414 upParams.currentPercentage * GetTmpProgressValue()),
415 static_cast<int>(pkgStartPosition[upParams.pkgLocation + 1] * FULL_PERCENT_PROGRESS));
416 if (status != UPDATE_SUCCESS) {
417 LOG(ERROR) << "InstallUpdaterPackage failed! Pkg is " << upParams.updatePackage[upParams.pkgLocation];
418 if (!CheckDumpResult()) {
419 UPDATER_LAST_WORD(status);
420 }
421 return status;
422 }
423 PkgManager::ReleasePackageInstance(manager);
424 }
425 UPDATER_UI_INSTANCE.ShowSuccessPage();
426 return status;
427 }
428
PostUpdatePackages(UpdaterParams & upParams,bool updateResult)429 static void PostUpdatePackages(UpdaterParams &upParams, bool updateResult)
430 {
431 std::string writeBuffer;
432 std::string buf;
433 if (!updateResult) {
434 const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
435 std::ifstream fin {resultPath};
436 if (!fin.is_open() || !std::getline(fin, buf)) {
437 LOG(ERROR) << "read result file error " << resultPath;
438 buf = "fail";
439 }
440 } else {
441 buf = "pass";
442 upParams.pkgLocation = upParams.pkgLocation == 0 ? upParams.pkgLocation : (upParams.pkgLocation - 1);
443 }
444
445 for (unsigned int i = 0; i < upParams.pkgLocation; i++) {
446 writeBuffer += upParams.updatePackage[i] + "|pass\n";
447 }
448 writeBuffer += upParams.updatePackage[upParams.pkgLocation] + "|" + buf + "\n";
449 for (unsigned int i = upParams.pkgLocation + 1; i < upParams.updatePackage.size(); i++) {
450 writeBuffer += upParams.updatePackage[i] + "\n";
451 }
452 if (writeBuffer != "") {
453 writeBuffer.pop_back();
454 }
455 LOG(INFO) << "post over, writeBuffer = " << writeBuffer;
456 WriteDumpResult(writeBuffer);
457 }
458
InstallUpdaterPackages(UpdaterParams & upParams)459 static UpdaterStatus InstallUpdaterPackages(UpdaterParams &upParams)
460 {
461 UpdaterStatus status = PreUpdatePackages(upParams);
462 if (status == UPDATE_SUCCESS) {
463 status = DoUpdatePackages(upParams);
464 }
465 PostUpdatePackages(upParams, status == UPDATE_SUCCESS);
466 return status;
467 }
468
StartUpdaterEntry(UpdaterParams & upParams)469 static UpdaterStatus StartUpdaterEntry(UpdaterParams &upParams)
470 {
471 UpdaterStatus status = UPDATE_UNKNOWN;
472 if (upParams.updatePackage.size() > 0) {
473 UPDATER_UI_INSTANCE.ShowProgressPage();
474 status = InstallUpdaterPackages(upParams);
475 } else if (upParams.factoryWipeData) {
476 UPDATER_UI_INSTANCE.ShowProgressPage();
477 LOG(INFO) << "Factory level FactoryReset begin";
478 status = UPDATE_SUCCESS;
479 #ifndef UPDATER_UT
480 DoProgress();
481 #endif
482 if (FactoryReset(FACTORY_WIPE_DATA, "/data") != 0) {
483 LOG(ERROR) << "FactoryReset factory level failed";
484 status = UPDATE_ERROR;
485 }
486 UPDATER_UI_INSTANCE.ShowLogRes(
487 (status != UPDATE_SUCCESS) ? TR(LOGRES_FACTORY_FAIL) : TR(LOGRES_FACTORY_DONE));
488 } else if (upParams.userWipeData) {
489 UPDATER_UI_INSTANCE.ShowProgressPage();
490 LOG(INFO) << "User level FactoryReset begin";
491 status = UPDATE_SUCCESS;
492 #ifndef UPDATER_UT
493 DoProgress();
494 #endif
495 if (FactoryReset(USER_WIPE_DATA, "/data") != 0) {
496 LOG(ERROR) << "FactoryReset user level failed";
497 status = UPDATE_ERROR;
498 }
499 if (status != UPDATE_SUCCESS) {
500 UPDATER_UI_INSTANCE.ShowLogRes(TR(LOGRES_WIPE_FAIL));
501 } else {
502 UPDATER_UI_INSTANCE.ShowSuccessPage();
503 UPDATER_UI_INSTANCE.ShowLogRes(TR(LOGRES_WIPE_FINISH));
504 PostUpdater(true);
505 std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
506 }
507 }
508 return status;
509 }
510
StartUpdater(const std::vector<std::string> & args,char ** argv,PackageUpdateMode & mode)511 static UpdaterStatus StartUpdater(const std::vector<std::string> &args,
512 char **argv, PackageUpdateMode &mode)
513 {
514 UpdaterParams upParams {
515 false, false, 0, 0, 0, 0
516 };
517 std::vector<char *> extractedArgs;
518 int rc;
519 int optionIndex;
520
521 for (const auto &arg : args) {
522 extractedArgs.push_back(const_cast<char *>(arg.c_str()));
523 }
524 extractedArgs.push_back(nullptr);
525 extractedArgs.insert(extractedArgs.begin(), argv[0]);
526 while ((rc = getopt_long(extractedArgs.size() - 1, extractedArgs.data(), "", OPTIONS, &optionIndex)) != -1) {
527 switch (rc) {
528 case 0: {
529 std::string option = OPTIONS[optionIndex].name;
530 if (option == "update_package") {
531 upParams.updatePackage.push_back(optarg);
532 (void)UPDATER_UI_INSTANCE.SetMode(UpdaterMode::OTA);
533 mode = HOTA_UPDATE;
534 } else if (option == "retry_count") {
535 upParams.retryCount = atoi(optarg);
536 (void)UPDATER_UI_INSTANCE.SetMode(UpdaterMode::OTA);
537 mode = HOTA_UPDATE;
538 } else if (option == "factory_wipe_data") {
539 (void)UPDATER_UI_INSTANCE.SetMode(UpdaterMode::REBOOTFACTORYRST);
540 upParams.factoryWipeData = true;
541 } else if (option == "user_wipe_data") {
542 (void)UPDATER_UI_INSTANCE.SetMode(UpdaterMode::REBOOTFACTORYRST);
543 upParams.userWipeData = true;
544 } else if (option == "upgraded_pkg_num") {
545 upParams.pkgLocation = static_cast<unsigned int>(atoi(optarg));
546 }
547 break;
548 }
549 case '?':
550 LOG(ERROR) << "Invalid argument.";
551 break;
552 default:
553 LOG(ERROR) << "Invalid argument.";
554 break;
555 }
556 }
557 optind = 1;
558 // Sanity checks
559 if (upParams.factoryWipeData && upParams.userWipeData) {
560 LOG(WARNING) << "Factory level reset and user level reset both set. use user level reset.";
561 upParams.factoryWipeData = false;
562 }
563 return StartUpdaterEntry(upParams);
564 }
565
UpdaterMain(int argc,char ** argv)566 int UpdaterMain(int argc, char **argv)
567 {
568 [[maybe_unused]] UpdaterStatus status = UPDATE_UNKNOWN;
569 UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_INIT_EVENT);
570 std::vector<std::string> args = ParseParams(argc, argv);
571
572 LOG(INFO) << "Ready to start";
573 #if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
574 UPDATER_UI_INSTANCE.InitEnv();
575 #endif
576 UpdaterInit::GetInstance().InvokeEvent(UPDATER_INIT_EVENT);
577 PackageUpdateMode mode = UNKNOWN_UPDATE;
578 status = StartUpdater(args, argv, mode);
579 #if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
580 UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
581 if (status != UPDATE_SUCCESS && status != UPDATE_SKIP) {
582 if (mode == HOTA_UPDATE) {
583 UPDATER_UI_INSTANCE.ShowFailedPage();
584 } else {
585 UPDATER_UI_INSTANCE.ShowMainpage();
586 UPDATER_UI_INSTANCE.Sleep(50); /* wait for page flush 50ms */
587 UPDATER_UI_INSTANCE.SaveScreen();
588 }
589 // Wait for user input
590 while (true) {
591 Utils::UsSleep(DISPLAY_TIME);
592 }
593 return 0;
594 }
595 #endif
596 PostUpdater(true);
597 Utils::DoReboot("");
598 return 0;
599 }
600 } // Updater
601