* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "updater_main.h"
#include <chrono>
#include <dirent.h>
#include <fcntl.h>
#include <getopt.h>
#include <libgen.h>
#include <string>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/syscall.h>
#include <thread>
#include <unistd.h>
#include <vector>
#include "applypatch/partition_record.h"
#include "cert_verify.h"
#include "flashd/flashd.h"
#include "fs_manager/mount.h"
#include "include/updater/updater.h"
#include "json_node.h"
#include "language/language_ui.h"
#include "log/dump.h"
#include "log/log.h"
#include "misc_info/misc_info.h"
#include "package/pkg_manager.h"
#include "pkg_manager.h"
#include "pkg_utils.h"
#include "ptable_parse/ptable_process.h"
#include "sdcard_update/sdcard_update.h"
#include "scope_guard.h"
#include "securec.h"
#include "trace/io_collect.h"
#include "updater/updater_const.h"
#include "updater/hardware_fault_retry.h"
#include "updater/updater_preprocess.h"
#include "updater_ui_stub.h"
#include "utils.h"
#include "factory_reset/factory_reset.h"
#include "write_state/write_state.h"
#include "slot_info/slot_info.h"
#include "factory_reset/secure_erase.h"
namespace Updater {
using Utils::String2Int;
using namespace Hpackage;
using namespace Updater::Utils;
using namespace std::literals::chrono_literals;
[[maybe_unused]] constexpr int DISPLAY_TIME = 1000 * 1000;
constexpr struct option OPTIONS[] = {
{ "update_bin", required_argument, nullptr, 0 },
{ "update_package", required_argument, nullptr, 0 },
{ "retry_count", required_argument, nullptr, 0 },
{ "panic_count", required_argument, nullptr, 0 },
{ "factory_wipe_data", no_argument, nullptr, 0 },
{ "user_wipe_data", no_argument, nullptr, 0 },
{ "menu_wipe_data", no_argument, nullptr, 0 },
{ "sdcard_update", no_argument, nullptr, 0 },
{ "upgraded_pkg_num", required_argument, nullptr, 0 },
{ "force_update_action", required_argument, nullptr, 0 },
{ "night_update", no_argument, nullptr, 0 },
{ USB_MODE, no_argument, nullptr, 0 },
{ "UPDATE:MAINIMG", no_argument, nullptr, 0 },
{ "update_protect", no_argument, nullptr, 0 },
{ "factory_sd_update", no_argument, nullptr, 0 },
{ "UPDATE:SD", no_argument, nullptr, 0 },
{ "UPDATE:SDFROMDEV", no_argument, nullptr, 0 },
{ "sdcard_intral_update", optional_argument, nullptr, 0},
{ "shrink_info", required_argument, nullptr, 0 },
{ "virtual_shrink_info", required_argument, nullptr, 0 },
{"wipe_data_factory_lowlevel", no_argument, nullptr, 0},
{ "wipe_data_at_factoryreset_0", no_argument, nullptr, 0 },
{ "subpkg_update", no_argument, nullptr, 0 },
{ "secure_erase", optional_argument, nullptr, 0 },
{ "disk_erase", optional_argument, nullptr, 0 },
{ nullptr, 0, nullptr, 0 },
};
constexpr float VERIFY_PERCENT = 0.05;
constexpr double FULL_PERCENT = 100.00;
constexpr uint32_t BYTE_SHIFT_8 = 8;
constexpr uint32_t BYTE_SHIFT_16 = 16;
constexpr uint32_t BYTE_SHIFT_24 = 24;
constexpr uint32_t SECOND_BUFFER = 2;
constexpr uint32_t THIRD_BUFFER = 3;
constexpr uint8_t TYPE_ZIP_HEADER = 0xaa;
bool ReadLE16(std::istream& is, uint16_t& value)
{
char buf[2] = {0};
if (!is.read(buf, sizeof(buf))) {
return false;
}
value = static_cast<uint16_t>(static_cast<unsigned char>(buf[0])) |
(static_cast<uint16_t>(static_cast<unsigned char>(buf[1])) << BYTE_SHIFT_8);
return true;
}
bool ReadLE32(std::istream& is, uint32_t& value)
{
char buf[4] = {0};
if (!is.read(buf, sizeof(buf))) {
return false;
}
value = static_cast<uint32_t>(static_cast<unsigned char>(buf[0])) |
(static_cast<uint32_t>(static_cast<unsigned char>(buf[1])) << BYTE_SHIFT_8) |
(static_cast<uint32_t>(static_cast<unsigned char>(buf[SECOND_BUFFER])) << BYTE_SHIFT_16) |
(static_cast<uint32_t>(static_cast<unsigned char>(buf[THIRD_BUFFER])) << BYTE_SHIFT_24);
return true;
}
int FactoryReset(FactoryResetMode mode, const std::string &path)
{
UpdaterInit::GetInstance().InvokeEvent(FACTORY_RESET_INIT_EVENT);
auto ret = FactoryResetProcess::GetInstance().DoFactoryReset(mode, path);
if (ret == 0) {
LOG(INFO) << "restorecon for " << path;
RestoreconPath(path);
}
return ret;
}
static UpdaterStatus ReadUpdateStreamzip(const std::string &packagePath)
{
std::filesystem::path packageFsPath(packagePath);
std::filesystem::path outputPath = packageFsPath.parent_path() / "update_stream.zip";
std::string outputPathStr = outputPath.string();
LOG(INFO) << "outputPathStr:" << outputPathStr;
std::ifstream inFile(packagePath, std::ios::binary);
if (!inFile) {
LOG(ERROR) << "Error: Failed to open " << packagePath;
return UPDATE_ERROR;
}
uint16_t type;
if (!ReadLE16(inFile, type)) {
LOG(ERROR) << "Failed to read type";
return UPDATE_ERROR;
}
if (type != TYPE_ZIP_HEADER) {
LOG(ERROR) << "Invalid type, expected 0xaa but got " << type;
return UPDATE_ERROR;
}
uint32_t length;
if (!ReadLE32(inFile, length)) {
LOG(ERROR) << "Failed to read length";
return UPDATE_ERROR;
}
LOG(INFO) << "header.length = " << length;
std::vector<char> valueData(length);
if (!inFile.read(valueData.data(), length)) {
LOG(ERROR) << "Incomplete value data";
return UPDATE_ERROR;
}
std::ofstream outFile(outputPathStr, std::ios::binary);
if (!outFile.write(valueData.data(), length)) {
LOG(ERROR) << "Write failed";
return UPDATE_ERROR;
}
LOG(INFO) << "Successfully restored build_tools.zip to " << outputPathStr;
return UPDATE_SUCCESS;
}
const char* GetFileType(const char* path, struct stat* st)
{
if (lstat(path, st) != 0) {
return "Unknown";
}
switch (st->st_mode & S_IFMT) {
case S_IFREG: return "File";
case S_IFDIR: return "Directory";
case S_IFLNK: return "Symlink";
case S_IFIFO: return "FIFO";
case S_IFSOCK: return "Socket";
case S_IFCHR: return "CharDevice";
case S_IFBLK: return "BlockDevice";
default: return "Unknown";
}
}
static UpdaterStatus GetReadUpdateStreamzipFromBinfile(const std::string &packagePath)
{
UPDATER_INIT_RECORD;
int32_t status = ReadUpdateStreamzip(packagePath);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "ReadUpdateStreamzip failed";
return UPDATE_ERROR;
}
return UPDATE_SUCCESS;
}
int OtaUpdatePreCheck(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath)
{
UPDATER_INIT_RECORD;
if (pkgManager == nullptr) {
LOG(ERROR) << "pkgManager is nullptr";
UPDATER_LAST_WORD(PKG_INVALID_FILE, "pkgManager is nullptr");
return UPDATE_CORRUPT;
}
char realPath[PATH_MAX + 1] = {0};
if (realpath(packagePath.c_str(), realPath) == nullptr) {
LOG(ERROR) << "realpath error";
UPDATER_LAST_WORD(PKG_INVALID_FILE, "realpath error");
return PKG_INVALID_FILE;
}
if (access(realPath, F_OK) != 0) {
LOG(ERROR) << "package does not exist!";
UPDATER_LAST_WORD(PKG_INVALID_FILE, "package does not exist!");
return PKG_INVALID_FILE;
}
int32_t ret = pkgManager->VerifyOtaPackage(realPath);
if (ret != PKG_SUCCESS) {
LOG(INFO) << "VerifyOtaPackage fail ret :" << ret;
UPDATER_LAST_WORD("sign", ret);
return ret;
}
return UPDATE_SUCCESS;
}
static UpdaterStatus UpdatePreCheck(UpdaterParams &upParams, const std::string pkgPath)
{
UPDATER_INIT_RECORD;
int32_t ret = PreProcess::GetInstance().DoUpdateAuth(pkgPath);
if (ret != 0) {
return UPDATE_ERROR;
}
PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
if (pkgManager == nullptr) {
LOG(ERROR) << "CreatePackageInstance fail";
return UPDATE_ERROR;
}
if (GetUpdatePackageInfo(pkgManager, pkgPath) != PKG_SUCCESS) {
PkgManager::ReleasePackageInstance(pkgManager);
LOG(ERROR) << "Verify update bin file Fail!";
UPDATER_LAST_WORD(UPDATE_ERROR, "Verify update bin file Fail!");
return UPDATE_ERROR;
}
if (PreProcess::GetInstance().DoUpdatePreProcess(upParams, pkgManager) != PKG_SUCCESS) {
PkgManager::ReleasePackageInstance(pkgManager);
LOG(ERROR) << "Version Check Fail!";
UPDATER_LAST_WORD(UPDATE_ERROR, "Version Check Fail!");
return UPDATE_ERROR;
}
if (PreProcess::GetInstance().DoUpdateClear() != 0) {
LOG(ERROR) << "DoUpdateClear Fail!";
}
PkgManager::ReleasePackageInstance(pkgManager);
return UPDATE_SUCCESS;
}
__attribute__((weak)) int32_t VerifySpecialBin([[maybe_unused]]UpdaterParams &upParams)
{
return PKG_SUCCESS;
}
__attribute__((weak)) int32_t VerifySpecialPkgs([[maybe_unused]]UpdaterParams &upParams)
{
return PKG_SUCCESS;
}
__attribute__((weak)) void UpdaterVerifyFailEntry(bool verifyret)
{
LOG(INFO) << "pre verify package info process";
return;
}
__attribute__((weak)) UpdaterStatus NotifyActionResult(UpdaterParams &upParams,
UpdaterStatus &status, const std::vector<NotifyAction> ¬ifyActionVec)
{
return UPDATE_SUCCESS;
}
__attribute__((weak)) void NotifyReboot(const std::string& rebootTarget,
const std::string &rebootReason, const std::string &extData)
{
Updater::Utils::UpdaterDoReboot(rebootTarget, rebootReason, extData);
}
__attribute__((weak)) UpdaterStatus UpdateSubPkg(UpdaterParams &upParams)
{
return UPDATE_SUCCESS;
}
__attribute__((weak)) void NotifyPreCheck(UpdaterStatus &status, UpdaterParams &upParams)
{
return;
}
__attribute__((weak)) bool PreSdSpecialProcess(UpdaterParams &upParams)
{
LOG(INFO) << "start PreSdSpecialProcess";
if (SetUpdateSlotParam(upParams, true) != UPDATE_SUCCESS) {
LOG(ERROR) << "SetUpdateSlotParam failed";
return false;
}
return true;
}
__attribute__((weak)) void PostSdSpecialProcess([[maybe_unused]] UpdaterStatus &status)
{
return;
}
static UpdaterStatus VerifyBinfiles(UpdaterParams &upParams)
{
UPDATER_INIT_RECORD;
LOG(INFO) << "Verify binfiles start...";
UPDATER_UI_INSTANCE.ShowProgressPage();
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKG));
if (upParams.callbackProgress == nullptr) {
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
UPDATER_LAST_WORD(UPDATE_CORRUPT, "upParams.callbackProgress is null");
return UPDATE_CORRUPT;
}
upParams.callbackProgress(0.0);
upParams.installTime.resize(upParams.updateBin.size(), std::chrono::duration<double>(0));
ReadInstallTime(upParams);
for (unsigned int i = upParams.pkgLocation; i < upParams.updateBin.size(); i++) {
LOG(INFO) << "Verify package:" << upParams.updateBin[i];
auto startTime = std::chrono::system_clock::now();
PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
if (manager == nullptr) {
LOG(ERROR) << "CreatePackageInstance fail";
return UPDATE_ERROR;
}
int32_t status = GetReadUpdateStreamzipFromBinfile(upParams.updateBin[i]);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "GetReadUpdateStreamzipFromBinfile fail";
return UPDATE_ERROR;
}
int32_t verifyret = OtaUpdatePreCheck(manager, STREAM_ZIP_PATH);
PkgManager::ReleasePackageInstance(manager);
if (verifyret != UPDATE_SUCCESS) {
UpdaterVerifyFailEntry((verifyret == PKG_INVALID_DIGEST) && (upParams.updateMode == HOTA_UPDATE));
upParams.pkgLocation = i;
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
auto endTime = std::chrono::system_clock::now();
upParams.installTime[i] = endTime - startTime;
return UPDATE_CORRUPT;
}
auto endTime = std::chrono::system_clock::now();
upParams.installTime[i] = endTime - startTime;
}
if (VerifySpecialBin(upParams) != PKG_SUCCESS) {
UPDATER_LAST_WORD(UPDATE_CORRUPT, "VerifySpecialBin failed");
return UPDATE_CORRUPT;
}
ProgressSmoothHandler(UPDATER_UI_INSTANCE.GetCurrentPercent(),
UPDATER_UI_INSTANCE.GetCurrentPercent() + static_cast<int>(VERIFY_PERCENT * FULL_PERCENT_PROGRESS));
LOG(INFO) << "Verify binfiles successfull...";
return UPDATE_SUCCESS;
}
std::function<void(float, float, UpdaterParams, bool)> g_setPrgrsSmoothFunc = ProgressSmoothHandler;
void SetPrgrsSmoothHandlerFunc(std::function<void(float, float, UpdaterParams, bool)> func)
{
g_setPrgrsSmoothFunc = func;
}
void ProcessPrgrsSmooth(float beginProgress, float endProgress, UpdaterParams upParams, bool isFinish)
{
if (g_setPrgrsSmoothFunc == nullptr) {
LOG(ERROR) << "g_setPrgrsSmoothFunc is nullptr";
return;
}
g_setPrgrsSmoothFunc(beginProgress, endProgress, upParams, isFinish);
}
static UpdaterStatus VerifyPackages(UpdaterParams &upParams)
{
UPDATER_INIT_RECORD;
LOG(INFO) << "Verify packages start...";
UPDATER_UI_INSTANCE.ShowProgressPage();
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKG));
if (upParams.callbackProgress == nullptr) {
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
UPDATER_LAST_WORD(UPDATE_CORRUPT, "upParams.callbackProgress is null");
return UPDATE_CORRUPT;
}
upParams.callbackProgress(0.0);
upParams.installTime.resize(upParams.updatePackage.size(), std::chrono::duration<double>(0));
ReadInstallTime(upParams);
for (unsigned int i = upParams.pkgLocation; i < upParams.updatePackage.size(); i++) {
LOG(INFO) << "Verify package:" << upParams.updatePackage[i];
auto startTime = std::chrono::system_clock::now();
PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
if (manager == nullptr) {
LOG(ERROR) << "CreatePackageInstance fail";
return UPDATE_ERROR;
}
int32_t verifyret = OtaUpdatePreCheck(manager, upParams.updatePackage[i]);
PkgManager::ReleasePackageInstance(manager);
if (verifyret == UPDATE_SUCCESS) {
verifyret = UpdatePreCheck(upParams, upParams.updatePackage[i]);
}
if (verifyret != UPDATE_SUCCESS) {
UpdaterVerifyFailEntry((verifyret == PKG_INVALID_DIGEST) && (upParams.updateMode == HOTA_UPDATE));
upParams.pkgLocation = i;
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
auto endTime = std::chrono::system_clock::now();
upParams.installTime[i] = endTime - startTime;
return UPDATE_CORRUPT;
}
auto endTime = std::chrono::system_clock::now();
upParams.installTime[i] = endTime - startTime;
}
if (VerifySpecialPkgs(upParams) != PKG_SUCCESS) {
UPDATER_LAST_WORD(UPDATE_CORRUPT, "VerifySpecialPkgs failed");
return UPDATE_CORRUPT;
}
ProcessPrgrsSmooth(UPDATER_UI_INSTANCE.GetCurrentPercent(), UPDATER_UI_INSTANCE.GetCurrentPercent() +
static_cast<int>(VERIFY_PERCENT * FULL_PERCENT_PROGRESS), upParams, false);
LOG(INFO) << "Verify packages successfull...";
return UPDATE_SUCCESS;
}
__attribute__((weak)) bool IsSpareBoardBoot(void)
{
LOG(INFO) << "no need check spareboardboot";
return false;
}
bool IsBatteryCapacitySufficient()
{
RecordBatteryLevel();
if (Utils::CheckUpdateMode(OTA_MODE)) {
LOG(INFO) << "this is OTA update, on need to determine the battery";
return true;
}
if (IsSpareBoardBoot()) {
LOG(INFO) << "this is spare board boot, no need to determine the battery";
return true;
}
static constexpr auto levelIdx = "lowBatteryLevel";
static constexpr auto jsonPath = "/etc/product_cfg.json";
int capacity = 0;
bool ret = GetBatteryCapacity(capacity);
if (!ret) {
return true;
}
JsonNode node { Fs::path { jsonPath }};
auto item = node[levelIdx].As<int>();
if (!item.has_value()) {
return true;
}
int lowLevel = *item;
if (lowLevel > 100 || lowLevel < 0) {
LOG(ERROR) << "load battery level error:" << lowLevel;
return false;
}
LOG(INFO) << "current capacity:" << capacity << ", low level:" << lowLevel;
return capacity >= lowLevel;
}
UpdaterStatus InstallUpdaterBinfile(UpdaterParams &upParams, PkgManager::PkgManagerPtr manager)
{
UPDATER_INIT_RECORD;
UpdaterStatus status = UPDATE_UNKNOWN;
STAGE(UPDATE_STAGE_BEGIN) << "Install Binfile";
status = DoInstallUpdaterBinfile(manager, upParams, HOTA_UPDATE);
if (status != UPDATE_SUCCESS) {
UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
UPDATER_UI_INSTANCE.ShowLog(TR(LOG_UPDFAIL));
STAGE(UPDATE_STAGE_FAIL) << "Install failed";
if (status == UPDATE_RETRY) {
HardwareFaultRetry::GetInstance().DoRetryAction();
UPDATER_UI_INSTANCE.ShowFailedPage();
}
} else {
LOG(INFO) << "Install binfile success.";
STAGE(UPDATE_STAGE_SUCCESS) << "Install binfile";
}
return status;
}
UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, PkgManager::PkgManagerPtr manager)
{
UPDATER_INIT_RECORD;
UpdaterStatus status = UPDATE_UNKNOWN;
STAGE(UPDATE_STAGE_BEGIN) << "Install package";
if (upParams.retryCount == 0) {
if (!PartitionRecord::GetInstance().ClearRecordPartitionOffset()) {
LOG(ERROR) << "ClearRecordPartitionOffset failed";
UPDATER_LAST_WORD(UPDATE_ERROR, "ClearRecordPartitionOffset failed");
return UPDATE_ERROR;
}
SetMessageToMisc(upParams.miscCmd, upParams.retryCount + 1, "retry_count");
}
if (upParams.updateMode == SDCARD_UPDATE) {
status = DoInstallUpdaterPackage(manager, upParams, SDCARD_UPDATE);
} else {
status = DoInstallUpdaterPackage(manager, upParams, HOTA_UPDATE);
if (NotifyActionResult(upParams, status, {SET_RETRY_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "set retry status fail";
}
}
if (status != UPDATE_SUCCESS) {
UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
UPDATER_UI_INSTANCE.ShowLog(TR(LOG_UPDFAIL));
STAGE(UPDATE_STAGE_FAIL) << "Install failed";
if (status == UPDATE_RETRY) {
HardwareFaultRetry::GetInstance().DoRetryAction();
UPDATER_UI_INSTANCE.ShowFailedPage();
}
} else {
LOG(INFO) << "Install package success.";
STAGE(UPDATE_STAGE_SUCCESS) << "Install package";
}
return status;
}
static UpdaterStatus UpdateUpdateFile(const UpdaterParams &upParams,
std::vector<double> &pkgStartPosition, double &updateStartPosition,
std::vector<std::string> &updateFile)
{
updateFile.clear();
if (upParams.updateBin.size() > 0) {
if (upParams.pkgLocation == upParams.updateBin.size()) {
updateStartPosition = VERIFY_PERCENT;
return UPDATE_SUCCESS;
}
for (const auto& file : upParams.updateBin) {
updateFile.push_back(file);
}
} else if (upParams.updatePackage.size() > 0) {
if (upParams.pkgLocation == upParams.updatePackage.size()) {
updateStartPosition = VERIFY_PERCENT;
return UPDATE_SUCCESS;
}
for (const auto& file : upParams.updatePackage) {
updateFile.push_back(file);
}
}
return UPDATE_SKIP;
}
static UpdaterStatus CalcProgress(const UpdaterParams &upParams,
std::vector<double> &pkgStartPosition, double &updateStartPosition)
{
UPDATER_INIT_RECORD;
int64_t allPkgSize = 0;
std::vector<int64_t> everyPkgSize;
std::vector<std::string> updateFile;
UpdaterStatus status = UpdateUpdateFile(upParams, pkgStartPosition, updateStartPosition, updateFile);
if (status == UPDATE_SUCCESS) {
return UPDATE_SUCCESS;
}
for (const auto &path : updateFile) {
char realPath[PATH_MAX] = {0};
if (realpath(path.c_str(), realPath) == nullptr) {
LOG(WARNING) << "Can not find updatePackage : " << path;
everyPkgSize.push_back(0);
continue;
}
struct stat st {};
if (stat(realPath, &st) == 0) {
everyPkgSize.push_back(st.st_size);
allPkgSize += st.st_size;
LOG(INFO) << "pkg " << path << " size is:" << st.st_size;
}
}
pkgStartPosition.push_back(VERIFY_PERCENT);
if (allPkgSize == 0) {
LOG(ERROR) << "All packages's size is 0.";
UPDATER_LAST_WORD(UPDATE_ERROR, "All packages's size is 0.");
return UPDATE_ERROR;
}
int64_t startSize = 0;
for (auto size : everyPkgSize) {
startSize += size;
float percent = static_cast<double>(startSize) / static_cast<double>(allPkgSize) + VERIFY_PERCENT;
percent = (percent > 1.0) ? 1.0 : percent;
LOG(INFO) << "percent is:" << percent;
pkgStartPosition.push_back(percent);
}
updateStartPosition = pkgStartPosition[upParams.pkgLocation];
return UPDATE_SUCCESS;
}
static int CheckMountData()
{
UPDATER_INIT_RECORD;
constexpr int retryTime = 3;
for (int i = 0; i < retryTime; i++) {
if (SetupPartitions(true, Utils::IsVabDevice()) == 0) {
return 0;
}
LOG(INFO) << "retry mount userdata number:" << i;
Utils::UsSleep(DISPLAY_TIME);
}
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
UPDATER_LAST_WORD(UPDATE_ERROR, "retry mount userdata more than three times");
return UPDATE_ERROR;
}
static UpdaterStatus VerifyCommonFiles(UpdaterParams &upParams)
{
if (upParams.updateBin.size() > 0) {
if (upParams.pkgLocation == upParams.updateBin.size()) {
LOG(WARNING) << "all package has been upgraded, skip pre process";
return UPDATE_SUCCESS;
}
UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_VERIFY_PACKAGE_EVENT);
if (VerifyBinfiles(upParams) != UPDATE_SUCCESS) {
LOG(ERROR) << "VerifyBinfiles failed";
return UPDATE_CORRUPT;
}
} else if (upParams.updatePackage.size() > 0) {
if (upParams.pkgLocation == upParams.updatePackage.size()) {
LOG(WARNING) << "all package has been upgraded, skip pre process";
return UPDATE_SUCCESS;
}
UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_VERIFY_PACKAGE_EVENT);
if (VerifyPackages(upParams) != UPDATE_SUCCESS) {
LOG(ERROR) << "VerifyPackages failed";
return UPDATE_CORRUPT;
}
}
return UPDATE_SUCCESS;
}
static UpdaterStatus SetUpdateParam(UpdaterParams &upParams, bool isUpdateCurrSlot)
{
if (SetUpdateSlotParam(upParams, false) != UPDATE_SUCCESS) {
LOG(ERROR) << "SetUpdateSlotParam failed";
return UPDATE_ERROR;
}
if (SetUpdateSuffixParam() != UPDATE_SUCCESS) {
LOG(ERROR) << "SetUpdateSuffixParam failed";
return UPDATE_ERROR;
}
return UPDATE_SUCCESS;
}
static UpdaterStatus VerifyUpParams(UpdaterParams &upParams)
{
if (SetUpdateParam(upParams, false) != UPDATE_SUCCESS) {
LOG(ERROR) << "SetUpdateParam failed";
return UPDATE_ERROR;
}
if (VerifyCommonFiles(upParams) != UPDATE_SUCCESS) {
return UPDATE_CORRUPT;
}
if (upParams.updatePackage.size() > 0) {
if (IsSpaceCapacitySufficient(upParams) == UPDATE_ERROR) {
UPDATER_LAST_WORD(UPDATE_UNKNOWN, "space nott enough");
return UPDATE_UNKNOWN;
}
}
if (upParams.retryCount == 0 && !IsBatteryCapacitySufficient()) {
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(LOG_LOWPOWER));
UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
UPDATER_LAST_WORD(UPDATE_ERROR, "Battery is not sufficient for install package.");
LOG(ERROR) << "Battery is not sufficient for install package.";
return UPDATE_SKIP;
}
return UPDATE_SUCCESS;
}
static UpdaterStatus PreUpdatePackages(UpdaterParams &upParams)
{
UPDATER_INIT_RECORD;
LOG(INFO) << "start to update packages, start index:" << upParams.pkgLocation;
UpdaterStatus status = UPDATE_UNKNOWN;
ON_SCOPE_EXIT(syncresult) {
NotifyPreCheck(status, upParams);
};
ResetCollectTotalIo();
if (upParams.updateBin.size() > 0) {
upParams.installTime.resize(upParams.updateBin.size(), std::chrono::duration<double>(0));
if (CheckMountData() != 0) {
return UPDATE_ERROR;
}
} else if (upParams.updatePackage.size() > 0) {
upParams.installTime.resize(upParams.updatePackage.size(), std::chrono::duration<double>(0));
if (CheckMountData() != 0) {
return UPDATE_ERROR;
}
}
const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
const std::string resultPathBak = std::string(LOG_UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
(void)DeleteFile(resultPath);
LOG(INFO) << "delete last upgrade file";
(void)DeleteFile(resultPathBak);
status = VerifyUpParams(upParams);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "verify updater params fail";
return status;
}
NotifyPreCheck(status, upParams);
if (status != UPDATE_SUCCESS) {
CANCEL_SCOPE_EXIT_GUARD(syncresult);
return UPDATE_CORRUPT;
}
#ifdef UPDATER_USE_PTABLE
if (!PtablePreProcess::GetInstance().DoPtableProcess(upParams)) {
LOG(ERROR) << "DoPtableProcess failed";
return UPDATE_ERROR;
}
#endif
CANCEL_SCOPE_EXIT_GUARD(syncresult);
return UPDATE_SUCCESS;
}
static UpdaterStatus DoInstallBinfiles(UpdaterParams &upParams, std::vector<double> &pkgStartPosition)
{
UPDATER_INIT_RECORD;
UpdaterStatus status = UPDATE_UNKNOWN;
if (upParams.pkgLocation == upParams.updateBin.size()) {
LOG(WARNING) << "all Binfiles has been installed, directly return success";
upParams.callbackProgress(FULL_PERCENT_PROGRESS);
return UPDATE_SUCCESS;
}
PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
if (manager == nullptr) {
LOG(ERROR) << "CreatePackageInstance fail";
return UPDATE_ERROR;
}
auto startTime = std::chrono::system_clock::now();
upParams.initialProgress = ((UPDATER_UI_INSTANCE.GetCurrentPercent() / FULL_PERCENT) >
pkgStartPosition[upParams.pkgLocation]) ?
(UPDATER_UI_INSTANCE.GetCurrentPercent() / FULL_PERCENT) : pkgStartPosition[upParams.pkgLocation];
upParams.currentPercentage = pkgStartPosition[upParams.pkgLocation + 1] - upParams.initialProgress;
LOG(INFO) << "InstallUpdaterBin pkg is " << upParams.updateBin[upParams.pkgLocation] <<
" percent:" << upParams.initialProgress << "~" << pkgStartPosition[upParams.pkgLocation + 1];
status = InstallUpdaterBinfile(upParams, manager);
auto endTime = std::chrono::system_clock::now();
upParams.installTime[upParams.pkgLocation] = upParams.installTime[upParams.pkgLocation] + endTime - startTime;
WriteInstallTime(upParams);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "InstallUpdaterBin failed! Pkg is " << upParams.updateBin[upParams.pkgLocation];
if (!CheckResultFail()) {
UPDATER_LAST_WORD(status, "InstallUpdaterBin failed");
}
PkgManager::ReleasePackageInstance(manager);
return status;
}
ProgressSmoothHandler(
static_cast<int>(upParams.initialProgress * FULL_PERCENT_PROGRESS +
upParams.currentPercentage * GetTmpProgressValue()),
static_cast<int>(pkgStartPosition[upParams.pkgLocation + 1] * FULL_PERCENT_PROGRESS));
SetMessageToMisc(upParams.miscCmd, upParams.pkgLocation + 1, "upgraded_pkg_num");
PkgManager::ReleasePackageInstance(manager);
return status;
}
static UpdaterStatus DoInstallPackages(UpdaterParams &upParams, std::vector<double> &pkgStartPosition)
{
UPDATER_INIT_RECORD;
UpdaterStatus status = UPDATE_UNKNOWN;
if (upParams.pkgLocation == upParams.updatePackage.size()) {
LOG(WARNING) << "all packages has been installed, directly return success";
upParams.callbackProgress(FULL_PERCENT_PROGRESS);
return UPDATE_SUCCESS;
}
for (; upParams.pkgLocation < upParams.updatePackage.size(); upParams.pkgLocation++) {
PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
if (manager == nullptr) {
LOG(ERROR) << "CreatePackageInstance fail";
return UPDATE_ERROR;
}
auto startTime = std::chrono::system_clock::now();
upParams.initialProgress = ((UPDATER_UI_INSTANCE.GetCurrentPercent() / FULL_PERCENT) >
pkgStartPosition[upParams.pkgLocation]) ?
(UPDATER_UI_INSTANCE.GetCurrentPercent() / FULL_PERCENT) : pkgStartPosition[upParams.pkgLocation];
upParams.currentPercentage = pkgStartPosition[upParams.pkgLocation + 1] - upParams.initialProgress;
LOG(INFO) << "InstallUpdaterPackage pkg is " << upParams.updatePackage[upParams.pkgLocation] <<
" percent:" << upParams.initialProgress << "~" << pkgStartPosition[upParams.pkgLocation + 1];
status = InstallUpdaterPackage(upParams, manager);
auto endTime = std::chrono::system_clock::now();
upParams.installTime[upParams.pkgLocation] = upParams.installTime[upParams.pkgLocation] + endTime - startTime;
WriteInstallTime(upParams);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "InstallUpdaterPackage failed! Pkg is " << upParams.updatePackage[upParams.pkgLocation];
if (!CheckResultFail()) {
UPDATER_LAST_WORD(status, "InstallUpdaterPackage failed");
}
PkgManager::ReleasePackageInstance(manager);
return status;
}
ProcessPrgrsSmooth(
static_cast<int>(upParams.initialProgress * FULL_PERCENT_PROGRESS +
upParams.currentPercentage * GetTmpProgressValue()),
static_cast<int>(pkgStartPosition[upParams.pkgLocation + 1] * FULL_PERCENT_PROGRESS),
upParams, upParams.pkgLocation == upParams.updatePackage.size() - 1);
SetMessageToMisc(upParams.miscCmd, upParams.pkgLocation + 1, "upgraded_pkg_num");
PkgManager::ReleasePackageInstance(manager);
}
return status;
}
UpdaterStatus DoUpdateBinfiles(UpdaterParams &upParams)
{
UPDATER_INIT_RECORD;
UpdaterStatus status = UPDATE_UNKNOWN;
std::vector<double> pkgStartPosition {};
double updateStartPosition = 0.0;
status = CalcProgress(upParams, pkgStartPosition, updateStartPosition);
if (status != UPDATE_SUCCESS) {
UPDATER_LAST_WORD(status, "CalcProgress failed");
return status;
}
for (unsigned int i = 0; i < upParams.updateBin.size(); i++) {
LOG(INFO) << "package " << i << ":" << upParams.updateBin[i] <<
" percent:" << upParams.currentPercentage;
}
if (upParams.callbackProgress == nullptr) {
LOG(ERROR) << "CallbackProgress is nullptr";
return UPDATE_CORRUPT;
}
float value = (UPDATER_UI_INSTANCE.GetCurrentPercent() > (updateStartPosition * FULL_PERCENT_PROGRESS)) ?
UPDATER_UI_INSTANCE.GetCurrentPercent() : (updateStartPosition * FULL_PERCENT_PROGRESS);
upParams.callbackProgress(value);
status = DoInstallBinfiles(upParams, pkgStartPosition);
if (NotifyActionResult(upParams, status, {GET_UPDATE_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "get status fail";
return UPDATE_CORRUPT;
}
if (status != UPDATE_SUCCESS) {
UPDATER_LAST_WORD(status, "DoInstallBinfiles failed");
return status;
}
if (upParams.forceUpdate) {
UPDATER_UI_INSTANCE.ShowLogRes(TR(LABEL_UPD_OK_SHUTDOWN));
}
if (NotifyActionResult(upParams, status, {GET_UPDATE_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "get status fail";
return UPDATE_CORRUPT;
}
UPDATER_UI_INSTANCE.ShowSuccessPage();
return status;
}
UpdaterStatus DoUpdatePackages(UpdaterParams &upParams)
{
UPDATER_INIT_RECORD;
UpdaterStatus status = UPDATE_UNKNOWN;
std::vector<double> pkgStartPosition {};
double updateStartPosition = 0.0;
status = CalcProgress(upParams, pkgStartPosition, updateStartPosition);
if (status != UPDATE_SUCCESS) {
UPDATER_LAST_WORD(status, "CalcProgress failed");
return status;
}
for (unsigned int i = 0; i < upParams.updatePackage.size(); i++) {
LOG(INFO) << "package " << i << ":" << upParams.updatePackage[i] <<
" percent:" << upParams.currentPercentage;
}
if (upParams.callbackProgress == nullptr) {
LOG(ERROR) << "CallbackProgress is nullptr";
return UPDATE_CORRUPT;
}
float value = (UPDATER_UI_INSTANCE.GetCurrentPercent() > (updateStartPosition * FULL_PERCENT_PROGRESS)) ?
UPDATER_UI_INSTANCE.GetCurrentPercent() : (updateStartPosition * FULL_PERCENT_PROGRESS);
upParams.callbackProgress(GetTotalProgressRatio() * value);
status = DoInstallPackages(upParams, pkgStartPosition);
if (NotifyActionResult(upParams, status, {SET_UPDATE_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "set status fail";
return UPDATE_CORRUPT;
}
if (status != UPDATE_SUCCESS) {
UPDATER_LAST_WORD(status, "DoInstallPackages failed");
return status;
}
return status;
}
static void ShowSuccessUi(UpdaterParams &upParams, UpdaterStatus &status)
{
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "update not succ";
return;
}
if (upParams.forceUpdate) {
UPDATER_UI_INSTANCE.ShowLogRes(TR(LABEL_UPD_OK_SHUTDOWN));
}
if (NotifyActionResult(upParams, status, {GET_UPDATE_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "get status fail";
status = UPDATE_CORRUPT;
return;
}
UPDATER_UI_INSTANCE.ShowSuccessPage();
}
__attribute__((weak)) UpdaterStatus CheckAndSetSlot([[maybe_unused]]UpdaterParams &upParams)
{
LOG(INFO) << "not need check and set slot";
#ifndef UPDATER_UT
SetActiveSlot();
#endif
return UPDATE_SUCCESS;
}
__attribute__((weak)) bool PostUpdateSyncProcess([[maybe_unused]] bool isOtaUpdate,
[[maybe_unused]] const UpdaterParams &upParams, [[maybe_unused]] UpdaterStatus &status)
{
LOG(INFO) << "not need sync process";
return true;
}
__attribute__((weak)) bool PostUpdateWriteBack()
{
LOG(INFO) << "not need write back process";
return true;
}
static void PostUpdate(UpdaterParams &upParams, UpdaterStatus &status,
const std::vector<std::string>& updateList, const std::string& type)
{
if (status == UPDATE_SUCCESS) {
if (!PostUpdateWriteBack()) {
LOG(ERROR) << "write stashed images to device failed";
status = UPDATE_ERROR;
}
}
if (status == UPDATE_SUCCESS) {
status = CheckAndSetSlot(upParams);
}
ClearUpdateSlotParam();
ClearUpdateSuffixParam();
bool updateResult = (status == UPDATE_SUCCESS);
std::string writeBuffer;
std::string buf;
std::string time;
if (!updateResult) {
const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
std::ifstream fin {resultPath};
if (!fin.is_open() || !std::getline(fin, buf)) {
LOG(ERROR) << "read result file error: " << resultPath;
buf = "fail|";
}
} else {
buf = "pass|";
upParams.pkgLocation = upParams.pkgLocation == 0 ? upParams.pkgLocation : (upParams.pkgLocation - 1);
}
for (unsigned int i = 0; i < upParams.pkgLocation; i++) {
time = DurationToString(upParams.installTime, i);
writeBuffer += (i < updateList.size() ? updateList[i] : "");
writeBuffer += "|pass||install_time=" + time + "|\n";
}
time = DurationToString(upParams.installTime, upParams.pkgLocation);
writeBuffer += (upParams.pkgLocation < updateList.size() ? updateList[upParams.pkgLocation] : "");
writeBuffer += "|" + buf + "|install_time=" + time + "|\n";
for (unsigned int i = upParams.pkgLocation + 1; i < updateList.size(); i++) {
writeBuffer += updateList[i] + "\n";
}
if (!writeBuffer.empty()) {
writeBuffer.pop_back();
}
LOG(INFO) << "post over, writeBuffer = " << writeBuffer;
WriteDumpResult(writeBuffer, UPDATER_PATH, UPDATER_RESULT_FILE);
WriteDumpResult(writeBuffer, LOG_UPDATER_PATH, UPDATER_RESULT_FILE);
DeleteInstallTimeFile();
}
static void PostUpdateBinfiles(UpdaterParams &upParams, UpdaterStatus &status)
{
PostUpdate(upParams, status, upParams.updateBin, "Binfiles");
}
static void PostUpdatePackages(UpdaterParams &upParams, UpdaterStatus &status)
{
PostUpdate(upParams, status, upParams.updatePackage, "Packages");
}
static UpdaterStatus PreSdcardUpdatePackages(UpdaterParams &upParams)
{
UpdaterStatus status = UPDATE_UNKNOWN;
ON_SCOPE_EXIT(syncresult) {
NotifyPreCheck(status, upParams);
};
ResetCollectTotalIo();
upParams.installTime.resize(upParams.updatePackage.size(), std::chrono::duration<double>(0));
if (upParams.retryCount == 0 && !IsBatteryCapacitySufficient()) {
UPDATER_UI_INSTANCE.ShowUpdInfo(TR(LOG_LOWPOWER));
UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
LOG(ERROR) << "Battery is not sufficient for install package.";
return UPDATE_SKIP;
}
UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_VERIFY_PACKAGE_EVENT);
if (!PreSdSpecialProcess(upParams)) {
LOG(ERROR) << "pre sd special process failed";
return UPDATE_ERROR;
}
status = VerifyPackages(upParams);
NotifyPreCheck(status, upParams);
CANCEL_SCOPE_EXIT_GUARD(syncresult);
if (status != UPDATE_SUCCESS) {
return UPDATE_CORRUPT;
}
#ifdef UPDATER_USE_PTABLE
if (!PtablePreProcess::GetInstance().DoPtableProcess(upParams)) {
LOG(ERROR) << "DoPtableProcess failed";
return UPDATE_ERROR;
}
#endif
return UPDATE_SUCCESS;
}
static void PostSdcardUpdatePackages(UpdaterParams &upParams, UpdaterStatus &status)
{
(void)PostUpdateSyncProcess(false, upParams, status);
ClearUpdateSlotParam();
ClearUpdateSuffixParam();
PostSdSpecialProcess(status);
if (Utils::CheckUpdateMode(Updater::SDCARD_INTRAL_MODE)) {
PostUpdatePackages(upParams, status);
} else if (status == UPDATE_SUCCESS) {
if (NotifyActionResult(upParams, status, {GET_UPDATE_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "get status fail";
status = UPDATE_CORRUPT;
return;
}
UPDATER_UI_INSTANCE.ShowSuccessPage();
}
}
UpdaterStatus UpdaterFromSdcard(UpdaterParams &upParams)
{
UPDATER_INIT_RECORD;
upParams.callbackProgress = [] (float value) { UPDATER_UI_INSTANCE.ShowProgress(value); };
SetMessageToMisc(upParams.miscCmd, 0, "sdcard_update");
UpdaterStatus status = UPDATE_SUCCESS;
if (NotifyActionResult(upParams, status, {TRIGGER_SDUPDATE}) != UPDATE_SUCCESS) {
LOG(ERROR) << "trigger sd update fail";
return UPDATE_ERROR;
}
status = CheckSdcardPkgs(upParams);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "can not find sdcard packages";
if (NotifyActionResult(upParams, status, {SET_UPDATE_STATUS, GET_UPDATE_STATUS}) != UPDATE_SUCCESS) {
LOG(ERROR) << "notify action fail";
}
return UPDATE_ERROR;
}
status = PreSdcardUpdatePackages(upParams);
if (status == UPDATE_SUCCESS) {
upParams.initialProgress += VERIFY_PERCENT;
upParams.currentPercentage -= VERIFY_PERCENT;
STAGE(UPDATE_STAGE_BEGIN) << "UpdaterFromSdcard";
UPDATER_UI_INSTANCE.ShowLog(TR(LOG_SDCARD_NOTMOVE));
status = DoUpdatePackages(upParams);
}
PostSdcardUpdatePackages(upParams, status);
return status;
}
UpdaterStatus InstallUpdaterBinfiles(UpdaterParams &upParams)
{
UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_UPDATE_PACKAGE_EVENT);
UpdaterStatus status = PreUpdatePackages(upParams);
if (status == UPDATE_SUCCESS) {
status = DoUpdateBinfiles(upParams);
}
PostUpdateBinfiles(upParams, status);
UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_UPDATE_PACKAGE_EVENT);
return status;
}
UpdaterStatus InstallUpdaterPackages(UpdaterParams &upParams)
{
UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_UPDATE_PACKAGE_EVENT);
UpdaterStatus status = PreUpdatePackages(upParams);
if (status == UPDATE_SUCCESS) {
status = DoUpdatePackages(upParams);
}
PostUpdatePackages(upParams, status);
(void)PostUpdateSyncProcess(true, upParams, status);
UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_UPDATE_PACKAGE_EVENT);
return status;
}
UpdaterStatus StartUpdaterEntry(UpdaterParams &upParams)
{
UpdaterStatus status = UPDATE_UNKNOWN;
status = PreStartUpdaterEntry(upParams, status);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "PreStartUpdaterEntry failed";
return status;
}
status = DoUpdaterEntry(upParams);
if (status != UPDATE_SUCCESS) {
LOG(WARNING) << "DoUpdaterEntry failed";
}
status = PostStartUpdaterEntry(upParams, status);
if (status != UPDATE_SUCCESS) {
LOG(ERROR) << "PostStartUpdaterEntry failed";
}
return status;
}
std::string GetCurrentTime()
{
struct tm timeInfo {};
GetLocalTime(timeInfo);
std::ostringstream oss;
int width = 2;
oss << std::setw(width) << std::setfill('0') << timeInfo.tm_hour
<< ":" << std::setw(width) << std::setfill('0') << timeInfo.tm_min;
std::string formattedTime = oss.str();
int beginYear = 1900;
std::string currentTime = std::to_string(timeInfo.tm_year + beginYear) + TR(YEAR_STRING) +
std::to_string(timeInfo.tm_mon + 1) + TR(MONTH_STRING) +
std::to_string(timeInfo.tm_mday) + TR(DAY_STRING) + " " + formattedTime;
return currentTime;
}
UpdaterStatus DoSecureErase(UpdaterParams &upParams)
{
UpdaterStatus status = UPDATE_UNKNOWN;
UPDATER_UI_INSTANCE.ShowProgressPage();
(void) UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_SECUREERASE);
if (upParams.factoryResetMode == "disk_erase") {
(void) UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_DISKERASE);
}
LOG(INFO) << "SecureErase FactoryReset begin";
status = UPDATE_SUCCESS;
#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
DoProgress();
#endif
time_t eraseStart = time(nullptr);
if (FactoryReset(SECURE_ERASE, "/data") != 0) {
LOG(ERROR) << "FactoryReset secure erase failed";
status = UPDATE_ERROR;
}
time_t eraseEnd = time(nullptr);
uint64_t eplasedSeconds = static_cast<uint64_t>(difftime(eraseEnd, eraseStart));
if (status == UPDATE_SUCCESS) {
LOG(INFO) << "Secure Erase Finish";
UPDATER_UI_INSTANCE.ShowProgress(100);
UPDATER_UI_INSTANCE.ShowSuccessPage();
Utils::Time finishedTime(eplasedSeconds);
std::string costTimeText = TR(LABEL_COST_TIME) + std::to_string(finishedTime.GetHour()) + " " +
TR(HOUR_STRING) + std::to_string(finishedTime.GetMinute()) + " " + TR(MINUTE_STRING);
std::string currentTime = GetCurrentTime();
std::string finshedText = TR(LABEL_FINISHED_TIME) + currentTime + " (" + costTimeText + ")";
UPDATER_UI_INSTANCE.ShowLogRes(finshedText);
ClearUpdaterParaMisc();
if (upParams.factoryResetMode == "disk_erase") {
while (true) {
Utils::UsSleep(DISPLAY_TIME);
}
}
}
return status;
}
UpdaterStatus DoFactoryRstEntry(UpdaterParams &upParams)
{
UpdaterStatus status = UPDATE_UNKNOWN;
if (upParams.factoryResetMode == "factory_wipe_data") {
UPDATER_UI_INSTANCE.ShowProgressPage();
LOG(INFO) << "Factory level FactoryReset begin";
status = UPDATE_SUCCESS;
#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
DoProgress();
#endif
if (FactoryReset(FACTORY_WIPE_DATA, "/data") != 0) {
LOG(ERROR) << "FactoryReset factory level failed";
status = UPDATE_ERROR;
}
UPDATER_UI_INSTANCE.ShowLogRes(
(status != UPDATE_SUCCESS) ? TR(LOGRES_FACTORY_FAIL) : TR(LOGRES_FACTORY_DONE));
} else if (upParams.factoryResetMode == "user_wipe_data" || upParams.factoryResetMode == "menu_wipe_data") {
UPDATER_UI_INSTANCE.ShowProgressPage();
LOG(INFO) << "User level FactoryReset begin";
status = UPDATE_SUCCESS;
#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
DoProgress();
#endif
if (FactoryReset(upParams.factoryResetMode == "user_wipe_data" ?
USER_WIPE_DATA : MENU_WIPE_DATA, "/data") != 0) {
LOG(ERROR) << "FactoryReset user level failed";
status = UPDATE_ERROR;
}
if (status != UPDATE_SUCCESS) {
UPDATER_UI_INSTANCE.ShowLogRes(TR(LOGRES_WIPE_FAIL));
} else {
UPDATER_UI_INSTANCE.ShowSuccessPage();
UPDATER_UI_INSTANCE.ShowLogRes(TR(LOGRES_WIPE_FINISH));
ClearUpdaterParaMisc();
std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
}
} else if (upParams.factoryResetMode == "secure_erase" || upParams.factoryResetMode == "disk_erase") {
status = DoSecureErase(upParams);
}
return status;
}
UpdaterStatus DoUpdaterEntry(UpdaterParams &upParams)
{
UpdaterStatus status = UPDATE_UNKNOWN;
if (upParams.updateBin.size() > 0) {
LOG(INFO) << "start bin update";
UPDATER_UI_INSTANCE.ShowProgressPage();
status = InstallUpdaterBinfiles(upParams);
} else if (upParams.updateMode == SDCARD_UPDATE) {
LOG(INFO) << "start sdcard update";
UPDATER_UI_INSTANCE.ShowProgressPage();
status = UpdaterFromSdcard(upParams);
return status;
} else if (upParams.updatePackage.size() > 0) {
UPDATER_UI_INSTANCE.ShowProgressPage();
status = InstallUpdaterPackages(upParams);
} else if (upParams.updateMode == SUBPKG_UPDATE) {
UPDATER_UI_INSTANCE.ShowProgressPage();
if (CheckMountData() != 0) {
LOG(ERROR) << "subpkg update mount data fail";
return UPDATE_ERROR;
}
status = UpdateSubPkg(upParams);
if (status == UPDATE_SUCCESS) {
UPDATER_UI_INSTANCE.ShowSuccessPage();
}
} else {
status = DoFactoryRstEntry(upParams);
}
return status;
}
static void InitSecureEraseFunc(char* &optarg,
PackageUpdateMode &mode, UpdaterParams &upParams)
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
SecureErase::GetInstance().AddOverWritePartitions(upParams.factoryResetMode);
if (optarg != nullptr) {
std::string offsetStr(optarg);
uint64_t offset = 0;
if (!Utils::ConvertToUnsignedLongLong(offsetStr, offset)) {
LOG(ERROR) << "Convert secure erase offset error";
offset = 0;
}
LOG(INFO) << "secure erase offset: " << offset;
SecureErase::GetInstance().LoadOffsetInRetry(offset);
}
}
std::unordered_map<std::string, std::function<void ()>> InitOptionsFuncTab(char* &optarg,
PackageUpdateMode &mode, UpdaterParams &upParams)
{
std::unordered_map<std::string, std::function<void ()>> optionsFuncTab {
{"update_bin", [&upParams, &optarg, &mode]() -> void
{
upParams.updateBin.push_back(optarg);
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_OTA);
mode = HOTA_UPDATE;
}},
{"update_package", [&upParams, &optarg, &mode]() -> void
{
upParams.updatePackage.push_back(optarg);
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_OTA);
mode = HOTA_UPDATE;
}},
{"retry_count", [&upParams, &optarg]() -> void
{
upParams.retryCount = atoi(optarg);
HardwareFaultRetry::GetInstance().SetRetryCount(upParams.retryCount);
}},
{"panic_count", [&upParams, &optarg]() -> void
{
upParams.panicCount = atoi(optarg);
}},
{"factory_wipe_data", [&upParams]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
upParams.factoryResetMode = "factory_wipe_data";
}},
{"wipe_data_at_factoryreset_0", [&upParams]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_ATFACTORYRST);
upParams.factoryResetMode = "factory_wipe_data";
}},
{"user_wipe_data", [&upParams]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
upParams.factoryResetMode = "user_wipe_data";
}},
{"wipe_data_factory_lowlevel", [&upParams]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
upParams.factoryResetMode = "user_wipe_data";
}},
{"menu_wipe_data", [&upParams]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
upParams.factoryResetMode = "menu_wipe_data";
}},
{"upgraded_pkg_num", [&upParams, &optarg]() -> void
{
upParams.pkgLocation = static_cast<unsigned int>(atoi(optarg));
}},
{"sdcard_update", [&upParams]() -> void
{
upParams.updateMode = SDCARD_UPDATE;
upParams.sdExtMode = SDCARD_NORMAL_UPDATE;
}},
{"UPDATE:MAINIMG", [&upParams]() -> void
{
upParams.updateMode = SDCARD_UPDATE;
upParams.sdExtMode = SDCARD_MAINIMG;
}},
{"factory_sd_update", [&upParams]() -> void
{
upParams.updateMode = SDCARD_UPDATE;
upParams.sdExtMode = SDCARD_NORMAL_UPDATE;
}},
{"UPDATE:SD", [&upParams]() -> void
{
upParams.updateMode = SDCARD_UPDATE;
upParams.sdExtMode = SDCARD_NORMAL_UPDATE;
}},
{"UPDATE:SDFROMDEV", [&upParams]() -> void
{
upParams.updateMode = SDCARD_UPDATE;
upParams.sdExtMode = SDCARD_UPDATE_FROM_DEV;
}},
{"force_update_action", [&upParams, &optarg]() -> void
{
if (std::string(optarg) == POWEROFF) {
upParams.forceUpdate = true;
}
}},
{"night_update", [&upParams]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_NIGHTUPDATE);
upParams.forceReboot = true;
}},
{"sdcard_intral_update", [&upParams]() -> void
{
upParams.updateMode = SDCARD_UPDATE;
}},
{"shrink_info", [&upParams, &optarg]() -> void
{
upParams.shrinkInfo = std::string(optarg);
}},
{"virtual_shrink_info", [&upParams, &optarg]() -> void
{
upParams.virtualShrinkInfo = std::string(optarg);
}},
{"subpkg_update", [&upParams, &optarg, &mode]() -> void
{
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_OTA);
upParams.updateMode = SUBPKG_UPDATE;
mode = HOTA_UPDATE;
}},
{"secure_erase", [&upParams, &optarg, &mode]() -> void
{
upParams.factoryResetMode = "secure_erase";
InitSecureEraseFunc(optarg, mode, upParams);
}},
{"disk_erase", [&upParams, &optarg, &mode]() -> void
{
upParams.factoryResetMode = "disk_erase";
InitSecureEraseFunc(optarg, mode, upParams);
}}
};
return optionsFuncTab;
}
__attribute__((weak)) bool IsSupportOption([[maybe_unused]] const std::string &option)
{
LOG(INFO) << "option: " << option;
return false;
}
__attribute__((weak)) UpdaterStatus ProcessOtherOption([[maybe_unused]] const std::string &option,
[[maybe_unused]] UpdaterParams &upParams, PackageUpdateMode &mode)
{
return UPDATE_UNKNOWN;
}
static UpdaterStatus StartUpdater(const std::vector<std::string> &args,
char **argv, PackageUpdateMode &mode, UpdaterParams &upParams)
{
std::vector<char *> extractedArgs;
int rc;
int optionIndex;
auto optionsFuncTab = InitOptionsFuncTab(optarg, mode, upParams);
for (const auto &arg : args) {
extractedArgs.push_back(const_cast<char *>(arg.c_str()));
STAGE(UPDATE_STAGE_OUT) << "option:" << arg;
LOG(INFO) << "option:" << arg;
}
extractedArgs.push_back(nullptr);
extractedArgs.insert(extractedArgs.begin(), argv[0]);
while ((rc = getopt_long(extractedArgs.size() - 1, extractedArgs.data(), "", OPTIONS, &optionIndex)) != -1) {
switch (rc) {
case 0: {
std::string option = OPTIONS[optionIndex].name;
if (optionsFuncTab.find(option) != optionsFuncTab.end()) {
auto optionsFunc = optionsFuncTab.at(option);
optionsFunc();
} else if (IsSupportOption(option)) {
return ProcessOtherOption(option, upParams, mode);
}
break;
}
default:
LOG(ERROR) << "Invalid argument.";
break;
}
}
optind = 1;
if (upParams.pkgLocation == 0) {
DeleteInstallTimeFile();
}
if (upParams.updateMode == SDCARD_UPDATE) {
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_SDCARD);
mode = SDCARD_UPDATE;
}
return StartUpdaterEntry(upParams);
}
REGISTER_MODE(Updater, "updater.hdc.configfs");
__attribute__((weak)) const char* GetResetMisc(const std::vector<std::string> &args)
{
return "";
}
__attribute__((weak)) const char* GetSdResetMisc()
{
return "";
}
__attribute__((weak)) bool NotifySdUpdateReboot(const UpdaterParams &upParams)
{
if (upParams.sdExtMode == SDCARD_UPDATE_FROM_DEV) {
NotifyReboot("updater", "Updater wipe data after upgrade success", "--user_wipe_data");
return true;
}
if (upParams.sdExtMode == SDCARD_UPDATE_FROM_DATA) {
std::string extData = "--user_wipe_data\n--";
extData += ERASE_LOG_OEMINFO;
extData += "\n--";
extData += RESET_MESSAGE_INFO;
NotifyReboot("updater", "Updater wipe data after upgrade success", extData);
return true;
}
return false;
}
__attribute__((weak)) void NotifyAutoReboot(PackageUpdateMode &mode)
{
return;
}
__attribute__((weak)) void DeleteOtaPkg([[maybe_unused]] const UpdaterParams &upParams)
{
LOG(INFO) << "Delete ota package";
}
void RebootAfterUpdateSuccess(const UpdaterParams &upParams, const std::vector<std::string> &args,
const UpdaterStatus &status, const PackageUpdateMode &mode)
{
#if !defined(UPDATER_UT) && !defined(UPDATER_UI_SUPPORT)
if (status == UPDATE_UNKNOWN && mode == UNKNOWN_UPDATE) {
while (true) {
Utils::UsSleep(DISPLAY_TIME);
}
}
#endif
std::string extData;
if (IsNeedUpdateNode(args, extData)) {
LOG(INFO) << "Need reboot to updater again.";
NotifyReboot("updater", "Updater update dev node after upgrade success when ptable change", extData);
}
std::string resetData = GetResetMisc(args);
if (!resetData.empty()) {
NotifyReboot("updater", "Updater wipe data after upgrade success", resetData);
return;
}
if (NotifySdUpdateReboot(upParams)) {
LOG(INFO) << "sd update and wipe data";
return;
}
DeleteOtaPkg(upParams);
upParams.forceUpdate ? Utils::DoShutdown("Updater update success go shut down") :
NotifyReboot("", "Updater update success");
}
bool IsNeedWaitUserReboot(UpdaterParams &upParams)
{
if (Updater::Utils::CheckUpdateMode(FACTORY_RESET_OTA_TAG)) {
Utils::UsSleep(5 * DISPLAY_TIME);
PostUpdater(true);
NotifyReboot("updater", "Updater wipe data after upgrade success", FACTORY_RESET_OTA_MISC);
return false;
}
UPDATER_UI_INSTANCE.ShowFailedPage();
if (upParams.forceReboot) {
Utils::UsSleep(5 * DISPLAY_TIME);
PostUpdater(true);
NotifyReboot("", "Updater night update fail");
return false;
}
return true;
}
int UpdaterMain(int argc, char **argv)
{
UpdaterParams upParams {};
upParams.callbackProgress = [] (float value) { UPDATER_UI_INSTANCE.ShowProgress(value); };
UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_INIT_EVENT);
std::vector<std::string> args = ParseParams(argc, argv);
LOG(INFO) << "Ready to start";
#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
UPDATER_UI_INSTANCE.InitEnv();
#endif
UpdaterInit::GetInstance().InvokeEvent(UPDATER_INIT_EVENT);
PackageUpdateMode mode = UNKNOWN_UPDATE;
[[maybe_unused]] UpdaterStatus status = StartUpdater(args, argv, mode, upParams);
ShowSuccessUi(upParams, status);
#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
if (status != UPDATE_SUCCESS && status != UPDATE_SKIP) {
if (mode == HOTA_UPDATE) {
UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
if (!IsNeedWaitUserReboot(upParams)) {
return 0;
}
} else if (mode == SDCARD_UPDATE) {
UPDATER_UI_INSTANCE.ShowLogRes(
status == UPDATE_CORRUPT ? TR(LOGRES_VERIFY_FAILED) : TR(LOGRES_UPDATE_FAILED));
UPDATER_UI_INSTANCE.ShowFailedPage();
} else if (upParams.factoryResetMode == "user_wipe_data" || upParams.factoryResetMode == "secure_erase" ||
upParams.factoryResetMode == "menu_wipe_data" || upParams.factoryResetMode == "factory_wipe_data"||
upParams.factoryResetMode == "disk_erase") {
UPDATER_UI_INSTANCE.ShowFailedPage();
} else if (CheckUpdateMode(USB_UPDATE_FAIL)) {
(void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_USBUPDATE);
UPDATER_UI_INSTANCE.ShowFailedPage();
} else {
UPDATER_UI_INSTANCE.ShowMainpage();
UPDATER_UI_INSTANCE.SaveScreen();
}
NotifyAutoReboot(mode);
while (true) {
Utils::UsSleep(DISPLAY_TIME);
}
return 0;
}
#endif
PostUpdater(true);
RebootAfterUpdateSuccess(upParams, args, status, mode);
return 0;
}
}