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