/* * Copyright (c) 2021 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 "update_processor.h" #include #include #include #include #include #include "securec.h" #include "applypatch/data_writer.h" #include "applypatch/partition_record.h" #include "applypatch/update_progress.h" #include "dump.h" #include "log.h" #include "package/hash_data_verifier.h" #include "pkg_manager.h" #ifdef UPDATER_USE_PTABLE #include "ptable_manager.h" #endif #include "script_instruction.h" #include "script_manager.h" #include "slot_info/slot_info.h" #include "updater_main.h" #include "updater/updater_const.h" #include "update_bin/bin_process.h" #include "scope_guard.h" #include "bin_chunk_update.h" #define TYPE_ZIP_HEADER 0xaa using namespace Uscript; using namespace Hpackage; using namespace Updater; namespace Updater { constexpr uint32_t BUFFER_SIZE = 50 * 1024; constexpr uint32_t MAX_UPDATER_BUFFER_SIZE = 2 * BUFFER_SIZE; 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; enum UpdateStatus { UPDATE_STATE_INIT = 0, UPDATE_STATE_ONGOING, UPDATE_STATE_FAILED, UPDATE_STATE_SUCCESSFUL, UPDATE_STATE_MAX }; bool ReadLE16(std::istream& is, uint16_t& value) { char buf[2] = {0}; // 2:定义2字节缓冲区,用于读取小端序的16位无符号整数(每字节8位) if (!is.read(buf, sizeof(buf))) { return false; } value = static_cast(static_cast(buf[0])) | (static_cast(static_cast(buf[1])) << BYTE_SHIFT_8); return true; } bool ReadLE32(std::istream& is, uint32_t& value) { char buf[4] = {0}; // 4:定义4字节缓冲区,用于读取小端序的32位无符号整数(每字节8位) if (!is.read(buf, sizeof(buf))) { return false; } value = static_cast(static_cast(buf[0])) | (static_cast(static_cast(buf[1])) << BYTE_SHIFT_8) | (static_cast(static_cast(buf[SECOND_BUFFER])) << BYTE_SHIFT_16) | (static_cast(static_cast(buf[THIRD_BUFFER])) << BYTE_SHIFT_24); return true; } static int ProcessUpdateFile(const std::string &packagePath, FILE* pipeWrite) { std::shared_ptr binChunkUpdate_ {}; // 打开输入文件 std::ifstream inFile(packagePath, std::ios::binary); if (!inFile) { LOG(ERROR) << "Error: Failed to open " << packagePath; return UPDATE_ERROR; } uint16_t type = 0; if (!ReadLE16(inFile, type)) { LOG(ERROR) << "Failed to read type"; return UPDATE_ERROR; } if (type != TYPE_ZIP_HEADER) { LOG(ERROR) << "Unsupported header type: 0x" << std::hex << type; inFile.close(); return UPDATE_ERROR; } uint32_t length = 0; if (!ReadLE32(inFile, length)) { LOG(ERROR) << "Failed to read length"; return UPDATE_ERROR; } if (!inFile.seekg(length, std::ios::cur)) { inFile.close(); LOG(ERROR) << "Failed to seekg length"; return UPDATE_ERROR; } // 读取剩余数据 std::vector buffer_stream(BUFFER_SIZE); binChunkUpdate_ = std::make_unique(MAX_UPDATER_BUFFER_SIZE); while (!inFile.eof()) { inFile.read(reinterpret_cast(buffer_stream.data()), buffer_stream.size()); size_t readBytes = inFile.gcount(); uint32_t dealLen = 0; if (readBytes > 0) { UpdateResultCode ret = binChunkUpdate_->StartBinChunkUpdate( buffer_stream.data(), static_cast(readBytes), dealLen); if (STREAM_UPDATE_SUCCESS == ret) { LOG(INFO) << "StreamInstallProcesser ThreadExecuteFunc STREM_UPDATE_SUCCESS"; } else if (STREAM_UPDATE_FAILURE == ret) { LOG(ERROR) << "StreamInstallProcesser ThreadExecuteFunc STREM_UPDATE_FAILURE"; return UPDATE_ERROR; } else if (STREAM_UPDATE_COMPLETE == ret) { LOG(INFO) << "StreamInstallProcesser ThreadExecuteFunc STREM_UPDATE_COMPLETE"; break; } } } inFile.close(); return UPDATE_SUCCESS; } int ProcessUpdaterStream(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath) { UPDATER_INIT_RECORD; UpdaterInit::GetInstance().InvokeEvent(UPDATER_BINARY_INIT_EVENT); Dump::GetInstance().RegisterDump("DumpHelperLog", std::make_unique()); // 初始化管道 std::unique_ptr pipeWrite(fdopen(pipeFd, "w"), fclose); if (pipeWrite == nullptr) { LOG(ERROR) << "Fail to fdopen, err: " << strerror(errno); UPDATER_LAST_WORD(strerror(errno), "Fail to fdopen"); return EXIT_INVALID_ARGS; } int ret = -1; Detail::ScopeGuard guard([&] { (void)fprintf(pipeWrite.get(), "subProcessResult:%d\n", ret); (void)fflush(pipeWrite.get()); }); setlinebuf(pipeWrite.get()); // 初始化包管理器 PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance(); if (pkgManager == nullptr) { LOG(ERROR) << "pkgManager is nullptr"; UPDATER_LAST_WORD(EXIT_INVALID_ARGS, "pkgManager is nullptr"); return EXIT_INVALID_ARGS; } // 加载包 std::vector components; int loadRet = pkgManager->LoadPackage(packagePath, keyPath, components); if (loadRet != PKG_SUCCESS) { LOG(ERROR) << "Fail to load package"; PkgManager::ReleasePackageInstance(pkgManager); UPDATER_LAST_WORD("Fail to load package", packagePath, keyPath); return EXIT_INVALID_ARGS; } #ifdef UPDATER_USE_PTABLE // 分区表操作 if (!PackagePtable::GetInstance().WritePtableWithFile()) { LOG(ERROR) << "write ptable with file fail"; PkgManager::ReleasePackageInstance(pkgManager); UPDATER_LAST_WORD("Error to write ptable with file"); return EXIT_EXEC_SCRIPT_ERROR; } if (!DevicePtable::GetInstance().LoadPartitionInfo()) { PkgManager::ReleasePackageInstance(pkgManager); return EXIT_EXEC_SCRIPT_ERROR; } #endif // 调用核心函数并传递管道 ret = ProcessUpdateFile(packagePath, pipeWrite.get()); if (ret != UPDATE_SUCCESS) { LOG(ERROR) << "ProcessUpdaterStream failed with code: " << ret; } // 释放资源 PkgManager::ReleasePackageInstance(pkgManager); return ret; } } // Updater