• 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 "fs_manager/mount.h"
32 #include "include/updater/updater.h"
33 #include "log/log.h"
34 #include "misc_info/misc_info.h"
35 #include "package/pkg_manager.h"
36 #include "pkg_manager.h"
37 #include "pkg_utils.h"
38 #include "securec.h"
39 #include "ui/frame.h"
40 #include "ui/text_label.h"
41 #include "ui/updater_ui.h"
42 #include "updater/updater_const.h"
43 #include "utils.h"
44 
45 namespace updater {
46 using utils::String2Int;
47 using namespace hpackage;
48 using namespace updater::utils;
49 
50 extern TextLabel *g_logLabel;
51 extern TextLabel *g_logResultLabel;
52 
53 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     { nullptr, 0, nullptr, 0 },
60 };
61 
SetRetryCountToMisc(int retryCount,const std::vector<std::string> args)62 static void SetRetryCountToMisc(int retryCount, const std::vector<std::string> args)
63 {
64     struct UpdateMessage msg {};
65     char buffer[20];
66     UPDATER_ERROR_CHECK(!strncpy_s(msg.command, sizeof(msg.command), "boot_updater", strlen("boot_updater") + 1),
67         "SetRetryCountToMisc strncpy_s failed", return);
68     for (const auto& arg : args) {
69         if (arg.find("--retry_count") == std::string::npos) {
70             UPDATER_ERROR_CHECK(!strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1),
71                 "SetRetryCountToMisc strncat_s failed", return);
72             UPDATER_ERROR_CHECK(!strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1),
73                 "SetRetryCountToMisc strncat_s failed", return);
74         }
75     }
76     UPDATER_ERROR_CHECK(snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--retry_count=%d", retryCount) != -1,
77         "SetRetryCountToMisc snprintf_s failed", return);
78     UPDATER_ERROR_CHECK(!strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1),
79         "SetRetryCountToMisc strncat_s failed", return);
80     UPDATER_ERROR_CHECK_NOT_RETURN(WriteUpdaterMessage(MISC_FILE, msg) == true, "Write command to misc failed.");
81 }
82 
DoFactoryReset(FactoryResetMode mode,const std::string & path)83 static int DoFactoryReset(FactoryResetMode mode, const std::string &path)
84 {
85     if (mode == USER_WIPE_DATA) {
86         STAGE(UPDATE_STAGE_BEGIN) << "User FactoryReset";
87         LOG(INFO) << "Begin erasing /data";
88         if (FormatPartition(path) != 0) {
89             LOG(ERROR) << "User level FactoryReset failed";
90             STAGE(UPDATE_STAGE_FAIL) << "User FactoryReset";
91             ERROR_CODE(CODE_FACTORY_RESET_FAIL);
92             return 1;
93         }
94         LOG(INFO) << "User level FactoryReset success";
95         STAGE(UPDATE_STAGE_SUCCESS) << "User FactoryReset";
96     }
97     return 0;
98 }
99 
FactoryReset(FactoryResetMode mode,const std::string & path)100 int FactoryReset(FactoryResetMode mode, const std::string &path)
101 {
102     return DoFactoryReset(mode, path);
103 }
104 
UpdaterFromSdcard()105 UpdaterStatus UpdaterFromSdcard()
106 {
107 #ifndef UPDATER_UT
108     // sdcard fsType only support ext4/vfat
109     std::string sdcardStr = GetBlockDeviceByMountPoint(SDCARD_PATH);
110     if (!IsSDCardExist(sdcardStr)) {
111         if (errno == ENOENT) {
112             ShowText(g_logLabel, "Cannot detect SdCard!");
113         } else {
114             ShowText(g_logLabel, "Detecting SdCard abnormally!");
115         }
116         return UPDATE_ERROR;
117     }
118     if (MountForPath(SDCARD_PATH) != 0) {
119         int ret = mount(sdcardStr.c_str(), SDCARD_PATH.c_str(), "vfat", 0, NULL);
120         UPDATER_WARING_CHECK(ret == 0, "MountForPath /sdcard failed!", return UPDATE_ERROR);
121     }
122 #endif
123     UPDATER_ERROR_CHECK(access(SDCARD_CARD_PKG_PATH.c_str(), 0) == 0, "package is not exist",
124         ShowText(g_logLabel, "Package is not exist!");
125         return UPDATE_CORRUPT);
126     PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance();
127     UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return UPDATE_CORRUPT);
128 
129     STAGE(UPDATE_STAGE_BEGIN) << "UpdaterFromSdcard";
130     LOG(INFO) << "UpdaterFromSdcard start, sdcard updaterPath : " << SDCARD_CARD_PKG_PATH;
131 
132     g_logLabel->SetText("Don't remove SD Card!");
133     usleep(DISPLAY_TIME);
134     UpdaterStatus updateRet = DoInstallUpdaterPackage(pkgManager, SDCARD_CARD_PKG_PATH.c_str(), 0);
135     if (updateRet != UPDATE_SUCCESS) {
136         std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
137         g_logLabel->SetText("SD Card update failed!");
138         STAGE(UPDATE_STAGE_FAIL) << "UpdaterFromSdcard failed";
139     } else {
140         LOG(INFO) << "Update from SD Card successfully!";
141         STAGE(UPDATE_STAGE_SUCCESS) << "UpdaterFromSdcard success";
142     }
143     PkgManager::ReleasePackageInstance(pkgManager);
144     return updateRet;
145 }
146 
IsBatteryCapacitySufficient()147 bool IsBatteryCapacitySufficient()
148 {
149     return true;
150 }
151 
InstallUpdaterPackage(UpdaterParams & upParams,const std::vector<std::string> & args,PkgManager::PkgManagerPtr manager)152 static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, const std::vector<std::string> &args,
153     PkgManager::PkgManagerPtr manager)
154 {
155     UpdaterStatus status = UPDATE_UNKNOWN;
156     if (IsBatteryCapacitySufficient() == false) {
157         g_logLabel->SetText("Battery is low.\n");
158         LOG(ERROR) << "Battery is not sufficient for install package.";
159         status = UPDATE_SKIP;
160     } else {
161         STAGE(UPDATE_STAGE_BEGIN) << "Install package";
162         if (upParams.retryCount == 0) {
163             // First time enter updater, record retryCount in case of abnormal reset.
164             UPDATER_ERROR_CHECK(PartitionRecord::GetInstance().ClearRecordPartitionOffset() == true,
165                 "ClearRecordPartitionOffset failed", return UPDATE_ERROR);
166             SetRetryCountToMisc(upParams.retryCount + 1, args);
167         }
168         UPDATER_CHECK_ONLY_RETURN(SetupPartitions() == 0, ShowText(GetUpdateInfoLabel(), "Setup partitions failed");
169             return UPDATE_ERROR);
170         status = DoInstallUpdaterPackage(manager, upParams.updatePackage, upParams.retryCount);
171         if (status != UPDATE_SUCCESS) {
172             std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
173             std::string errMsg = ((status == UPDATE_SPACE_NOTENOUGH) ? "Free space is not enough" : "Update failed!");
174             g_logLabel->SetText(errMsg.c_str());
175             STAGE(UPDATE_STAGE_FAIL) << "Install failed";
176             if (status == UPDATE_RETRY && upParams.retryCount < MAX_RETRY_COUNT) {
177                 upParams.retryCount += 1;
178                 g_logLabel->SetText("Retry installation");
179                 SetRetryCountToMisc(upParams.retryCount, args);
180                 utils::DoReboot("updater");
181             }
182         } else {
183             LOG(INFO) << "Install package success.";
184             STAGE(UPDATE_STAGE_SUCCESS) << "Install package";
185         }
186     }
187     return status;
188 }
189 
StartUpdaterEntry(PkgManager::PkgManagerPtr manager,const std::vector<std::string> & args,UpdaterParams & upParams)190 static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager,
191     const std::vector<std::string> &args, UpdaterParams &upParams)
192 {
193     UpdaterStatus status = UPDATE_UNKNOWN;
194     if (upParams.updatePackage != "") {
195         ShowUpdateFrame(true);
196         status = InstallUpdaterPackage(upParams, args, manager);
197         UPDATER_CHECK_ONLY_RETURN(status == UPDATE_SUCCESS, return status);
198     } else if (upParams.factoryWipeData) {
199         LOG(INFO) << "Factory level FactoryReset begin";
200         status = UPDATE_SUCCESS;
201         SetUpdateFlag(1);
202         ShowUpdateFrame(true);
203         DoProgress();
204         UPDATER_ERROR_CHECK(FactoryReset(FACTORY_WIPE_DATA, "/data") == 0, "FactoryReset factory level failed",
205             status = UPDATE_ERROR);
206 
207         ShowUpdateFrame(false);
208         if (status != UPDATE_SUCCESS) {
209             g_logResultLabel->SetText("Factory reset failed");
210         } else {
211             g_logResultLabel->SetText("Factory reset done");
212         }
213     } else if (upParams.userWipeData) {
214         LOG(INFO) << "User level FactoryReset begin";
215         status = UPDATE_SUCCESS;
216         SetUpdateFlag(1);
217         ShowUpdateFrame(true);
218         DoProgress();
219         UPDATER_ERROR_CHECK(FactoryReset(USER_WIPE_DATA, "/data") == 0, "FactoryReset user level failed",
220             status = UPDATE_ERROR);
221         ShowUpdateFrame(false);
222         if (status != UPDATE_SUCCESS) {
223             g_logResultLabel->SetText("Wipe data failed");
224         } else {
225             g_logResultLabel->SetText("Wipe data finished");
226             PostUpdater(true);
227             std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
228         }
229     }
230     return status;
231 }
232 
StartUpdater(PkgManager::PkgManagerPtr manager,const std::vector<std::string> & args,char ** argv)233 static UpdaterStatus StartUpdater(PkgManager::PkgManagerPtr manager, const std::vector<std::string> &args,
234     char **argv)
235 {
236     UpdaterParams upParams {
237         false, false, 0, ""
238     };
239     std::vector<char *> extractedArgs;
240     int rc;
241     int optionIndex;
242 
243     for (const auto &arg : args) {
244         extractedArgs.push_back(const_cast<char *>(arg.c_str()));
245     }
246     extractedArgs.push_back(nullptr);
247     extractedArgs.insert(extractedArgs.begin(), argv[0]);
248     while ((rc = getopt_long(extractedArgs.size() - 1, extractedArgs.data(), "", OPTIONS, &optionIndex)) != -1) {
249         switch (rc) {
250             case 0: {
251                 std::string option = OPTIONS[optionIndex].name;
252                 if (option == "update_package") {
253                     upParams.updatePackage = optarg;
254                 } else if (option == "retry_count") {
255                     upParams.retryCount = atoi(optarg);
256                 } else if (option == "factory_wipe_data") {
257                     upParams.factoryWipeData = true;
258                 } else if (option == "user_wipe_data") {
259                     upParams.userWipeData = true;
260                 }
261                 break;
262             }
263             case '?':
264                 LOG(ERROR) << "Invalid argument.";
265                 break;
266             default:
267                 LOG(ERROR) << "Invalid argument.";
268                 break;
269         }
270     }
271     optind = 1;
272     // Sanity checks
273     UPDATER_WARING_CHECK((upParams.factoryWipeData && upParams.userWipeData) == false,
274         "Factory level reset and user level reset both set. use user level reset.", upParams.factoryWipeData = false);
275 
276     return StartUpdaterEntry(manager, args, upParams);
277 }
278 
UpdaterMain(int argc,char ** argv)279 int UpdaterMain(int argc, char **argv)
280 {
281     UpdaterStatus status = UPDATE_UNKNOWN;
282     PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
283     std::vector<std::string> args = ParseParams(argc, argv);
284 
285     LOG(INFO) << "Ready to start";
286 #ifndef UPDATER_UT
287     UpdaterUiInit();
288 #endif
289     status = StartUpdater(manager, args, argv);
290     std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
291 #ifndef UPDATER_UT
292     if (status != UPDATE_SUCCESS && status != UPDATE_SKIP) {
293         ShowUpdateFrame(false);
294         // Wait for user input
295         while (true) {
296             pause();
297         }
298         return 0;
299     }
300 #endif
301     PostUpdater(true);
302     utils::DoReboot("");
303     return 0;
304 }
305 } // updater
306