• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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