diff --git a/BUILD.gn b/BUILD.gn index 1ec17bb600724cbdc5da12fb0aa3beb849bc9ab2..650dad96c09fccc3a3430ffeb8dad1de5df67793 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2022 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 @@ -13,6 +13,19 @@ import("//build/ohos.gni") +group("fuzztest") { + testonly = true + deps = [ + "test/fuzztest/DoPartitions_fuzzer:DoPartitionsFuzzTest", + "test/fuzztest/ExtractAndExecuteScript_fuzzer:ExtractAndExecuteScriptFuzzTest", + "test/fuzztest/ReadFstabFromFile_fuzzer:ReadFstabFromFileFuzzTest", + "test/fuzztest/UpdaterFactoryReset_fuzzer:UpdaterFactoryResetFuzzTest", + "test/fuzztest/UpdaterFormatPartition_fuzzer:UpdaterFormatPartitionFuzzTest", + "test/fuzztest/UpdaterMountForPath_fuzzer:UpdaterMountForPathFuzzTest", + "test/fuzztest/UpdaterStartUpdaterProc_fuzzer:UpdaterStartUpdaterProcFuzzTest", + ] +} + group("unittest") { testonly = true deps = [ "test/unittest:updater_unittest" ] diff --git a/bundle.json b/bundle.json index 2bece3c7c16d36ad658a01c35be53b976f65d041..c61ec48c005734f30044cf6fb0eed6ff170035be 100644 --- a/bundle.json +++ b/bundle.json @@ -1,7 +1,7 @@ { "name": "@ohos/update_updater", "version": "3.1", - "description": "升级包安装组件运行在recovery分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。", + "description": "升级包安装组件运行在updater分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。", "homePage": "https://gitee.com/openharmony", "license": "Apache License 2.0", "repository": "https://gitee.com/openharmony/update_updater", @@ -66,7 +66,6 @@ "build": { "sub_component": [ "//base/update/updater/resources:updater_resources", - "//base/update/updater/services:updater_etc", "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/script:libupdaterscript", "//base/update/updater/services/log:libupdaterlog", diff --git a/interfaces/kits/include/misc_info/misc_info.h b/interfaces/kits/include/misc_info/misc_info.h index 38f781fd0587162ee6c24bec5f31138cee882cbe..4364588b9dce1fb5b686f5efab5b26c952400e71 100755 --- a/interfaces/kits/include/misc_info/misc_info.h +++ b/interfaces/kits/include/misc_info/misc_info.h @@ -23,7 +23,6 @@ namespace updater { constexpr int MAX_COMMAND_SIZE = 20; constexpr int MAX_UPDATE_SIZE = 100; -constexpr int MAX_LOGO_SIZE = 1024 * 2038; // misc partition offset definition. max size of misc is 2MB, do not overflow. constexpr off_t MISC_BASE_OFFSET = 0; @@ -37,9 +36,6 @@ constexpr off_t MISC_PARTITION_RECORD_SIZE = 1024; constexpr off_t MISC_RECORD_UPDATE_PARTITIONS_OFFSET = MISC_PARTITION_RECORD_OFFSET + MISC_PARTITION_RECORD_SIZE; constexpr off_t MISC_RECORD_UPDATE_PARTITIONS_SIZE = 256; -constexpr off_t MISC_RECORD_MISC_PARTITIONS_OFFSET = 1536; -constexpr off_t MISC_RECORD_MISC_PARTITIONS_SIZE = 1024 * 2038; - struct UpdateMessage { char command[MAX_COMMAND_SIZE]; char update[MAX_UPDATE_SIZE]; @@ -47,5 +43,7 @@ struct UpdateMessage { bool WriteUpdaterMessage(const std::string &path, const UpdateMessage &boot); bool ReadUpdaterMessage(const std::string &path, UpdateMessage &boot); +bool WriteUpdaterMiscMsg(const UpdateMessage &boot); +bool ReadUpdaterMiscMsg(UpdateMessage &boot); } // updater #endif /* MISC_INFO_H */ diff --git a/interfaces/kits/include/package/package.h b/interfaces/kits/include/package/package.h index 94baf70a79012c3c41b1cf96dab2c3719592ce67..22ea8c7f3e98c493e4ce35fe8def0537ce49f327 100755 --- a/interfaces/kits/include/package/package.h +++ b/interfaces/kits/include/package/package.h @@ -27,7 +27,7 @@ extern "C" { constexpr uint32_t DIGEST_MAX_LEN = 32; constexpr int8_t MID_COMPRESS_LEVEL = 2; -constexpr int8_t PKG_SUPPORT_L1 = 0x01; +constexpr uint8_t PKG_SUPPORT_L1 = 0x01; enum PkgPackType { PKG_PACK_TYPE_NONE = 0, @@ -147,6 +147,9 @@ int32_t VerifyPackage(const char *packagePath, const char *keyPath, int32_t VerifyPackageWithCallback(const std::string &packagePath, const std::string &keyPath, std::function cb); +int32_t CreateSignContent(const UpgradePkgInfoExt *pkgInfoExt, const char *packagePath, + const char *signedPackage, const char *keyPath); + #ifdef __cplusplus } #endif diff --git a/interfaces/kits/misc_info/misc_info.cpp b/interfaces/kits/misc_info/misc_info.cpp index cf40c7f46df782ca909a7ca3797f00208990e6b0..afc0c744b81c83bb933ac86eb8643a1583d60129 100755 --- a/interfaces/kits/misc_info/misc_info.cpp +++ b/interfaces/kits/misc_info/misc_info.cpp @@ -19,6 +19,7 @@ #include "fs_manager/mount.h" #include "log/log.h" #include "securec.h" +#include "updater/updater_const.h" namespace updater { bool WriteUpdaterMessage(const std::string &path, const UpdateMessage &boot) @@ -32,8 +33,8 @@ bool WriteUpdaterMessage(const std::string &path, const UpdateMessage &boot) size_t ret = fwrite(&boot, sizeof(UpdateMessage), 1, fp); UPDATER_FILE_CHECK(ret == 1, "WriteUpdaterMessage fwrite failed", fclose(fp); return false); - ret = fclose(fp); - UPDATER_FILE_CHECK(ret == 0, "WriteUpdaterMessage fclose failed", return false); + int res = fclose(fp); + UPDATER_FILE_CHECK(res == 0, "WriteUpdaterMessage fclose failed", return false); return true; } @@ -49,10 +50,26 @@ bool ReadUpdaterMessage(const std::string &path, UpdateMessage &boot) size_t ret = fread(&tempBoot, sizeof(UpdateMessage), 1, fp); UPDATER_FILE_CHECK(ret == 1, "ReadUpdaterMessage fwrite failed", fclose(fp); return false); - ret = fclose(fp); - UPDATER_FILE_CHECK(ret == 0, "ReadUpdaterMessage fclose failed", return false); + int res = fclose(fp); + UPDATER_FILE_CHECK(res == 0, "ReadUpdaterMessage fclose failed", return false); UPDATER_FILE_CHECK(!memcpy_s(&boot, sizeof(UpdateMessage), &tempBoot, sizeof(UpdateMessage)), "ReadUpdaterMessage memcpy failed", return false); return true; } + +bool WriteUpdaterMiscMsg(const UpdateMessage &boot) +{ + auto path = GetBlockDeviceByMountPoint(MISC_PATH); + UPDATER_INFO_CHECK(!path.empty(), "cannot get block device of partition", path = MISC_FILE); + LOG(INFO) << "WriteUpdaterMiscMsg::misc path : " << path; + return WriteUpdaterMessage(path, boot); +} + +bool ReadUpdaterMiscMsg(UpdateMessage &boot) +{ + auto path = GetBlockDeviceByMountPoint(MISC_PATH); + UPDATER_INFO_CHECK(!path.empty(), "cannot get block device of partition", path = MISC_FILE); + LOG(INFO) << "ReadUpdaterMiscMsg::misc path : " << path; + return ReadUpdaterMessage(path, boot); +} } // updater diff --git a/interfaces/kits/packages/package.cpp b/interfaces/kits/packages/package.cpp index ad8dae29762a838c688d03bffd2d2b4a4256d8ae..93baaf7eb65471c4a9d8283e5af80ead9b4d6cd1 100755 --- a/interfaces/kits/packages/package.cpp +++ b/interfaces/kits/packages/package.cpp @@ -225,4 +225,43 @@ int32_t CreatePackageL1(const UpgradePkgInfoExt *pkgInfo, ComponentInfoExt comp[ } PkgManager::ReleasePackageInstance(manager); return ret; -} \ No newline at end of file +} + +static void GetSignContentInfo(PkgManager::PkgInfoPtr pkgInfo, const UpgradePkgInfoExt *pkgInfoExt) +{ + pkgInfo->signMethod = pkgInfoExt->signMethod; + pkgInfo->digestMethod = pkgInfoExt->digestMethod; + pkgInfo->entryCount = pkgInfoExt->entryCount; + pkgInfo->pkgType = pkgInfoExt->pkgType; + + return; +} + +int32_t CreateSignContent(const UpgradePkgInfoExt *pkgInfoExt, const char *packagePath, + const char *signedPackage, const char *keyPath) +{ + if (pkgInfoExt == nullptr || packagePath == nullptr || signedPackage == nullptr || + keyPath == nullptr) { + LOG(ERROR) << "Check param fail "; + return PKG_INVALID_PARAM; + } + PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance(); + if (manager == nullptr) { + LOG(ERROR) << "Get package instance fail "; + return PKG_INVALID_PARAM; + } + + PkgInfo info; + GetSignContentInfo(&info, pkgInfoExt); + + int32_t ret = manager->CreateSignContent(packagePath, signedPackage, keyPath, &info); + if (ret != PKG_SUCCESS) { + LOG(ERROR) << "Sign Package fail "; + PkgManager::ReleasePackageInstance(manager); + return ret; + } + + PkgManager::ReleasePackageInstance(manager); + return ret; +} + diff --git a/interfaces/kits/updaterkits/updaterkits.cpp b/interfaces/kits/updaterkits/updaterkits.cpp index 227621f56eea5211cd0c3b2acbc576a027af477d..349050bde8f4566e6ed5c9a8572e329af4d0696b 100755 --- a/interfaces/kits/updaterkits/updaterkits.cpp +++ b/interfaces/kits/updaterkits/updaterkits.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ #include "updaterkits/updaterkits.h" + #include #include #include #include #include -#include + +#include "init_reboot.h" #include "misc_info/misc_info.h" #include "parameters.h" #include "securec.h" @@ -37,10 +39,8 @@ static bool WriteToMiscAndRebootToUpdater(const std::string &miscFile, return false; } #ifndef UPDATER_UT - int32_t propertyMaxSize = 92; - char updateCmd[propertyMaxSize]; - void(snprintf_s(updateCmd, propertyMaxSize, propertyMaxSize - 1, "updater:%s", updateMsg.update)); - DoReboot(updateCmd); + WriteUpdaterMiscMsg(updateMsg); + DoReboot("updater"); while (true) { pause(); } diff --git a/services/BUILD.gn b/services/BUILD.gn index a82b38f5aef2a220642ab9e557c4632261c61efd..502c960252536f801377c129b0546af91b05f76f 100755 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -15,47 +15,6 @@ import("//build/ohos.gni") SUBSYSTEM_DIR = "//base/update/updater" -ohos_prebuilt_etc("updater_init.cfg") { - source = "//base/update/updater/services/etc/init.cfg" - install_images = [ "updater" ] - part_name = "updater" -} - -ohos_prebuilt_etc("updater_usb_init.cfg") { - source = "//base/update/updater/services/etc/init.usb.cfg" - install_images = [ "updater" ] - part_name = "updater" -} - -ohos_prebuilt_etc("updater_init_usb_configfs.cfg") { - source = "//base/update/updater/services/etc/init.usb.configfs.cfg" - install_images = [ "updater" ] - part_name = "updater" -} - -ohos_prebuilt_etc("signing_cert.crt") { - source = "//device/board/hisilicon/hispark_taurus/linux/updater/config/signing_cert.crt" - module_install_dir = "certificate" - install_images = [ "updater" ] - part_name = "updater" -} - -ohos_prebuilt_etc("fstab.updater") { - source = "//device/board/hisilicon/hispark_taurus/linux/updater/config/fstab.updater" - install_images = [ "updater" ] - part_name = "updater" -} - -group("updater_etc") { - deps = [ - ":fstab.updater", - ":signing_cert.crt", - ":updater_init.cfg", - ":updater_init_usb_configfs.cfg", - ":updater_usb_init.cfg", - ] -} - ohos_executable("updater") { defines = [ "BUILD_OHOS" ] sources = [ @@ -67,12 +26,14 @@ ohos_executable("updater") { include_dirs = [ "include", - "$SUBSYSTEM_DIR/utils/include", - "$SUBSYSTEM_DIR/interfaces/kits/include", + "${SUBSYSTEM_DIR}/utils/include", + "${SUBSYSTEM_DIR}/interfaces/kits/include/", "//third_party/bounds_checking_function/include", "//base/update/updater/services/include/package", "//base/update/updater/services/package/pkg_manager", + "//base/update/updater/services/package/pkg_verify", "//base/update/updater/services/include/log", + "//base/update/updater/utils/json", "//drivers/framework/ability/sbuf/include", "//drivers/framework/include/platform", "//drivers/framework/include/core", @@ -89,6 +50,8 @@ ohos_executable("updater") { ] deps = [ + "//base/startup/syspara_lite/hals/parameter:sysparam_hal", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", "//base/update/updater/interfaces/kits/packages:libpackageExt", "//base/update/updater/services/applypatch:libapplypatch", @@ -99,8 +62,10 @@ ohos_executable("updater") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/ui:libui", "//base/update/updater/utils:libutils", + "//third_party/bounds_checking_function:libsec_shared", "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", + "//third_party/cJSON:cjson_static", "//third_party/libdrm:libdrm", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", @@ -108,6 +73,17 @@ ohos_executable("updater") { "//third_party/zlib:libz", ] + if (defined(use_ptable)) { + include_dirs += [ "//base/update/updater/services/ptable_parse" ] + deps += [ "//base/update/updater/services/ptable_parse:libptableparse" ] + defines += [ "UPDATER_USE_PTABLE" ] + } + + # add updater custom library + if (defined(updater_custom_lib)) { + deps += updater_custom_lib + } + external_deps = [ "init:libbegetutil" ] install_images = [ "updater" ] install_enable = true diff --git a/services/applypatch/block_set.cpp b/services/applypatch/block_set.cpp index b267cfb72a0f6bb955690fadd313cef42ad6c332..fb1e0448f7b4e8b240143e132e35ffa852442a90 100644 --- a/services/applypatch/block_set.cpp +++ b/services/applypatch/block_set.cpp @@ -324,7 +324,7 @@ int32_t BlockSet::WriteDiffToBlock(const Command &cmd, std::vector &src UPDATER_ERROR_CHECK(writer.get() != nullptr, "Cannot create block writer, pkgdiff patch abort!", return -1); int32_t ret = updatepatch::UpdatePatch::ApplyImagePatch(patchParam, empty, [&](size_t start, const updatepatch::BlockBuffer &data, size_t size) -> int { - bool ret = writer->Write(data.buffer, size, WRITE_BLOCK, ""); + bool ret = writer->Write(data.buffer, size); return ret ? 0 : -1; }, cmd.GetArgumentByPos(pos + 1)); writer.reset(); @@ -336,7 +336,7 @@ int32_t BlockSet::WriteDiffToBlock(const Command &cmd, std::vector &src UPDATER_ERROR_CHECK(writer.get() != nullptr, "Cannot create block writer, pkgdiff patch abort!", return -1); auto ret = updatepatch::UpdatePatch::ApplyBlockPatch(patchInfo, {srcBuffer.data(), srcBuffSize}, [&](size_t start, const updatepatch::BlockBuffer &data, size_t size) -> int { - bool ret = writer->Write(data.buffer, size, WRITE_BLOCK, ""); + bool ret = writer->Write(data.buffer, size); return ret ? 0 : -1; }, cmd.GetArgumentByPos(pos + 1)); writer.reset(); diff --git a/services/applypatch/block_writer.cpp b/services/applypatch/block_writer.cpp index 92eb931971ad069ac78af804338d2f6ae6fa1feb..70ff58abd21a8de28464385bb7d1d03b22b4258f 100644 --- a/services/applypatch/block_writer.cpp +++ b/services/applypatch/block_writer.cpp @@ -35,11 +35,8 @@ size_t BlockWriter::GetTotalWritten() const return totalWritten_; } -bool BlockWriter::Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName) +bool BlockWriter::Write(const uint8_t *addr, size_t len, [[maybe_unused]] const void *context) { - (void)(partitionName); - (void)(mode); - if (IsWriteDone()) { LOG(WARNING) << "BlockWriter: call writer while no more blocks need to write. skip " << len << " byte(s)"; return false; diff --git a/services/applypatch/data_writer.cpp b/services/applypatch/data_writer.cpp index 2cf5616f66550c15bd907b413df7446d8e9286e6..7f77ece491421bd05919873a8176924cec7f1c56 100644 --- a/services/applypatch/data_writer.cpp +++ b/services/applypatch/data_writer.cpp @@ -26,38 +26,34 @@ namespace updater { UpdaterEnv *DataWriter::env_ = nullptr; -int DataWriter::OpenPartition(const std::string &partitionName) +int DataWriter::OpenPath(const std::string &path) { - if (partitionName.empty()) { + if (path.empty()) { LOG(ERROR) << "Datawriter: partition name is empty."; return -1; } - auto devPath = GetBlockDeviceByMountPoint(partitionName); - if (devPath.empty()) { - LOG(ERROR) << "Datawriter: cannot find device path for partition \'" << - partitionName.substr(1, partitionName.size()) << "\'."; - return -1; - } - if (access(devPath.c_str(), W_OK) < 0) { - LOG(ERROR) << "Datawriter: " << devPath << " is not writable."; + if (access(path.c_str(), W_OK) < 0) { + LOG(ERROR) << "Datawriter: " << path << " is not writable."; return -1; } - char *realPath = realpath(devPath.c_str(), NULL); - UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return -1); - int fd = open(realPath, O_WRONLY | O_EXCL); + char realPath[PATH_MAX] = {0x00}; + char *get = realpath(path.c_str(), realPath); + UPDATER_FILE_CHECK(get != nullptr, "realPath is NULL", return -1); + int fd = open(realPath, O_RDWR | O_LARGEFILE); free(realPath); - UPDATER_FILE_CHECK(fd >= 0, "Datawriter: open block device " << devPath << " failed ", return fd); - UPDATER_CHECK_FILE_OP(lseek(fd, 0, SEEK_SET) != -1, "Datawriter: seek " << devPath << "failed ", fd, fd = -1); + UPDATER_FILE_CHECK(fd >= 0, "Datawriter: open block device " << path << " failed ", return fd); + UPDATER_CHECK_FILE_OP(lseek(fd, 0, SEEK_SET) != -1, "Datawriter: seek " << path << "failed ", fd, fd = -1); return fd; } -std::unique_ptr DataWriter::CreateDataWriter(WriteMode mode, const std::string &partitionName) +std::unique_ptr DataWriter::CreateDataWriter(WriteMode mode, const std::string &path, + uint64_t offset) { switch (mode) { case WRITE_RAW: { - std::unique_ptr writer(std::make_unique(partitionName)); + std::unique_ptr writer(std::make_unique(path, offset)); return std::move(writer); } case WRITE_DECRYPT: @@ -74,11 +70,16 @@ UpdaterEnv *DataWriter::GetUpdaterEnv() return env_; } -std::unique_ptr DataWriter::CreateDataWriter(WriteMode mode, const std::string &partitionName, - UpdaterEnv *env) +void DataWriter::SetUpdaterEnv(UpdaterEnv *env) +{ + env_ = env; +} + +std::unique_ptr DataWriter::CreateDataWriter(WriteMode mode, const std::string &path, + UpdaterEnv *env, uint64_t offset) { env_ = env; - return CreateDataWriter(mode, partitionName); + return CreateDataWriter(mode, path, offset); } void DataWriter::ReleaseDataWriter(std::unique_ptr &writer) diff --git a/services/applypatch/partition_record.cpp b/services/applypatch/partition_record.cpp index e6de89be5d0fa02396bba601cada9d8be9a69026..b991bc5650603b9708b5a1b5c81c0937d21186cf 100644 --- a/services/applypatch/partition_record.cpp +++ b/services/applypatch/partition_record.cpp @@ -69,24 +69,24 @@ bool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionNa off_t newOffset = 0; UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) >= 0, "PartitionRecord: Seek misc to record offset failed", fd, return false); - UPDATER_CHECK_FILE_OP(read(fd, &newOffset, sizeof(off_t)) == sizeof(off_t), + UPDATER_CHECK_FILE_OP(read(fd, &newOffset, sizeof(off_t)) == static_cast(sizeof(off_t)), "PartitionRecord: Read offset failed", fd, return false); offset_ = newOffset; UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_START + offset_, SEEK_SET) >= 0, "PartitionRecord: Seek misc to specific offset failed", fd, return false); - if (offset_ + sizeof(PartitionRecordInfo) < PARTITION_UPDATER_RECORD_SIZE) { + if (offset_ + static_cast(sizeof(PartitionRecordInfo)) < PARTITION_UPDATER_RECORD_SIZE) { UPDATER_CHECK_FILE_OP(memset_s(&info_, sizeof(info_), 0, sizeof(info_)) == 0, "PartitionRecord: clear partition info failed", fd, return false); UPDATER_CHECK_FILE_OP(!strncpy_s(info_.partitionName, PARTITION_NAME_LEN, partitionName.c_str(), PARTITION_NAME_LEN - 1), "PartitionRecord: strncpy_s failed", fd, return false); info_.updated = updated; - UPDATER_CHECK_FILE_OP(write(fd, &info_, sizeof(PartitionRecordInfo)) == sizeof(PartitionRecordInfo), - "PartitionRecord: write failed", fd, return false); - offset_ += sizeof(PartitionRecordInfo); + UPDATER_CHECK_FILE_OP(write(fd, &info_, sizeof(PartitionRecordInfo)) == + static_cast(sizeof(PartitionRecordInfo)), "PartitionRecord: write failed", fd, return false); + offset_ += static_cast(sizeof(PartitionRecordInfo)); UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) >= 0, "PartitionRecord: Seek misc to record offset failed", fd, return false); - UPDATER_CHECK_FILE_OP(write(fd, &offset_, sizeof(off_t)) == sizeof(off_t), + UPDATER_CHECK_FILE_OP(write(fd, &offset_, sizeof(off_t)) == static_cast(sizeof(off_t)), "PartitionRecord: write misc to record offset failed", fd, return false); LOG(DEBUG) << "PartitionRecord: offset is " << offset_; } else { @@ -111,7 +111,7 @@ bool PartitionRecord::ClearRecordPartitionOffset() "Seek misc to specific offset failed", fd, return false); off_t initOffset = 0; - UPDATER_CHECK_FILE_OP(write(fd, &initOffset, sizeof(off_t)) == sizeof(off_t), + UPDATER_CHECK_FILE_OP(write(fd, &initOffset, sizeof(off_t)) == static_cast(sizeof(off_t)), "StartUpdater: Write misc initOffset 0 failed", fd, return false); fsync(fd); close(fd); diff --git a/services/applypatch/raw_writer.cpp b/services/applypatch/raw_writer.cpp index 0e30d6ceccc3caa14a96d0a81d4f947573f8ec84..a2f8ed0ddc6177fa39351a612ff85d6ea126d98e 100644 --- a/services/applypatch/raw_writer.cpp +++ b/services/applypatch/raw_writer.cpp @@ -20,7 +20,7 @@ #include "log/log.h" namespace updater { -bool RawWriter::Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName) +bool RawWriter::Write(const uint8_t *addr, size_t len, [[maybe_unused]] const void *context) { if (addr == nullptr) { LOG(ERROR) << "RawWriter: invalid address."; @@ -33,7 +33,7 @@ bool RawWriter::Write(const uint8_t *addr, size_t len, WriteMode mode, const std } if (fd_ < 0) { - fd_ = OpenPartition(partitionName_); + fd_ = OpenPath(path_); if (fd_ < 0) { return false; } @@ -55,9 +55,9 @@ int RawWriter::WriteInternal(int fd, const uint8_t *data, size_t len) written = write(fd, data, rest); UPDATER_FILE_CHECK(written >= 0, "RawWriter: failed to write data of len " << len, return -1); data += written; - rest -= written; + rest -= static_cast(written); } - offset_ += len; + offset_ += static_cast(len); return 0; } } // namespace updater diff --git a/services/applypatch/raw_writer.h b/services/applypatch/raw_writer.h index 8427e39491301dade3f4496983503e461218e235..71ebca16e42eba5716a93c5c2ae14a2442eb3580 100644 --- a/services/applypatch/raw_writer.h +++ b/services/applypatch/raw_writer.h @@ -25,9 +25,9 @@ namespace updater { class RawWriter : public DataWriter { public: - virtual bool Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName); + bool Write(const uint8_t *addr, size_t len, const void *context = nullptr) override; - explicit RawWriter(const std::string partitionName) : offset_(0), fd_(-1), partitionName_(partitionName) {} + explicit RawWriter(const std::string path, uint64_t offset) : fd_(-1), path_(path), offset_(offset) {} virtual ~RawWriter() { @@ -44,9 +44,9 @@ private: RawWriter(const RawWriter&) = delete; const RawWriter& operator=(const RawWriter&) = delete; - off64_t offset_; int fd_; - std::string partitionName_; + std::string path_; + off64_t offset_; }; } // namespace updater #endif /* UPDATER_RAW_WRITER_H */ diff --git a/services/applypatch/store.cpp b/services/applypatch/store.cpp index d436ec539740490952554b5e85b7f5f98f060c52..937a521df5797636d5da20a02d732944ee80f28e 100644 --- a/services/applypatch/store.cpp +++ b/services/applypatch/store.cpp @@ -95,7 +95,7 @@ int32_t Store::WriteDataToStore(const std::string &dirPath, const std::string &f UPDATER_ERROR_CHECK(fchown(fd, O_USER_GROUP_ID, O_USER_GROUP_ID) == 0, "Failed to chown", close(fd); return -1); LOG(INFO) << "Writing " << size << " blocks to " << path; - if (!WriteFully(fd, const_cast(buffer.data()), size)) { + if (size < 0 || !WriteFully(fd, const_cast(buffer.data()), static_cast(size))) { UPDATER_CHECK_ONLY_RETURN(errno != EIO, close(fd); return 1); LOG(ERROR) << "Write to stash failed"; close(fd); diff --git a/services/applypatch/transfer_manager.cpp b/services/applypatch/transfer_manager.cpp index f2281560815dbe6222e4beafd35b3bade0b040d2..a946b4c138136bbce0cb1297f3558a02e529716c 100644 --- a/services/applypatch/transfer_manager.cpp +++ b/services/applypatch/transfer_manager.cpp @@ -53,6 +53,7 @@ TransferManager::~TransferManager() bool TransferManager::CommandsParser(int fd, const std::vector &context) { UPDATER_ERROR_CHECK(context.size() >= 1, "too small context in transfer file", return false); + UPDATER_ERROR_CHECK(globalParams != nullptr, "globalParams is nullptr", return false); std::vector::const_iterator ct = context.begin(); globalParams->version = utils::String2Int(*ct++, utils::N_DEC); globalParams->blockCount = utils::String2Int(*ct++, utils::N_DEC); @@ -60,15 +61,15 @@ bool TransferManager::CommandsParser(int fd, const std::vector &con globalParams->maxBlocks = utils::String2Int(*ct++, utils::N_DEC); size_t totalSize = globalParams->blockCount; std::string retryCmd = ""; - if (globalParams != nullptr && globalParams->env != nullptr && globalParams->env->IsRetry()) { + if (globalParams->env != nullptr && globalParams->env->IsRetry()) { retryCmd = ReloadForRetry(); } std::unique_ptr cmd; - int initBlock = 0; + size_t initBlock = 0; while (ct != context.end()) { cmd = std::make_unique(); UPDATER_ERROR_CHECK(cmd != nullptr, "Failed to parse command line.", return false); - if (cmd->Init(*ct) && cmd->GetCommandType() != CommandType::LAST) { + if (cmd->Init(*ct) && cmd->GetCommandType() != CommandType::LAST && globalParams->env != nullptr) { if (!retryCmd.empty() && globalParams->env->IsRetry()) { if (*ct == retryCmd) { retryCmd.clear(); @@ -93,7 +94,7 @@ bool TransferManager::CommandsParser(int fd, const std::vector &con } if (totalSize != 0 && globalParams->env != nullptr && NeedSetProgress(cmd->GetCommandType())) { globalParams->env->PostMessage("set_progress", - std::to_string((float)(globalParams->written - initBlock) / totalSize)); + std::to_string((static_cast(globalParams->written) - initBlock) / totalSize)); } LOG(INFO) << "Running command : " << cmd->GetArgumentByPos(0) << " success"; } diff --git a/services/diffpatch/bzip2/bzip2_adapter.cpp b/services/diffpatch/bzip2/bzip2_adapter.cpp index 509f3eacffea9b714661714d64041cdfaa1349c4..39ce9b1c4bc23da7aa21dcba6c487843b86df64b 100644 --- a/services/diffpatch/bzip2/bzip2_adapter.cpp +++ b/services/diffpatch/bzip2/bzip2_adapter.cpp @@ -23,7 +23,7 @@ using namespace hpackage; namespace updatepatch { int32_t BZip2Adapter::Open() { - memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream)); + (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream)); int32_t ret = BZ2_bzCompressInit(&stream_, BLOCK_SIZE_BEST, 0, 0); PATCH_CHECK(ret == BZ_OK, return ret, "Failed to bzcompressinit %d", ret); init_ = true; diff --git a/services/diffpatch/bzip2/deflate_adapter.h b/services/diffpatch/bzip2/deflate_adapter.h index dba4b91dd9bf3942cf999f7cfab6e91c7b4712f7..06a17d1cbb85330205d5f2622bd47cfb016734b6 100644 --- a/services/diffpatch/bzip2/deflate_adapter.h +++ b/services/diffpatch/bzip2/deflate_adapter.h @@ -44,6 +44,7 @@ public: { return 0; }; + protected: bool init_ = false; }; diff --git a/services/diffpatch/bzip2/lz4_adapter.cpp b/services/diffpatch/bzip2/lz4_adapter.cpp index 6f59e8a229deb457d3e742e5f70d160f27083fce..24b23a5bb02ecec5ade8b0cc13cfd036e142b07d 100644 --- a/services/diffpatch/bzip2/lz4_adapter.cpp +++ b/services/diffpatch/bzip2/lz4_adapter.cpp @@ -49,7 +49,7 @@ int32_t Lz4FrameAdapter::Open() PATCH_CHECK(!LZ4F_isError(errorCode), return -1, "Failed to create compress context %s", LZ4F_getErrorName(errorCode)); PATCH_CHECK(!memset_s(&preferences, sizeof(preferences), 0, sizeof(preferences)), return -1, "Memset failed"); - preferences.autoFlush = autoFlush_; + preferences.autoFlush = static_cast(autoFlush_); preferences.compressionLevel = compressionLevel_; preferences.frameInfo.blockMode = ((blockIndependence_ == 0) ? LZ4F_blockLinked : LZ4F_blockIndependent); preferences.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID_; @@ -167,8 +167,9 @@ int32_t Lz4BlockAdapter::Open() blockSize, LZ4_BLOCK_SIZE(blockSizeID_), LZ4B_BLOCK_SIZE); /* write package */ - size_t bufferSize = LZ4_compressBound(LZ4_BLOCK_SIZE(blockSizeID_)); - buffer_.resize(bufferSize); + int bufferSize = LZ4_compressBound(LZ4_BLOCK_SIZE(blockSizeID_)); + PATCH_CHECK(bufferSize >= 0, return -1, "Buffer size should >= 0"); + buffer_.resize(static_cast(bufferSize)); int32_t ret = memcpy_s(buffer_.data(), buffer_.size(), &LZ4B_MAGIC_NUMBER, sizeof(int32_t)); PATCH_CHECK(ret == 0, return -1, "Failed to memcpy "); ret = outStream_->Write(offset_, {buffer_.data(), sizeof(int32_t)}, sizeof(int32_t)); diff --git a/services/diffpatch/diff/blocks_diff.cpp b/services/diffpatch/diff/blocks_diff.cpp index 2a68f28cf9f3cbbcedebd5c2721b093814a7c66a..ac28d464df17819baa79b30bc2bf31fc960253b2 100644 --- a/services/diffpatch/diff/blocks_diff.cpp +++ b/services/diffpatch/diff/blocks_diff.cpp @@ -26,7 +26,7 @@ namespace updatepatch { #define SWAP(a, b) auto swapTmp = (a); (a) = (b); (b) = swapTmp #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define SET_BUFFER(y, buffer, index) \ - (buffer)[index] = (y) % 256; (y) -= (buffer)[index]; (y) = (y) / 256 + (buffer)[index] = static_cast((y) % 256); (y) -= (buffer)[index]; (y) = (y) / 256 constexpr uint32_t BUCKET_SIZE = 256; constexpr uint32_t MULTIPLE_TWO = 2; @@ -36,7 +36,7 @@ constexpr int64_t MIN_LENGTH = 16; static void WriteLE64(const BlockBuffer &buffer, int64_t value) { int32_t index = 0; - int64_t y = (value < 0) ? -value : value; + auto y = static_cast((value < 0) ? -value : value); SET_BUFFER(y, buffer.buffer, index); index++; SET_BUFFER(y, buffer.buffer, index); @@ -237,7 +237,7 @@ void BlocksDiff::ComputeLength(const BlockBuffer &newInfo, int64_t i = 0; int64_t s = 0; int64_t tmp = 0; - for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length));) { + while (((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length))) { if (oldInfo.buffer[lastPos_ + i] == newInfo.buffer[lastScan_ + i]) { s++; } @@ -413,7 +413,8 @@ void SuffixArray::Init(const BlockBuffer &oldInfo) DataType len = 0; for (h = 1; suffixArray_[0] != -(static_cast(oldInfo.length) + 1); h += h) { len = 0; - for (i = 0; i < (static_cast(oldInfo.length) + 1);) { + i = 0; + while (i < (static_cast(oldInfo.length) + 1)) { if (suffixArray_[i] < 0) { len -= suffixArray_[i]; i -= suffixArray_[i]; diff --git a/services/diffpatch/diff/blocks_diff.h b/services/diffpatch/diff/blocks_diff.h index 5dd76fa949cf8e203429ca837ef48c9d33804119..5945c31d033d88c9a0591cada5e48a058e4a653f 100644 --- a/services/diffpatch/diff/blocks_diff.h +++ b/services/diffpatch/diff/blocks_diff.h @@ -57,6 +57,7 @@ public: const BlockBuffer &oldInfo, std::fstream &patchFile, size_t &patchSize); int32_t MakePatch(const BlockBuffer &newInfo, const BlockBuffer &oldInfo, size_t &patchSize); + private: virtual std::unique_ptr CreateBZip2Adapter(size_t patchOffset) = 0; virtual int32_t WritePatchHeader(int64_t controlSize, @@ -86,10 +87,11 @@ class BlocksStreamDiff : public BlocksDiff { public: BlocksStreamDiff(std::fstream &stream, size_t offset) : BlocksDiff(), stream_(stream), offset_(offset) {} ~BlocksStreamDiff() override {} + private: std::unique_ptr CreateBZip2Adapter(size_t patchOffset) override; int32_t WritePatchHeader(int64_t controlSize, - int64_t diffDataSize, int64_t newSize, size_t &headerLen) override; + int64_t diffDataSize, int64_t newSize, size_t &patchOffset) override; std::fstream &stream_; size_t offset_ { 0 }; }; @@ -99,10 +101,11 @@ public: BlocksBufferDiff(std::vector &patchData, size_t offset) : BlocksDiff(), patchData_(patchData), offset_(offset) {} ~BlocksBufferDiff() override {} + private: std::unique_ptr CreateBZip2Adapter(size_t patchOffset) override; int32_t WritePatchHeader(int64_t controlSize, - int64_t diffDataSize, int64_t newSize, size_t &headerLen) override; + int64_t diffDataSize, int64_t newSize, size_t &patchOffset) override; std::vector &patchData_; size_t offset_ { 0 }; }; diff --git a/services/diffpatch/diff/image_diff.cpp b/services/diffpatch/diff/image_diff.cpp index bbc7277a95001027f9ad25a19c1027dba37f50a1..a282c22a927c7500fdf12120c6518b66947193e9 100644 --- a/services/diffpatch/diff/image_diff.cpp +++ b/services/diffpatch/diff/image_diff.cpp @@ -452,7 +452,7 @@ int32_t Lz4ImageDiff::TestAndSetConfig(const BlockBuffer &buffer, const std::str const FileInfo *fileInfo = newParser_->GetFileInfo(fileName); PATCH_CHECK(fileInfo != nullptr, return -1, "Failed to get file info"); Lz4FileInfo *info = (Lz4FileInfo *)fileInfo; - method_ = info->fileInfo.packMethod; + method_ = static_cast(info->fileInfo.packMethod); compressionLevel_ = info->compressionLevel; blockIndependence_ = info->blockIndependence; contentChecksumFlag_ = info->contentChecksumFlag; diff --git a/services/diffpatch/diff/image_diff.h b/services/diffpatch/diff/image_diff.h index 965249e7af5ecaad95924f468d5cbb9b72ef14f2..2f75d6fd18559424eeb4675fac9c7bf9695ef207 100644 --- a/services/diffpatch/diff/image_diff.h +++ b/services/diffpatch/diff/image_diff.h @@ -46,6 +46,7 @@ public: virtual int32_t MakePatch(const std::string &patchName); virtual int32_t WriteHeader(std::ofstream &patchFile, std::fstream &blockPatchFile, size_t &offset, ImageBlock &block) const; + protected: int32_t SplitImage(const PatchBuffer &oldInfo, const PatchBuffer &newInfo); int32_t DiffImage(const std::string &patchName); @@ -68,6 +69,7 @@ public: ~CompressedImageDiff() override {} int32_t MakePatch(const std::string &patchName) override; + protected: virtual int32_t TestAndSetConfig(const BlockBuffer &buffer, const std::string &fileName) = 0; int32_t DiffFile(const std::string &fileName, size_t &oldOffset, size_t &newOffset); @@ -84,6 +86,7 @@ public: int32_t WriteHeader(std::ofstream &patchFile, std::fstream &blockPatchFile, size_t &offset, ImageBlock &block) const override; + protected: int32_t TestAndSetConfig(const BlockBuffer &buffer, const std::string &fileName) override; @@ -102,8 +105,10 @@ public: int32_t WriteHeader(std::ofstream &patchFile, std::fstream &blockPatchFile, size_t &offset, ImageBlock &block) const override; + protected: int32_t TestAndSetConfig(const BlockBuffer &buffer, const std::string &fileName) override; + private: int32_t method_ {0}; int32_t compressionLevel_ {0}; diff --git a/services/diffpatch/diffpatch.cpp b/services/diffpatch/diffpatch.cpp index 36b48f5cf7e7cd1fc16c9ab380c51c84f0857e67..ead9f17312b005972268914415ef96ec08da67c0 100644 --- a/services/diffpatch/diffpatch.cpp +++ b/services/diffpatch/diffpatch.cpp @@ -34,7 +34,10 @@ int32_t WriteDataToFile(const std::string &fileName, const std::vector int32_t PatchMapFile(const std::string &fileName, MemMapInfo &info) { - int32_t file = open(fileName.c_str(), O_RDONLY); + char realPath[PATH_MAX] = {0x00}; + char *get = realpath(fileName.c_str(), realPath); + PATCH_CHECK(get != nullptr, return -1, "Failed to get realpath %s", fileName.c_str()); + int32_t file = open(realPath, O_RDONLY); PATCH_CHECK(file >= 0, return -1, "Failed to open file %s", fileName.c_str()); struct stat st {}; int32_t ret = fstat(file, &st); @@ -42,7 +45,7 @@ int32_t PatchMapFile(const std::string &fileName, MemMapInfo &info) info.memory = static_cast(mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, file, 0)); PATCH_CHECK(info.memory != nullptr, close(file); return -1, "Failed to memory map"); - info.length = st.st_size; + info.length = static_cast(st.st_size); close(file); return PATCH_SUCCESS; } diff --git a/services/diffpatch/patch/blocks_patch.cpp b/services/diffpatch/patch/blocks_patch.cpp index ec60d1495a197f85bd714ed883e8b5c147d8007a..096053f87442647d085d7fe9bd3e2c26136b9345 100644 --- a/services/diffpatch/patch/blocks_patch.cpp +++ b/services/diffpatch/patch/blocks_patch.cpp @@ -34,7 +34,7 @@ static int64_t ReadLE64(const uint8_t *buffer) } int64_t y = 0; int32_t index = static_cast(sizeof(int64_t)) - 1; - y = buffer[index] & (~BUFFER_MASK); + y = buffer[index] & static_cast(~BUFFER_MASK); index--; GET_BYTE_FROM_BUFFER(y, index, buffer); index--; @@ -94,7 +94,7 @@ int32_t BlocksPatch::ApplyPatch() int32_t BlocksPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize) { - PATCH_LOGI("BlocksPatch::ApplyPatch %p %zu %zu", patchInfo_.buffer, patchInfo_.start, patchInfo_.length); + PATCH_LOGI("BlocksPatch::ApplyPatch %zu %zu", patchInfo_.start, patchInfo_.length); PATCH_CHECK(patchInfo_.buffer != nullptr && patchInfo_.length > PATCH_MIN, return -1, "Invalid parm"); BlockBuffer patchData = {patchInfo_.buffer + patchInfo_.start, patchInfo_.length - patchInfo_.start}; PATCH_LOGI("Restore patch hash %zu %s", @@ -120,9 +120,9 @@ int32_t BlocksPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, BlockBuffer patchBuffer = {header, patchInfo_.length - patchInfo_.start}; controlDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast(controlDataSize), patchBuffer)); - offset += controlDataSize; + offset += static_cast(controlDataSize); diffDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast(diffDataSize), patchBuffer)); - offset += diffDataSize; + offset += static_cast(diffDataSize); extraDataReader_.reset(new BZip2BufferReadAdapter(offset, patchInfo_.length - patchInfo_.start - offset, patchBuffer)); PATCH_CHECK(controlDataReader_ != nullptr && diffDataReader_ != nullptr && extraDataReader_ != nullptr, @@ -196,7 +196,7 @@ int32_t BlocksStreamPatch::RestoreDiffData(const ControlData &ctrlData) int32_t ret = diffDataReader_->ReadData(diffBuffer); PATCH_CHECK(ret == 0, return ret, "Failed to read diff data"); - size_t oldOffset = oldOffset_; + size_t oldOffset = static_cast(oldOffset_); size_t oldLength = stream_->GetFileLength(); PkgBuffer buffer {}; if (stream_->GetStreamType() == PkgStream::PkgStreamType_MemoryMap || @@ -213,7 +213,7 @@ int32_t BlocksStreamPatch::RestoreDiffData(const ControlData &ctrlData) } for (int64_t i = 0; i < ctrlData.diffLength; i++) { if ((oldOffset_ + i >= 0) && (static_cast(oldOffset_ + i) < oldLength)) { - diffData[i] += buffer.buffer[oldOffset + i]; + diffData[i] += buffer.buffer[static_cast(oldOffset) + i]; } } // write diff --git a/services/diffpatch/patch/image_patch.cpp b/services/diffpatch/patch/image_patch.cpp index e7357344c56d4bc131415326c08a86d1d24b18e2..503d03a36875ab5269cc9d55345570ffc3efe53d 100644 --- a/services/diffpatch/patch/image_patch.cpp +++ b/services/diffpatch/patch/image_patch.cpp @@ -232,11 +232,11 @@ std::unique_ptr Lz4ImagePatch::GetFileInfo() const fileInfo->fileInfo.packedSize = 0; fileInfo->fileInfo.unpackedSize = 0; fileInfo->fileInfo.identity = std::to_string(g_tmpFileId++); - fileInfo->compressionLevel = static_cast(compressionLevel_); - fileInfo->blockIndependence = static_cast(blockIndependence_); - fileInfo->contentChecksumFlag = static_cast(contentChecksumFlag_); - fileInfo->blockSizeID = static_cast(blockSizeID_); - fileInfo->autoFlush = static_cast(autoFlush_); + fileInfo->compressionLevel = static_cast(compressionLevel_); + fileInfo->blockIndependence = static_cast(blockIndependence_); + fileInfo->contentChecksumFlag = static_cast(contentChecksumFlag_); + fileInfo->blockSizeID = static_cast(blockSizeID_); + fileInfo->autoFlush = static_cast(autoFlush_); return std::unique_ptr((FileInfo *)fileInfo); } diff --git a/services/diffpatch/patch/image_patch.h b/services/diffpatch/patch/image_patch.h index d0b0a771bb34158ab8e3e0b5477a329c67e00c67..e9cb17cbfee984d4793410efb8236266e8c0d455 100644 --- a/services/diffpatch/patch/image_patch.h +++ b/services/diffpatch/patch/image_patch.h @@ -35,7 +35,11 @@ public: static T ReadLE(const uint8_t *address) { T result; - memcpy_s(&result, sizeof(result), address, sizeof(T)); + errno_t ret = memcpy_s(&result, sizeof(result), address, sizeof(T)); + if (ret != EOK) { + // only warning no need to return invalid value + PATCH_LOGE("Failed to memcpy"); + } return result; } protected: diff --git a/services/fs_manager/do_partition.cpp b/services/fs_manager/do_partition.cpp index d0f98adc7d2baf38e0b7f78918a0e1f57796a9e0..18eed38d584f159180d55d41d91ac41d8fccf290 100644 --- a/services/fs_manager/do_partition.cpp +++ b/services/fs_manager/do_partition.cpp @@ -40,7 +40,7 @@ static int BlkpgPartCommand(const Partition &part, struct blkpg_partition &pg, i struct blkpg_ioctl_arg args {}; args.op = op; args.flags = 0; - args.datalen = sizeof(struct blkpg_partition); + args.datalen = static_cast(sizeof(struct blkpg_partition)); args.data = static_cast(&pg); int ret = 0; @@ -84,7 +84,7 @@ static int BlockSync(const Disk &disk) static int BlkpgRemovePartition(const Partition &part) { struct blkpg_partition blkPart {}; - UPDATER_CHECK_ONLY_RETURN(memset_s(&blkPart, sizeof(blkPart), 0, sizeof(blkPart))==0, return -1); + UPDATER_CHECK_ONLY_RETURN(memset_s(&blkPart, sizeof(blkPart), 0, sizeof(blkPart)) == 0, return -1); blkPart.pno = part.partNum; return BlkpgPartCommand(part, blkPart, BLKPG_DEL_PARTITION); } @@ -124,9 +124,9 @@ static int BlkpgAddPartition(Partition &part) { struct blkpg_partition blkPart {}; UPDATER_CHECK_ONLY_RETURN(!memset_s(&blkPart, sizeof(blkPart), 0, sizeof(blkPart)), return 0); - blkPart.start = part.start * SECTOR_SIZE_DEFAULT; + blkPart.start = static_cast(part.start * SECTOR_SIZE_DEFAULT); LOG(INFO) << "blkPart.start " << blkPart.start; - blkPart.length = part.length * SECTOR_SIZE_DEFAULT; + blkPart.length = static_cast(part.length * SECTOR_SIZE_DEFAULT); LOG(INFO) << "blkPart.length " << blkPart.length; blkPart.pno = part.partNum; LOG(INFO) << "blkPart.pno " << blkPart.pno; @@ -175,7 +175,7 @@ static void DestroyDiskDevices(const Disk &disk) static bool WriteDiskPartitionToMisc(PartitonList &nlist) { - UPDATER_CHECK_ONLY_RETURN(nlist.empty()==0, return false); + UPDATER_CHECK_ONLY_RETURN(nlist.empty() == 0, return false); char blkdevparts[MISC_RECORD_UPDATE_PARTITIONS_SIZE] = "mmcblk0:"; std::sort(nlist.begin(), nlist.end(), [](const struct Partition *a, const struct Partition *b) { return (a->start < b->start); diff --git a/services/fs_manager/mount.cpp b/services/fs_manager/mount.cpp index 0a71611fd7b56546b29e177a9c16d9c511e611a0..cf53bab420269f1ac840acb8f2676bee8c48b125 100644 --- a/services/fs_manager/mount.cpp +++ b/services/fs_manager/mount.cpp @@ -28,7 +28,9 @@ namespace updater { using updater::utils::SplitString; static std::string g_defaultUpdaterFstab = ""; -static Fstab *g_fstab; +static Fstab *g_fstab = nullptr; +static const std::string PARTITION_PATH = "/dev/block/by-name"; + static std::string GetFstabFile() { /* check vendor fstab files from specific directory */ @@ -156,7 +158,7 @@ int FormatPartition(const std::string &path) return ((ret != 0) ? -1 : 0); } -int SetupPartitions() +int SetupPartitions(PackageUpdateMode mode) { if (g_fstab == NULL || g_fstab->head == NULL) { LOG(ERROR) << "Fstab is invalid"; @@ -170,7 +172,7 @@ int SetupPartitions() continue; } - if (mountPoint == "/data") { + if (mountPoint == "/data" && mode != SDCARD_UPDATE) { if (MountForPath(mountPoint) != 0) { LOG(ERROR) << "Expected partition " << mountPoint << " is not mounted."; return -1; @@ -187,8 +189,12 @@ int SetupPartitions() const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint) { - std::string blockDevice = ""; - if (!mountPoint.empty()) { + if (mountPoint.empty()) { + LOG(ERROR) << "mountPoint empty error."; + return ""; + } + std::string blockDevice = PARTITION_PATH + mountPoint; + if (g_fstab != nullptr) { FstabItem *item = FindFstabItemForMountPoint(*g_fstab, mountPoint.c_str()); if (item != NULL) { blockDevice = item->deviceName; diff --git a/services/fs_manager/partitions.cpp b/services/fs_manager/partitions.cpp index f965b7ee28060271cddbaa67365aa6e6d7287929..adb7d57eefd5d0b55bc95d5aa99d5911ca71864d 100644 --- a/services/fs_manager/partitions.cpp +++ b/services/fs_manager/partitions.cpp @@ -48,8 +48,10 @@ static int DeviceProbeType(BlockDevice &dev) UPDATER_CHECK_ONLY_RETURN(DeviceStat(dev, devStat), return 0); - specific->major = devMajor = major (devStat.st_rdev); - specific->minor = devMinor = minor (devStat.st_rdev); + devMajor = static_cast(major (devStat.st_rdev)); + specific->major = devMajor; + devMinor = static_cast(minor (devStat.st_rdev)); + specific->minor = devMinor; bool a1 = SCSI_BLK_MAJOR(devMajor) && (devMinor % 0x10 == 0); bool a2 = devMajor == SDMMC_MAJOR && (devMinor % 0x08 == 0); UPDATER_CHECK_ONLY_RETURN(!a1, dev.type = DEVICE_SCSI); @@ -290,10 +292,10 @@ static struct Partition* NewPartition(const BlockDevice &dev, int partn) free(part); return nullptr; } - part->start = atoi(strstart.c_str()); + part->start = static_cast(atoi(strstart.c_str())); std::string strsize = ReadPartitionFromSys(devName, partName, "size", ""); UPDATER_CHECK_ONLY_RETURN(!strsize.empty(), free(part); return nullptr); - part->length = atoi(strsize.c_str()); + part->length = static_cast(atoi(strsize.c_str())); std::string strdevname = ReadPartitionFromSys(devName, partName, "uevent", "DEVNAME="); part->devName = partName; diff --git a/services/include/applypatch/block_set.h b/services/include/applypatch/block_set.h index 34f89b964a537256dfbb50d03bf1e3229e88d0dc..308a6f8e57b2ed10bae037ed71c767116a4b7afd 100644 --- a/services/include/applypatch/block_set.h +++ b/services/include/applypatch/block_set.h @@ -97,9 +97,11 @@ public: // write data to block size_t WriteDataToBlock(int fd, std::vector &buffer); + protected: size_t blockSize_; std::vector blocks_; + private: void PushBack(BlockPair block_pair); void ClearBlocks(); diff --git a/services/include/applypatch/block_writer.h b/services/include/applypatch/block_writer.h index ae9de3dd1fd0cc39df9d2e1e486da6ab378ba12e..d4c02d15169a450fed7cdd77617900d2a18feb21 100644 --- a/services/include/applypatch/block_writer.h +++ b/services/include/applypatch/block_writer.h @@ -24,7 +24,7 @@ namespace updater { class BlockWriter : public DataWriter { public: - virtual bool Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName); + bool Write(const uint8_t *addr, size_t len, const void *context = nullptr) override; virtual ~BlockWriter() {} BlockWriter(int fd, BlockSet& bs) : fd_(fd), bs_(bs), totalWritten_(0), blockIndex_(0), currentBlockLeft_(0) {} diff --git a/services/include/applypatch/command.h b/services/include/applypatch/command.h index 505be6e0d4cfd3f23fe7f6c2f8309a00a53b7f16..c68311a9d9bc5abe073106308244be6d057d3d9e 100644 --- a/services/include/applypatch/command.h +++ b/services/include/applypatch/command.h @@ -58,10 +58,10 @@ public: private: CommandType ParseCommandType(const std::string &first_cmd); - CommandType type_; - std::string cmdLine_; - std::vector tokens_; - std::unique_ptr fd_; + CommandType type_ {LAST}; + std::string cmdLine_ {}; + std::vector tokens_ {}; + std::unique_ptr fd_ {}; }; } // namespace updater #endif diff --git a/services/include/applypatch/data_writer.h b/services/include/applypatch/data_writer.h index 924387f41b60413fe8bb461c35cd7fd7f577afcb..43db48a77dbfcbe61fbe2898af7e38cdb7cc77c3 100644 --- a/services/include/applypatch/data_writer.h +++ b/services/include/applypatch/data_writer.h @@ -24,23 +24,26 @@ namespace updater { enum WriteMode : int { - WRITE_SPARSE = 1, - WRITE_RAW = 2, - WRITE_DECRYPT = 3, - WRITE_BLOCK = 4, + WRITE_RAW = 1, + WRITE_DECRYPT = 2, + WRITE_BLOCK = 3, }; class DataWriter { public: using DataWriterPtr = DataWriter *; - virtual bool Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName) = 0; - virtual int OpenPartition(const std::string &partitionName); + virtual bool Write(const uint8_t *addr, size_t len, const void *context = nullptr) = 0; virtual ~DataWriter() {} - static std::unique_ptr CreateDataWriter(WriteMode mode, const std::string &partitionName, - UpdaterEnv *env); - static std::unique_ptr CreateDataWriter(WriteMode mode, const std::string &partitionName); + static std::unique_ptr CreateDataWriter(WriteMode mode, const std::string &path, UpdaterEnv *env, + uint64_t offset = 0); + static std::unique_ptr CreateDataWriter(WriteMode mode, const std::string &path, uint64_t offset = 0); static UpdaterEnv *GetUpdaterEnv(); + void SetUpdaterEnv(UpdaterEnv *env); static void ReleaseDataWriter(std::unique_ptr &writer); + +protected: + virtual int OpenPath(const std::string &path); + private: static UpdaterEnv *env_; }; diff --git a/services/include/applypatch/partition_record.h b/services/include/applypatch/partition_record.h index 962d43f4aaf2f5ce20976691409361d8ee30cb77..d95243f5318c533618be3dab593d3f588ff1043b 100644 --- a/services/include/applypatch/partition_record.h +++ b/services/include/applypatch/partition_record.h @@ -58,6 +58,7 @@ public: bool RecordPartitionUpdateStatus(const std::string &partitionName, bool status); bool ClearRecordPartitionOffset(); + private: PartitionRecord() { @@ -65,6 +66,7 @@ private: } ~PartitionRecord() {} + private: std::string GetMiscPartitionPath(const std::string &mountPoint = "/misc"); diff --git a/services/include/fs_manager/mount.h b/services/include/fs_manager/mount.h index 744a8d1363015abd1f9d0f06fb9d1c047187ccfe..e5a7ba6c4095886c1472e7185facdaecc52f583f 100644 --- a/services/include/fs_manager/mount.h +++ b/services/include/fs_manager/mount.h @@ -17,6 +17,7 @@ #include #include "fs_manager/fs_manager.h" +#include "updater/updater.h" namespace updater { void LoadFstab(); /* Load fstab */ @@ -24,7 +25,7 @@ void LoadSpecificFstab(const std::string &fstabName); int FormatPartition(const std::string &path); int UmountForPath(const std::string &path); int MountForPath(const std::string &path); -int SetupPartitions(); +int SetupPartitions(PackageUpdateMode mode = HOTA_UPDATE); const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint); MountStatus GetMountStatusForPath(const std::string &path); } // updater diff --git a/services/include/log/log.h b/services/include/log/log.h index 13955819be5c7aaf640e63d237d713087008766c..65e289d09ae7e10e1c479ee34c2bb9affc5c65dc 100644 --- a/services/include/log/log.h +++ b/services/include/log/log.h @@ -122,7 +122,7 @@ private: class StageLogger { public: - StageLogger(int stage) : stage_(stage) { } + StageLogger(int stage) : stage_(stage) {} ~StageLogger(); @@ -133,9 +133,9 @@ private: class ErrorCode { public: - ErrorCode(enum UpdaterErrorCode level) {} + ErrorCode(enum UpdaterErrorCode level) {} - ~ErrorCode() {}; + ~ErrorCode() {} std::ostream& OutputErrorCode(const std::string &path, int line, UpdaterErrorCode code); }; diff --git a/services/include/package/packages_info.h b/services/include/package/packages_info.h index eefa42798d45c25a0151b8cdb9607d8a9f39b2f2..2216ac4b57857446c1188fe36d82bc9de4bc5da3 100644 --- a/services/include/package/packages_info.h +++ b/services/include/package/packages_info.h @@ -32,7 +32,7 @@ class PackagesInfo; using PackagesInfoPtr = PackagesInfo *; class PackagesInfo { public: - ~PackagesInfo() {}; + ~PackagesInfo() {} static PackagesInfoPtr GetPackagesInfoInstance(); @@ -57,15 +57,16 @@ public: const std::string &boardListPath); /** - * Gets information about files in the package. For an update package, + * Gets information about files in the package. For an update package, * you can convert the information into updater information for viewing. * * @param fileId file ID * @return information about files in the package */ bool IsAllowRollback(); + private: - PackagesInfo() {}; + PackagesInfo() {} }; } #endif // PACKAGESINFO_H \ No newline at end of file diff --git a/services/include/package/pkg_manager.h b/services/include/package/pkg_manager.h index e70c9d8dbeafdf1f0b38c50c554d6fb12efb65d6..016b48efe1adbc11af08ecce6a49e5dcf20c954e 100644 --- a/services/include/package/pkg_manager.h +++ b/services/include/package/pkg_manager.h @@ -270,6 +270,11 @@ public: virtual int32_t LoadPackage(const std::string &packagePath, const std::string &keyPath, std::vector &fileIds) = 0; + virtual int32_t CreateSignContent(const std::string &packagePath, const std::string &signedPackage, + const std::string &keyPath, PkgInfoPtr header) = 0; + + virtual int32_t VerifyOtaPackage(const std::string &packagePath, const std::string &keyPath) = 0; + /** * Get the information about the update package. * diff --git a/services/include/updater/updater.h b/services/include/updater/updater.h index 272c301ac6afab32d28b9a1248a090306bf164e9..c0dcca36afa5bd3b62e9864a25d02e541589015c 100644 --- a/services/include/updater/updater.h +++ b/services/include/updater/updater.h @@ -32,8 +32,14 @@ enum UpdaterStatus { using PostMessageFunction = std::function; +enum PackageUpdateMode { + HOTA_UPDATE = 0, + SDCARD_UPDATE, + UNKNOWN_UPDATE, +}; + UpdaterStatus DoInstallUpdaterPackage(hpackage::PkgManager::PkgManagerPtr pkgManager, - const std::string &packagePath, int retryCount); + const std::string &packagePath, int retryCount, PackageUpdateMode updateMode); UpdaterStatus StartUpdaterProc(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath, int retryCount, int &maxTemperature); @@ -41,14 +47,13 @@ UpdaterStatus StartUpdaterProc(hpackage::PkgManager::PkgManagerPtr pkgManager, c int GetUpdatePackageInfo(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string& path); int UpdatePreProcess(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string& path); +#ifdef UPDATER_USE_PTABLE +bool PtableProcess(hpackage::PkgManager::PkgManagerPtr pkgManager, PackageUpdateMode updateMode); +#endif int ExecUpdate(hpackage::PkgManager::PkgManagerPtr pkgManager, int retry, PostMessageFunction postMessage); -bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog); - -void CompressLogs(const std::string &name); - -int IsSpaceCapacitySufficient(const std::string &packagePath); +UpdaterStatus IsSpaceCapacitySufficient(const std::string &packagePath); bool IsSDCardExist(const std::string &sdcard_path); diff --git a/services/include/updater/updater_const.h b/services/include/updater/updater_const.h index 6b447687201e76eb889baabf32d68f4300f15302..1b2a5ba7fc2261dbcecdc565c4e5b15d2525c8f9 100644 --- a/services/include/updater/updater_const.h +++ b/services/include/updater/updater_const.h @@ -22,9 +22,14 @@ const std::string COMMAND_FILE = "/data/updater/command"; const std::string TMP_LOG = "/tmp/updater.log"; const std::string TMP_STAGE_LOG = "/tmp/updater_stage.log"; const std::string TMP_ERROR_CODE_PATH = "/tmp/error_code.log"; +const std::string ERROR_CODE_PATH = "/data/updater/log/error_code.log"; const std::string UPDATER_LOG_DIR = "/data/updater/log"; +const std::string UPDATER_LOG = "/data/updater/log/updater_log"; +const std::string UPDATER_STAGE_LOG = "/data/updater/log/updater_stage_log"; const std::string UPDATER_PATH = "/data/updater"; +const std::string UPDATER_RESULT_FILE = "updater_result"; const std::string MISC_FILE = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc"; +const std::string MISC_PATH = "/misc"; const std::string UPDATER_BINARY = "updater_binary"; const std::string SDCARD_PATH = "/sdcard"; const std::string UPDATER_HDC_LOG = "/data/updater/log/flashd_hdc.log"; @@ -45,6 +50,7 @@ constexpr int MAX_LOG_BUF_SIZE = 4096; constexpr int MAX_LOG_NAME_SIZE = 100; constexpr long MAX_LOG_SIZE = 5 * 1024 * 1024; constexpr int MAX_TIME_SIZE = 20; +constexpr int MAX_RESULT_SIZE = 20; constexpr int VERIFICATION_PROGRESS_TIME = 60; constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25f; constexpr int PREDICTED_ELAPSED_TIME = 30; @@ -53,7 +59,6 @@ constexpr int PROGRESS_VALUE_MIN = 0; constexpr int SLEEP_TIME = 1; constexpr int DECIMAL = 10; constexpr int BINARY = 2; -constexpr int LEAST_PARTITION_COUNT = 4; constexpr int FAKE_TEMPRATURE = 40; constexpr int32_t DEFAULT_PROCESS_NUM = 2; constexpr int32_t MAX_BUFFER_SIZE = 512; @@ -71,6 +76,7 @@ constexpr int SHUTDOWN = 6; constexpr int FULL_PERCENT_PROGRESS = 100; constexpr int PROGRESS_VALUE_CONST = 2; constexpr int SHOW_FULL_PROGRESS_TIME = 2000; +constexpr unsigned int LEAST_PARTITION_COUNT = 4; constexpr unsigned int UI_SHOW_DURATION = 2000; constexpr unsigned int INTERVAL_TIME = 300; constexpr float EPSINON = 0.00001; diff --git a/services/log/log.cpp b/services/log/log.cpp index f81993da38eefed1573e0ca89eed764dd32633c8..b02fabff4252fe3c36a20ebe8c8400c7f011111e 100644 --- a/services/log/log.cpp +++ b/services/log/log.cpp @@ -118,6 +118,10 @@ void Logger(int level, const char* fileName, int32_t line, const char* format, . va_start(list, format); int size = vsnprintf_s(reinterpret_cast(buff.data()), buff.capacity(), buff.capacity(), format, list); va_end(list); + if (size < EOK) { + UpdaterLogger(level).OutputUpdaterLog(fileName, line) << "vsnprintf_s failed"; + return; + } std::string str(buff.data(), size); UpdaterLogger(level).OutputUpdaterLog(fileName, line) << str; } diff --git a/services/package/BUILD.gn b/services/package/BUILD.gn index 142054f0ff68aa3ece976ce8785228ecafea00cb..9bca33a5076a07d061d3438d2346f85035485c76 100644 --- a/services/package/BUILD.gn +++ b/services/package/BUILD.gn @@ -28,6 +28,7 @@ config("package_config") { "pkg_algorithm", "pkg_manager", "pkg_package", + "pkg_verify", "//third_party/bounds_checking_function/include", ] if (current_cpu == "arm" && host_os != "mac") { @@ -53,6 +54,9 @@ ohos_static_library("libupdaterpackage") { "$SUBSYSTEM_DIR/pkg_package/pkg_pkgfile.cpp", "$SUBSYSTEM_DIR/pkg_package/pkg_upgradefile.cpp", "$SUBSYSTEM_DIR/pkg_package/pkg_zipfile.cpp", + "$SUBSYSTEM_DIR/pkg_verify/pkcs7_signed_data.cpp", + "$SUBSYSTEM_DIR/pkg_verify/pkg_verify_util.cpp", + "$SUBSYSTEM_DIR/pkg_verify/zip_pkg_parse.cpp", ] deps = [ "//third_party/bounds_checking_function:libsec_static" ] diff --git a/services/package/pkg_algorithm/pkg_algo_deflate.h b/services/package/pkg_algorithm/pkg_algo_deflate.h index d7cc17c898255b8f3d8eec6f02c2c45f2352635d..e425914304a452cf0f0c5f0e21fa5731fd0b44ca 100644 --- a/services/package/pkg_algorithm/pkg_algo_deflate.h +++ b/services/package/pkg_algorithm/pkg_algo_deflate.h @@ -39,6 +39,7 @@ public: int32_t Unpack(const PkgStreamPtr inStream, const PkgStreamPtr outStream, PkgAlgorithmContext &context) override; + private: int32_t UnpackCalculate(PkgAlgorithmContext &context, const PkgStreamPtr inStream, const PkgStreamPtr outStream, DigestAlgorithm::DigestAlgorithmPtr algorithm); @@ -49,6 +50,7 @@ private: int32_t DeflateData(const PkgStreamPtr outStream, z_stream &zstream, int32_t flush, PkgBuffer &outBuffer, size_t &destOffset) const; + private: int32_t level_ {0}; int32_t method_ {0}; diff --git a/services/package/pkg_algorithm/pkg_algo_digest.cpp b/services/package/pkg_algorithm/pkg_algo_digest.cpp index 4bb6eef67b32ac66d9743c6d81dae1b381d58cec..a6fd662449a86e3a5f9d981beabceac9b1169fb2 100644 --- a/services/package/pkg_algorithm/pkg_algo_digest.cpp +++ b/services/package/pkg_algorithm/pkg_algo_digest.cpp @@ -124,7 +124,7 @@ int32_t Sha384Algorithm::Update(const PkgBuffer &buffer, size_t size) int32_t Sha384Algorithm::Final(PkgBuffer &result) { - PKG_CHECK(result.buffer != nullptr && result.length == 64, // 64 length + PKG_CHECK(result.buffer != nullptr && result.length == DIGEST_SHA384_LEN, return PKG_INVALID_PARAM, "Param context null!"); SHA384_Final(result.buffer, &shaCtx_); return PKG_SUCCESS; @@ -132,7 +132,7 @@ int32_t Sha384Algorithm::Final(PkgBuffer &result) int32_t Sha384Algorithm::Calculate(PkgBuffer &result, const PkgBuffer &buffer, size_t size) { - PKG_CHECK(result.buffer != nullptr && result.length == 64, // 64 length + PKG_CHECK(result.buffer != nullptr && result.length == DIGEST_SHA384_LEN, return PKG_INVALID_PARAM, "Param context null!"); PKG_CHECK(buffer.buffer != nullptr, return PKG_INVALID_PARAM, "Param null!"); SHA512_Init(&shaCtx_); diff --git a/services/package/pkg_algorithm/pkg_algo_digest.h b/services/package/pkg_algorithm/pkg_algo_digest.h index a83c1328953179252cdb55bae1e7c31142d58597..4b08139dda2df4e43109f57d133d98fd2b6b56cb 100644 --- a/services/package/pkg_algorithm/pkg_algo_digest.h +++ b/services/package/pkg_algorithm/pkg_algo_digest.h @@ -21,7 +21,7 @@ namespace hpackage { constexpr uint32_t DIGEST_CRC_LEN = 4; constexpr uint32_t DIGEST_SHA256_LEN = 32; -constexpr uint32_t DIGEST_SHA384_LEN = 48; +constexpr uint32_t DIGEST_SHA384_LEN = 64; constexpr uint32_t SIGN_SHA256_LEN = 256; constexpr uint32_t SIGN_SHA384_LEN = 384; constexpr uint32_t SIGN_TOTAL_LEN = 384 + 256; diff --git a/services/package/pkg_algorithm/pkg_algo_lz4.cpp b/services/package/pkg_algorithm/pkg_algo_lz4.cpp index c1aa802fd66a800c6ebf3b4adf080aabb4854d5a..ea617a14d0f3665c9658189d45ec33f3e02f2f92 100644 --- a/services/package/pkg_algorithm/pkg_algo_lz4.cpp +++ b/services/package/pkg_algorithm/pkg_algo_lz4.cpp @@ -61,7 +61,7 @@ int32_t PkgAlgorithmBlockLz4::Pack(const PkgStreamPtr inStream, const PkgStreamP PkgAlgorithmContext &context) { PKG_CHECK(inStream != nullptr && outStream != nullptr, return PKG_INVALID_PARAM, "Param context null!"); - size_t blockSize = GetBlockSizeFromBlockId(blockSizeID_); + size_t blockSize = static_cast(GetBlockSizeFromBlockId(blockSizeID_)); blockSize = (blockSize > LZ4B_BLOCK_SIZE) ? LZ4B_BLOCK_SIZE : blockSize; PkgBuffer inBuffer = {blockSize}; PkgBuffer outBuffer = {LZ4_compressBound(blockSize)}; @@ -98,7 +98,7 @@ int32_t PkgAlgorithmBlockLz4::Pack(const PkgStreamPtr inStream, const PkgStreamP PKG_CHECK(ret == PKG_SUCCESS, break, "Fail write data "); srcOffset += readLen; - destOffset += outSize + LZ4B_REVERSED_LEN; + destOffset += static_cast(outSize) + LZ4B_REVERSED_LEN; } PKG_CHECK(srcOffset - context.srcOffset == context.unpackedSize, return ret, "original size error %zu %zu", srcOffset, context.unpackedSize); @@ -111,9 +111,9 @@ int32_t PkgAlgorithmBlockLz4::Unpack(const PkgStreamPtr inStream, const PkgStrea PkgAlgorithmContext &context) { PKG_CHECK(inStream != nullptr && outStream != nullptr, return PKG_INVALID_PARAM, "Param context null!"); - size_t inBuffSize = LZ4_compressBound(LZ4B_BLOCK_SIZE); + int inBuffSize = LZ4_compressBound(LZ4B_BLOCK_SIZE); PKG_CHECK(inBuffSize > 0, return PKG_NONE_MEMORY, "BufferSize must > 0"); - PkgBuffer inBuffer(inBuffSize); + PkgBuffer inBuffer(static_cast(inBuffSize)); PkgBuffer outBuffer(LZ4B_BLOCK_SIZE); PKG_CHECK(inBuffer.buffer != nullptr && outBuffer.buffer != nullptr, return PKG_NONE_MEMORY, "Fail to alloc buffer "); @@ -133,8 +133,8 @@ int32_t PkgAlgorithmBlockLz4::Unpack(const PkgStreamPtr inStream, const PkgStrea break; } uint32_t blockSize = ReadLE32(inBuffer.buffer); - PKG_CHECK(!(blockSize > LZ4_COMPRESSBOUND(LZ4B_BLOCK_SIZE) || blockSize > inBuffSize), break, - "Fail to get block size %u %u", blockSize, LZ4_COMPRESSBOUND(LZ4B_BLOCK_SIZE)); + PKG_CHECK(!(blockSize > static_cast(inBuffSize)), break, + "Fail to get block size %u %d", blockSize, inBuffSize); srcOffset += sizeof(uint32_t); /* Read Block */ @@ -150,7 +150,7 @@ int32_t PkgAlgorithmBlockLz4::Unpack(const PkgStreamPtr inStream, const PkgStrea /* Write Block */ ret = outStream->Write(outBuffer, decodeSize, destOffset); PKG_CHECK(ret == PKG_SUCCESS, break, "Fail write data "); - destOffset += decodeSize; + destOffset += static_cast(decodeSize); srcOffset += readLen; } context.packedSize = srcOffset - context.srcOffset; @@ -165,7 +165,7 @@ int32_t PkgAlgorithmLz4::GetPackParam(LZ4F_compressionContext_t &ctx, LZ4F_prefe errorCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); PKG_CHECK(!LZ4F_isError(errorCode), return PKG_NONE_MEMORY, "Fail to create compress context %s", LZ4F_getErrorName(errorCode)); - size_t blockSize = GetBlockSizeFromBlockId(blockSizeID_); + size_t blockSize = static_cast(GetBlockSizeFromBlockId(blockSizeID_)); PKG_CHECK(!memset_s(&preferences, sizeof(preferences), 0, sizeof(preferences)), return PKG_NONE_MEMORY, "Memset failed"); preferences.autoFlush = autoFlush_; @@ -304,21 +304,22 @@ int32_t PkgAlgorithmLz4::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr int32_t ret = GetUnpackParam(ctx, inStream, nextToRead, srcOffset); PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_LZ4, "Fail to get param "); - size_t outBuffSize = GetBlockSizeFromBlockId(blockSizeID_); - PKG_LOGI("Block size ID %d outBuffSize:%zu", blockSizeID_, outBuffSize); - size_t inBuffSize = outBuffSize + sizeof(uint32_t); + int32_t outBuffSize = GetBlockSizeFromBlockId(blockSizeID_); + PKG_LOGI("Block size ID %d outBuffSize:%d", blockSizeID_, outBuffSize); + int32_t inBuffSize = outBuffSize + static_cast(sizeof(uint32_t)); PKG_CHECK(inBuffSize > 0 && outBuffSize > 0, return PKG_NONE_MEMORY, "Buffer size must > 0"); - PkgBuffer inBuffer(inBuffSize); - PkgBuffer outBuffer(outBuffSize); + PkgBuffer inBuffer(static_cast(inBuffSize)); + PkgBuffer outBuffer(static_cast(outBuffSize)); PKG_CHECK(inBuffer.buffer != nullptr && outBuffer.buffer != nullptr, (void)LZ4F_freeDecompressionContext(ctx); return PKG_NONE_MEMORY, "Fail to alloc buffer "); /* Main Loop */ while (nextToRead != 0) { size_t readLen = 0; - size_t decodedBytes = outBuffSize; - PKG_CHECK(nextToRead <= inBuffSize, break, "Error next read %zu %zu ", nextToRead, inBuffSize); + size_t decodedBytes = static_cast(outBuffSize); + PKG_CHECK(nextToRead <= static_cast(inBuffSize), break, + "Error next read %zu %d ", nextToRead, inBuffSize); /* Read Block */ inBuffer.length = nextToRead; diff --git a/services/package/pkg_algorithm/pkg_algo_sign.cpp b/services/package/pkg_algorithm/pkg_algo_sign.cpp index b0f9d9cc57be7dc5841ea19c96472edf312e0ed7..ad394b55d5f4a09c8727924be86887288ce22a04 100644 --- a/services/package/pkg_algorithm/pkg_algo_sign.cpp +++ b/services/package/pkg_algorithm/pkg_algo_sign.cpp @@ -47,7 +47,7 @@ int32_t SignAlgorithmRsa::SignBuffer(const PkgBuffer &buffer, std::vector(RSA_size(rsa)); signedData.resize(size); ret = 0; if (digestMethod_ == PKG_DIGEST_TYPE_SHA256) { @@ -76,7 +76,7 @@ int32_t SignAlgorithmEcc::SignBuffer(const PkgBuffer &buffer, std::vector(ECDSA_size(ecKey)); signedData.resize(size + sizeof(uint32_t)); ret = ECDSA_sign(0, buffer.buffer, buffer.length, signedData.data() + sizeof(uint32_t), &size, ecKey); WriteLE32(signedData.data(), size); @@ -170,7 +170,7 @@ int32_t VerifyAlgorithm::VerifyBuffer(const std::vector &digest, const ret = RSA_verify(hashNid, digest.data(), digest.size(), signature.data(), signature.size(), certs.rsa); RSA_free(certs.rsa); } else if (certs.keyType == KEY_TYPE_EC && certs.hashLen == SHA256_DIGEST_LENGTH) { - int dataLen = ReadLE32(signature.data()); + uint32_t dataLen = ReadLE32(signature.data()); ret = ECDSA_verify(0, digest.data(), digest.size(), signature.data() + sizeof(uint32_t), dataLen, certs.ecKey); EC_KEY_free(certs.ecKey); } diff --git a/services/package/pkg_algorithm/pkg_algorithm.h b/services/package/pkg_algorithm/pkg_algorithm.h index c590feb8da504d51fbd7d531688e1398391bb399..e12c28f44a58c2dc16d0db276f433ccb9856ccbf 100644 --- a/services/package/pkg_algorithm/pkg_algorithm.h +++ b/services/package/pkg_algorithm/pkg_algorithm.h @@ -47,7 +47,7 @@ struct PkgAlgorithmContext { size_t unpackedSize = 0; uint32_t crc = 0; uint8_t digestMethod = 0; - uint8_t digest[DIGEST_MAX_LEN]; + uint8_t digest[DIGEST_MAX_LEN] = {}; PkgAlgorithmContext(PkgContextOffset offset, PkgContextSize size, uint32_t crc, uint8_t digestMethod) { diff --git a/services/package/pkg_manager/pkg_managerImpl.cpp b/services/package/pkg_manager/pkg_managerImpl.cpp index aa8951571be69499d6925c0952d3113476ce4e2c..9af91f14695b64960970c9fc51a4b24a566aacc8 100644 --- a/services/package/pkg_manager/pkg_managerImpl.cpp +++ b/services/package/pkg_manager/pkg_managerImpl.cpp @@ -25,8 +25,10 @@ #include "pkg_lz4file.h" #include "pkg_manager.h" #include "pkg_upgradefile.h" +#include "pkg_verify_util.h" #include "pkg_zipfile.h" #include "securec.h" +#include "zip_pkg_parse.h" using namespace std; @@ -41,7 +43,7 @@ constexpr int32_t DIGEST_FLAGS_SIGNATURE = 4; constexpr uint32_t VERIFY_FINSH_PERCENT = 100; constexpr uint32_t VERIFY_DIGEST_PERCENT = 50; -static PkgManagerImpl *g_pkgManagerInstance = nullptr; +static thread_local PkgManagerImpl *g_pkgManagerInstance = nullptr; PkgManager::PkgManagerPtr PkgManager::GetPackageInstance() { if (g_pkgManagerInstance == nullptr) { @@ -52,9 +54,7 @@ PkgManager::PkgManagerPtr PkgManager::GetPackageInstance() PkgManager::PkgManagerPtr PkgManager::CreatePackageInstance() { - PkgManager::PkgManagerPtr impl = new PkgManagerImpl(); - PKG_LOGI("CreatePackageInstance %p", impl); - return impl; + return new PkgManagerImpl(); } void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager) @@ -62,7 +62,6 @@ void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager) if (manager == nullptr) { return; } - PKG_LOGI("ReleasePackageInstance %p", manager); if (g_pkgManagerInstance == manager) { delete g_pkgManagerInstance; g_pkgManagerInstance = nullptr; @@ -83,12 +82,14 @@ void PkgManagerImpl::ClearPkgFile() while (iter != pkgFiles_.end()) { PkgFilePtr file = (*iter); delete file; + file = nullptr; iter = pkgFiles_.erase(iter); } auto iter1 = pkgStreams_.begin(); while (iter1 != pkgStreams_.end()) { PkgStreamPtr stream = (*iter1).second; delete stream; + stream = nullptr; iter1 = pkgStreams_.erase(iter1); } } @@ -107,6 +108,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; + pkgFile = nullptr; return ret; } @@ -124,6 +126,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; + pkgFile = nullptr; return ret; } @@ -141,6 +144,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; + pkgFile = nullptr; return ret; } @@ -169,6 +173,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, PkgInfoPtr header ret = Sign(pkgFile->GetPkgStream(), offset, header); } delete pkgFile; + pkgFile = nullptr; return ret; } @@ -196,11 +201,13 @@ PkgFilePtr PkgManagerImpl::CreatePackage(const std::string &path, PkgInfoPtr hea if (ret != PKG_SUCCESS) { ClosePkgStream(inputStream); delete pkgFile; + pkgFile = nullptr; return nullptr; } ret = pkgFile->SavePackage(offset); if (ret != PKG_SUCCESS) { delete pkgFile; + pkgFile = nullptr; return nullptr; } return pkgFile; @@ -431,6 +438,10 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string stream = nullptr; if (type == PkgStream::PkgStreamType_Write || type == PkgStream::PkgStreamType_Read) { static char const *modeFlags[] = { "rb", "wb+" }; + char realPath[PATH_MAX + 1] = {}; + if (type == PkgStream::PkgStreamType_Read && realpath(fileName.c_str(), realPath) == nullptr) { + return PKG_INVALID_FILE; + } int32_t ret = CheckFile(fileName); PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to check file %s ", fileName.c_str()); @@ -442,7 +453,11 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string } FILE *file = nullptr; - file = fopen(fileName.c_str(), modeFlags[type]); + if (type == PkgStream::PkgStreamType_Read) { + file = fopen(realPath, modeFlags[type]); + } else { + file = fopen(fileName.c_str(), modeFlags[type]); + } PKG_CHECK(file != nullptr, return PKG_INVALID_FILE, "Fail to open file %s ", fileName.c_str()); stream = new FileStream(this, fileName, file, type); } else if (type == PkgStream::PkgStreamType_MemoryMap) { @@ -494,8 +509,8 @@ void PkgManagerImpl::ClosePkgStream(PkgStreamPtr &stream) PkgFile::PkgType PkgManagerImpl::GetPkgTypeByName(const std::string &path) { - int32_t pos = path.find_last_of('.'); - if (pos < 0) { + std::size_t pos = path.find_last_of('.'); + if (pos == std::string::npos) { return PkgFile::PKG_TYPE_NONE; } std::string postfix = path.substr(pos + 1, -1); @@ -526,7 +541,7 @@ int32_t PkgManagerImpl::VerifyPackage(const std::string &packagePath, const std: PKG_CHECK(fileLen > 0, ClosePkgStream(stream); return PKG_INVALID_FILE, "invalid file to load"); PkgFile::PkgType type = GetPkgTypeByName(packagePath); - int8_t digestMethod = DigestAlgorithm::GetDigestMethod(version); + int8_t digestMethod = static_cast(DigestAlgorithm::GetDigestMethod(version)); size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod); size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod); PKG_CHECK(digestLen == digest.length, return PKG_INVALID_PARAM, "Invalid digestLen"); @@ -724,4 +739,83 @@ void PkgManagerImpl::PostDecodeProgress(int type, size_t writeDataLen, const voi decodeProgress_(type, writeDataLen, context); } } + +int32_t PkgManagerImpl::VerifyOtaPackage(const std::string &packagePath, const std::string &keyPath) +{ + size_t signatureStart = 0; + size_t signatureSize = 0; + char realPath[PATH_MAX + 1] = {0}; + if (realpath(keyPath.c_str(), realPath) == nullptr) { + return PKG_INVALID_FILE; + } + if (access(realPath, F_OK) != 0) { + PKG_LOGE("%s does not exist!", keyPath.c_str()); + return PKG_INVALID_FILE; + } + + PkgStreamPtr pkgStream = nullptr; + int32_t ret = CreatePkgStream(pkgStream, packagePath, 0, PkgStream::PkgStreamType_Read); + if (ret != PKG_SUCCESS) { + PKG_LOGE("CreatePackage fail %s", packagePath.c_str()); + return ret; + } + + ZipPkgParse zipParse; + ret = zipParse.ParseZipPkg(pkgStream, signatureStart, signatureSize); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Parse zip package signature failed."); + ClosePkgStream(pkgStream); + return ret; + } + + PkgVerifyUtil verifyUtil(keyPath); + ret = verifyUtil.VerifyPkcs7SignedData(pkgStream, signatureStart, signatureSize); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Verify zpkcs7 signature failed."); + ClosePkgStream(pkgStream); + return ret; + } + + ClosePkgStream(pkgStream); + return PKG_SUCCESS; +} + +int32_t PkgManagerImpl::CreateSignContent(const std::string &packagePath, const std::string &signedPackage, + const std::string &keyPath, PkgInfoPtr header) +{ + int32_t ret = SetSignVerifyKeyName(keyPath); + if (ret != PKG_SUCCESS) { + return ret; + } + if (access(packagePath.c_str(), F_OK) != 0) { + PKG_LOGE("%s does not exist!", packagePath.c_str()); + return PKG_INVALID_FILE; + } + PkgStreamPtr outStream = nullptr; + ret = CreatePkgStream(outStream, signedPackage, 0, PkgStream::PkgStreamType_Write); + if (ret != PKG_SUCCESS) { + PKG_LOGE("CreatePackage fail %s", signedPackage.c_str()); + return ret; + } + PkgStreamPtr inStream = nullptr; + ret = CreatePkgStream(inStream, packagePath, 0, PkgStream::PkgStreamType_Read); + if (ret != PKG_SUCCESS) { + PKG_LOGE("CreatePackage fail %s", packagePath.c_str()); + ClosePkgStream(outStream); + return ret; + } + + SignPkg signPkg(inStream, keyPath, header->signMethod); + ret = signPkg.SignPackage(outStream); + if (ret != PKG_SUCCESS) { + ClosePkgStream(inStream); + ClosePkgStream(outStream); + PKG_LOGE("sign package failed, ret[%d]", ret); + return ret; + } + + ClosePkgStream(inStream); + ClosePkgStream(outStream); + return PKG_SUCCESS; +} } // namespace hpackage diff --git a/services/package/pkg_manager/pkg_manager_impl.h b/services/package/pkg_manager/pkg_manager_impl.h index 04dd1039bc7c979e6fd6f28d5c815c10eca88f1a..baa8847d08c19ba6e02676224644e1d6d67efd03 100644 --- a/services/package/pkg_manager/pkg_manager_impl.h +++ b/services/package/pkg_manager/pkg_manager_impl.h @@ -27,7 +27,7 @@ namespace hpackage { class PkgManagerImpl : public PkgManager { public: - PkgManagerImpl() {}; + PkgManagerImpl() {} ~PkgManagerImpl() override; @@ -74,12 +74,18 @@ public: int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) override; + int32_t VerifyOtaPackage(const std::string &packagePath, const std::string &keyPath) override; + + int32_t CreateSignContent(const std::string &packagePath, const std::string &signedPackage, + const std::string &keyPath, PkgInfoPtr header) override; + void SetPkgDecodeProgress(PkgDecodeProgress decodeProgress) override { decodeProgress_ = decodeProgress; } void PostDecodeProgress(int type, size_t writeDataLen, const void *context) override; + private: PkgFilePtr CreatePackage(PkgStreamPtr stream, PkgFile::PkgType type, PkgInfoPtr header = nullptr); @@ -113,6 +119,7 @@ private: PkgStream::ExtractFileProcessor processor, const void *context); void ClosePkgStream(PkgStreamPtr &stream); + private: bool unzipToFile_ {true}; std::vector pkgFiles_ {}; diff --git a/services/package/pkg_manager/pkg_stream.cpp b/services/package/pkg_manager/pkg_stream.cpp index 7f28de2fcd46d8e99f10e9a3238a784f888ece43..fc400dafd6f02fd278d502d82bd4e47529c6ec19 100644 --- a/services/package/pkg_manager/pkg_stream.cpp +++ b/services/package/pkg_manager/pkg_stream.cpp @@ -18,7 +18,6 @@ #include #include #include "pkg_manager.h" -#include "pkg_manager_impl.h" #include "pkg_utils.h" #include "securec.h" @@ -93,12 +92,9 @@ size_t FileStream::GetFileLength() PKG_CHECK(stream_ != nullptr, return 0, "Invalid stream"); if (fileLength_ == 0) { PKG_CHECK(Seek(0, SEEK_END) == 0, return -1, "Invalid stream"); - off_t pos = ftello(stream_); - if (pos < 0) { - PKG_LOGE("Failed to get file length, err = %d", errno); - return 0; - } - fileLength_ = static_cast(pos); + off64_t ret = ftello64(stream_); + PKG_CHECK(ret >= 0, return PKG_INVALID_STREAM, "ftell64 failed"); + fileLength_ = static_cast(ret); fseek(stream_, 0, SEEK_SET); } return fileLength_; @@ -116,6 +112,13 @@ int32_t FileStream::Flush(size_t size) if (fileLength_ == 0) { fileLength_ = size; } + (void)fseek(stream_, 0, SEEK_END); + off64_t ret = ftello64(stream_); + PKG_CHECK(ret >= 0, return PKG_INVALID_STREAM, "ftell64 failed"); + fileLength_ = static_cast(ret); + if (size != fileLength_) { + PKG_LOGE("Flush size %zu local size:%zu", size, fileLength_); + } PKG_CHECK(fflush(stream_) == 0, return PKG_INVALID_STREAM, "Invalid stream"); return PKG_SUCCESS; } @@ -161,16 +164,17 @@ int32_t MemoryMapStream::Seek(long int offset, int whence) if (whence == SEEK_SET) { PKG_CHECK(offset >= 0, return PKG_INVALID_STREAM, "Invalid offset"); PKG_CHECK(static_cast(offset) <= memSize_, return PKG_INVALID_STREAM, "Invalid offset"); - currOffset_ = offset; + currOffset_ = static_cast(offset); } else if (whence == SEEK_CUR) { PKG_CHECK(static_cast(offset) <= (memSize_ - currOffset_), return PKG_INVALID_STREAM, "Invalid offset"); - currOffset_ += offset; + currOffset_ += static_cast(offset); } else { PKG_CHECK(offset <= 0, return PKG_INVALID_STREAM, "Invalid offset"); - PKG_CHECK((memSize_ + offset) <= memSize_, return PKG_INVALID_STREAM, "Invalid offset"); - PKG_CHECK((memSize_ + offset) >= 0, return PKG_INVALID_STREAM, "Invalid offset"); - currOffset_ = memSize_ + offset; + auto memSize = static_cast(memSize_); + PKG_CHECK((memSize + offset) <= memSize, return PKG_INVALID_STREAM, "Invalid offset"); + PKG_CHECK((memSize + offset) >= 0, return PKG_INVALID_STREAM, "Invalid offset"); + currOffset_ = static_cast(memSize + offset); } return PKG_SUCCESS; } diff --git a/services/package/pkg_manager/pkg_stream.h b/services/package/pkg_manager/pkg_stream.h index 02d21feb7d9c8c726904c0728507ee33f517dbf8..9fb184aa70738ae54c50cc3645da26d25df0d883 100644 --- a/services/package/pkg_manager/pkg_stream.h +++ b/services/package/pkg_manager/pkg_stream.h @@ -68,6 +68,7 @@ public: bool IsRef() const; static PkgStreamPtr ConvertPkgStream(PkgManager::StreamPtr stream); + protected: void PostDecodeProgress(int type, size_t writeDataLen, const void *context); std::string fileName_; @@ -98,6 +99,7 @@ public: { return streamType_; } + private: FILE *stream_; size_t fileLength_; @@ -145,6 +147,7 @@ public: buffer.length = memSize_; return PKG_SUCCESS; } + private: uint8_t *memMap_; size_t memSize_; @@ -201,6 +204,7 @@ public: PkgBuffer data = {}; return processor_(data, 0, 0, true, context_); } + private: ExtractFileProcessor processor_ = nullptr; const void *context_; diff --git a/services/package/pkg_manager/pkg_utils.cpp b/services/package/pkg_manager/pkg_utils.cpp index 554c4ed786936ff05a55ccb7c540b9d6c30654e8..73d485d85b5a0126cb6cce7168d9909deaa27ef9 100644 --- a/services/package/pkg_manager/pkg_utils.cpp +++ b/services/package/pkg_manager/pkg_utils.cpp @@ -39,8 +39,8 @@ using namespace updater::utils; std::string GetFilePath(const std::string &fileName) { - int32_t pos = fileName.find_last_of('/'); - if (pos < 0) { + std::size_t pos = fileName.find_last_of('/'); + if (pos == std::string::npos) { pos = fileName.find_last_of('\\'); } return fileName.substr(0, pos + 1); @@ -55,10 +55,15 @@ size_t GetFileSize(const std::string &fileName) PKG_CHECK(fp != nullptr, return 0, "Invalid file %s", fileName.c_str()); fseek(fp, 0, SEEK_END); - size_t size = ftell(fp); + long size = ftell(fp); + if (size < 0) { + PKG_LOGE("return value of ftell < 0"); + fclose(fp); + return 0; + } fclose(fp); // return file size in bytes - return size; + return static_cast(size); } std::string GetName(const std::string &filePath) @@ -120,8 +125,12 @@ void ExtraTimeAndDate(time_t when, uint16_t &date, uint16_t &time) if (year < MIN_YEAR) { year = MIN_YEAR; } - date = ((year - MIN_YEAR) << TM_YEAR_BITS) | ((nowTime.tm_mon + 1) << TM_MON_BITS) | nowTime.tm_mday; - time = (nowTime.tm_hour << TM_HOUR_BITS) | (nowTime.tm_min << TM_MIN_BITS) | (nowTime.tm_sec >> 1); + date = static_cast(static_cast(year - MIN_YEAR) << TM_YEAR_BITS); + date |= static_cast(static_cast(nowTime.tm_mon + 1) << TM_MON_BITS); + date |= static_cast(nowTime.tm_mday); + time = static_cast(static_cast(nowTime.tm_hour) << TM_HOUR_BITS); + time |= static_cast(static_cast(nowTime.tm_min) << TM_MIN_BITS); + time |= static_cast(static_cast(nowTime.tm_sec) >> 1); } uint32_t ReadLE32(const uint8_t *buff) @@ -130,11 +139,11 @@ uint32_t ReadLE32(const uint8_t *buff) size_t offset = 0; uint32_t value32 = buff[0]; offset += BYTE_SIZE; - value32 += (buff[1] << offset); + value32 += static_cast(static_cast(buff[1]) << offset); offset += BYTE_SIZE; - value32 += (buff[SECOND_BUFFER] << offset); + value32 += static_cast(static_cast(buff[SECOND_BUFFER]) << offset); offset += BYTE_SIZE; - value32 += (buff[THIRD_BUFFER] << offset); + value32 += static_cast(static_cast(buff[THIRD_BUFFER]) << offset); return value32; } @@ -164,7 +173,7 @@ uint16_t ReadLE16(const uint8_t *buff) { PKG_CHECK(buff != nullptr, return 0, "buff is null"); uint16_t value16 = buff[0]; - value16 += (buff[1] << BYTE_SIZE); + value16 += static_cast(buff[1] << BYTE_SIZE); return value16; } diff --git a/services/package/pkg_package/pkg_gzipfile.cpp b/services/package/pkg_package/pkg_gzipfile.cpp index dfb1596068f4dffa0cacbda85bf2584ee2cdae2a..ded086ecb701d5a0fc3eec59be26201f06d52843 100644 --- a/services/package/pkg_package/pkg_gzipfile.cpp +++ b/services/package/pkg_package/pkg_gzipfile.cpp @@ -226,7 +226,7 @@ int32_t GZipFileEntry::DecodeHeader(const PkgBuffer &buffer, size_t headerOffset } fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_GZIP; - fileInfo_.method = method; + fileInfo_.method = static_cast(method); fileInfo_.level = Z_BEST_COMPRESSION; fileInfo_.method = Z_DEFLATED; fileInfo_.windowBits = -MAX_WBITS; diff --git a/services/package/pkg_package/pkg_gzipfile.h b/services/package/pkg_package/pkg_gzipfile.h index a06dd7e55223092abef49a778413f27d20e4f17b..6d2309278d6ff86c243465f264b66ad9a068e0a2 100644 --- a/services/package/pkg_package/pkg_gzipfile.h +++ b/services/package/pkg_package/pkg_gzipfile.h @@ -25,7 +25,7 @@ struct __attribute__((packed)) GZipHeader { uint16_t magic = 0; uint8_t method = 0; uint8_t flags = 0; - uint32_t mtime = 0; + time_t mtime = 0; uint8_t xfl = 0; uint8_t osFile = 0; }; @@ -49,6 +49,7 @@ public: int32_t Unpack(PkgStreamPtr outStream) override; int32_t DecodeHeader(const PkgBuffer &buffer, size_t, size_t, size_t &decodeLen) override; + private: void DecodeHeaderCalOffset(uint8_t flags, const PkgBuffer &buffer, size_t &offset, std::string &fileName) const; @@ -70,6 +71,7 @@ public: int32_t SavePackage(size_t &offset) override; int32_t LoadPackage(std::vector &fileNames, VerifyFunction verifier = nullptr) override; + private: PkgInfo pkgInfo_ {}; size_t currentOffset_ = 0; diff --git a/services/package/pkg_package/pkg_lz4file.cpp b/services/package/pkg_package/pkg_lz4file.cpp index 96d8f4caf4700c9d448d9bacc5b42dae631fecf8..372c9cdc688f03a9df537b3b4f2aefda82ec1717 100644 --- a/services/package/pkg_package/pkg_lz4file.cpp +++ b/services/package/pkg_package/pkg_lz4file.cpp @@ -130,6 +130,7 @@ int32_t Lz4PkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStream PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Pack for %s", file->identity.c_str()); currentOffset_ += encodeLen; PKG_LOGI("offset:%zu ", currentOffset_); + pkgStream_->Flush(currentOffset_); return PKG_SUCCESS; } diff --git a/services/package/pkg_package/pkg_lz4file.h b/services/package/pkg_package/pkg_lz4file.h index 95b0658a0f4093f0b26f55bbcc24342982e4ba7f..bde1464202716064ffc0531f7ba2aa89ef9de60c 100644 --- a/services/package/pkg_package/pkg_lz4file.h +++ b/services/package/pkg_package/pkg_lz4file.h @@ -46,6 +46,7 @@ public: int32_t Unpack(PkgStreamPtr outStream) override; int32_t DecodeHeader(const PkgBuffer &buffer, size_t, size_t, size_t &decodeLen) override; + private: Lz4FileInfo fileInfo_ {}; }; @@ -65,6 +66,7 @@ public: int32_t SavePackage(size_t &offset) override; int32_t LoadPackage(std::vector &fileNames, VerifyFunction verifier = nullptr) override; + private: PkgInfo pkgInfo_ {}; size_t currentOffset_ {0}; diff --git a/services/package/pkg_package/pkg_pkgfile.h b/services/package/pkg_package/pkg_pkgfile.h index 7a7a908d1aea5d12ff940681c42cc12765d89712..fc05900823a56717ad2d0253841efb200ba05da6 100644 --- a/services/package/pkg_package/pkg_pkgfile.h +++ b/services/package/pkg_package/pkg_pkgfile.h @@ -59,6 +59,7 @@ public: { return nodeId_; } + protected: int32_t Init(PkgManager::FileInfoPtr localFileInfo, const PkgManager::FileInfoPtr fileInfo, PkgStreamPtr inStream); @@ -125,9 +126,11 @@ public: static int32_t ConvertStringToBuffer(const std::string &fileName, const PkgBuffer &buffer, size_t &realLen); void AddSignData(uint8_t digestMethod, size_t currOffset, size_t &signOffset); + protected: PkgEntryPtr AddPkgEntry(const std::string& fileName); bool CheckState(std::vector states, uint32_t state); + protected: enum { PKG_FILE_STATE_IDLE = 0, diff --git a/services/package/pkg_package/pkg_upgradefile.cpp b/services/package/pkg_package/pkg_upgradefile.cpp index ecda48ae12f5b262a0db716df72bccbdf39c3581..621d379325f673088e21057912a7ced245edd132 100644 --- a/services/package/pkg_package/pkg_upgradefile.cpp +++ b/services/package/pkg_package/pkg_upgradefile.cpp @@ -370,7 +370,8 @@ int32_t UpgradeFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset size_t len = 0; int32_t ret = PkgFile::ConvertStringToBuffer( fileInfo_.fileInfo.identity, {comp.address, sizeof(comp.address)}, len); - ret |= PkgFile::ConvertStringToBuffer(fileInfo_.version, {comp.version, sizeof(comp.version)}, len); + PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_PARAM, "outStream or inStream null for %s", fileName_.c_str()); + ret = PkgFile::ConvertStringToBuffer(fileInfo_.version, {comp.version, sizeof(comp.version)}, len); PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_PARAM, "outStream or inStream null for %s", fileName_.c_str()); ret = memcpy_s(comp.digest, sizeof(comp.digest), fileInfo_.digest, sizeof(fileInfo_.digest)); diff --git a/services/package/pkg_package/pkg_upgradefile.h b/services/package/pkg_package/pkg_upgradefile.h index e2fdbb273c6f068aa788f1ec24019713143c15b7..e16d03d4a29506cb9263fd52a3e731195de550c8 100644 --- a/services/package/pkg_package/pkg_upgradefile.h +++ b/services/package/pkg_package/pkg_upgradefile.h @@ -40,7 +40,7 @@ struct __attribute__((packed)) UpgradePkgTime { }; struct __attribute__((packed)) UpgradeCompInfo { - uint8_t address[16]; // L1 16 + uint8_t address[32]; // L1 16 uint16_t id; uint8_t resType; uint8_t flags; @@ -72,6 +72,7 @@ public: { return &fileInfo_.fileInfo; } + private: ComponentInfo fileInfo_ {}; }; @@ -92,7 +93,7 @@ public: int32_t AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr input) override; - int32_t SavePackage(size_t &signOffset) override; + int32_t SavePackage(size_t &offset) override; int32_t LoadPackage(std::vector &fileNames, VerifyFunction verify = nullptr) override; @@ -104,6 +105,7 @@ public: { return &pkgInfo_.pkgInfo; } + private: int16_t GetPackageTlvType(); int32_t ReadComponents(const PkgBuffer &buffer, size_t &parsedLen, @@ -114,6 +116,7 @@ private: int32_t Verify(size_t start, DigestAlgorithm::DigestAlgorithmPtr algorithm, VerifyFunction verifier, const std::vector &signData); + private: UpgradePkgInfo pkgInfo_ {}; size_t packedFileSize_ {0}; diff --git a/services/package/pkg_package/pkg_zipfile.cpp b/services/package/pkg_package/pkg_zipfile.cpp index df5626c44a7322c1c3c1cf1b33719c155d9e47f8..7327ec111a6af73ec6ef0f5b16d963bcfa1a03d7 100644 --- a/services/package/pkg_package/pkg_zipfile.cpp +++ b/services/package/pkg_package/pkg_zipfile.cpp @@ -18,6 +18,7 @@ #include "pkg_algorithm.h" #include "pkg_manager.h" #include "pkg_stream.h" +#include "zip_pkg_parse.h" #include "zlib.h" namespace hpackage { @@ -61,6 +62,7 @@ int32_t ZipPkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStream int32_t ZipPkgFile::SavePackage(size_t &signOffset) { + UNUSED(signOffset); PKG_CHECK(CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_CLOSE), return PKG_INVALID_STATE, "error state curr %d ", state_); int32_t ret = PKG_SUCCESS; @@ -88,7 +90,7 @@ int32_t ZipPkgFile::SavePackage(size_t &signOffset) PKG_CHECK(ret == PKG_SUCCESS, return ret, "Failed to write CentralDirEntry for %s", pkgStream_->GetFileName().c_str()); currentOffset_ = offset + sizeof(EndCentralDir); - AddSignData(pkgInfo_.digestMethod, currentOffset_, signOffset); + pkgStream_->Flush(currentOffset_); return PKG_SUCCESS; } @@ -152,7 +154,7 @@ int32_t ZipPkgFile::LoadPackage(std::vector& fileNames, VerifyFunct if (buffSize < sizeof(Zip64EndCentralDirRecord)) { buffSize = sizeof(Zip64EndCentralDirRecord); } - size_t signatureLen = SIGN_SHA256_LEN + SIGN_SHA384_LEN; + size_t signatureLen = 0; uint32_t magic = 0; uint32_t endDirLen = sizeof(EndCentralDir); size_t endDirPos = fileLen - endDirLen; @@ -162,12 +164,16 @@ int32_t ZipPkgFile::LoadPackage(std::vector& fileNames, VerifyFunct PKG_CHECK(ret == PKG_SUCCESS, return ret, "read EOCD struct failed %s", pkgStream_->GetFileName().c_str()); magic = ReadLE32(buffer.buffer); if (magic != END_CENTRAL_SIGNATURE) { // 按签名处理 - PKG_CHECK(fileLen >= static_cast(sizeof(EndCentralDir) + signatureLen), return PKG_INVALID_FILE, - "Too small to be zip %s", pkgStream_->GetFileName().c_str()); + size_t signatureStart = 0; + ZipPkgParse zipParse; + int32_t ret = zipParse.ParseZipPkg(pkgStream_, signatureStart, signatureLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Parse zip package signature failed"); + endDirPos -= signatureLen; ret = pkgStream_->Read(buffer, endDirPos, sizeof(EndCentralDir), readLen); PKG_CHECK(ret == PKG_SUCCESS, return ret, "read EOCD struct failed %s", pkgStream_->GetFileName().c_str()); } + return LoadPackage(fileNames, buffer, endDirLen, endDirPos, readLen); } @@ -175,7 +181,7 @@ int32_t ZipPkgFile::ParseFileEntries(std::vector &fileNames, const EndCentralDir &endDir, size_t currentPos, size_t fileLen) { int32_t ret = PKG_SUCCESS; - int32_t buffLen = MAX_FILE_NAME + sizeof(LocalFileHeader) + sizeof(DataDescriptor) + size_t buffLen = MAX_FILE_NAME + sizeof(LocalFileHeader) + sizeof(DataDescriptor) + sizeof(CentralDirEntry) + BIG_SIZE_HEADER; PkgBuffer buffer(buffLen); @@ -285,7 +291,7 @@ int32_t ZipFileEntry::EncodeCentralDirEntry(const PkgStreamPtr stream, size_t st if (fileInfo_.method == Z_DEFLATED) { centralDir->flags |= GPBDD_FLAG_MASK; } - centralDir->compressionMethod = fileInfo_.method; + centralDir->compressionMethod = static_cast(fileInfo_.method); centralDir->crc = crc32_; uint16_t date; uint16_t time; @@ -318,7 +324,7 @@ int32_t ZipFileEntry::EncodeLocalFileHeader(uint8_t *buffer, size_t bufferLen, b header->signature = LOCAL_HEADER_SIGNATURE; header->versionNeeded = 0; header->flags = 0; - header->compressionMethod = fileInfo_.method; + header->compressionMethod = static_cast(fileInfo_.method); uint16_t date; uint16_t time; ExtraTimeAndDate(fileInfo_.fileInfo.modifiedTime, date, time); @@ -391,7 +397,7 @@ int32_t ZipFileEntry::DecodeCentralDirEntry(PkgStreamPtr inStream, PkgBuffer &bu "data not not enough %zu", readLen); fileInfo_.fileInfo.identity.assign(reinterpret_cast(buffer.buffer + sizeof(CentralDirEntry)), fileNameLength); - fileInfo_.method = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, compressionMethod)); + fileInfo_.method = static_cast(ReadLE16(buffer.buffer + offsetof(CentralDirEntry, compressionMethod))); uint16_t modifiedTime = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, modifiedTime)); uint16_t modifiedDate = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, modifiedDate)); CombineTimeAndDate(fileInfo_.fileInfo.modifiedTime, modifiedTime, modifiedDate); @@ -405,7 +411,7 @@ int32_t ZipFileEntry::DecodeCentralDirEntry(PkgStreamPtr inStream, PkgBuffer &bu return PKG_SUCCESS; } uint8_t* extraData = buffer.buffer + nameSize + sizeof(CentralDirEntry); - int16_t headerId = ReadLE16(extraData); + uint16_t headerId = ReadLE16(extraData); if (headerId != 1) { // zip64 扩展 return PKG_SUCCESS; } @@ -479,7 +485,7 @@ int32_t ZipFileEntry::DecodeLocalFileHeader(PkgStreamPtr inStream, const PkgBuff return PKG_INVALID_PKG_FORMAT, "data not not enough %zu", readLen); std::string fileName(reinterpret_cast(data.buffer + sizeof(LocalFileHeader)), fileNameLength); uint16_t compressionMethod = ReadLE16(data.buffer + offsetof(LocalFileHeader, compressionMethod)); - fileInfo_.method = compressionMethod; + fileInfo_.method = static_cast(compressionMethod); fileInfo_.level = Z_BEST_COMPRESSION; fileInfo_.method = Z_DEFLATED; fileInfo_.windowBits = -MAX_WBITS; diff --git a/services/package/pkg_package/pkg_zipfile.h b/services/package/pkg_package/pkg_zipfile.h index 706e57154bf942fae67d8162280166fe548b461e..89174f713b2365109a5077a90c1c35c0f6b19f15 100644 --- a/services/package/pkg_package/pkg_zipfile.h +++ b/services/package/pkg_package/pkg_zipfile.h @@ -150,9 +150,11 @@ public: int32_t DecodeCentralDirEntry(PkgStreamPtr inStream, PkgBuffer &buffer, size_t currentPos, size_t &decodeLen); + protected: ZipFileInfo fileInfo_ {}; uint32_t crc32_ {0}; + private: int32_t DecodeLocalFileHeaderCheck(PkgStreamPtr inStream, const PkgBuffer &data, size_t currentPos); @@ -181,11 +183,13 @@ public: int32_t SavePackage(size_t &offset) override; int32_t LoadPackage(std::vector &fileNames, VerifyFunction verifier = nullptr) override; + private: int32_t LoadPackage(std::vector &fileNames, const PkgBuffer &buff, uint32_t endDirLen, size_t endDirPos, size_t &readLen); int32_t ParseFileEntries(std::vector &fileNames, const EndCentralDir &endDir, size_t currentPos, size_t fileLen); + private: PkgInfo pkgInfo_ {}; size_t currentOffset_ = 0; diff --git a/services/package/pkg_verify/pkcs7_signed_data.cpp b/services/package/pkg_verify/pkcs7_signed_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c376c8e02b64e86ca10b8622fe352ecc64a81530 --- /dev/null +++ b/services/package/pkg_verify/pkcs7_signed_data.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2022 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 "pkcs7_signed_data.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pkg_utils.h" + +namespace hpackage { +Pkcs7SignedData::Pkcs7SignedData() +{ + pkcs7_ = nullptr; + p7Bio_ = nullptr; +} + +Pkcs7SignedData::~Pkcs7SignedData() +{ + if (p7Bio_ != nullptr) { + BIO_free(p7Bio_); + p7Bio_ = nullptr; + } + if (pkcs7_ != nullptr) { + PKCS7_free(pkcs7_); + pkcs7_ = nullptr; + } +} + +int32_t Pkcs7SignedData::BuildPkcs7SignedData(PkgBuffer &p7Data, uint32_t signMethod, + const std::vector &digestBlock, const std::vector &signedData) +{ + if (digestBlock.empty() || signedData.empty()) { + return PKG_INVALID_PARAM; + } + pkcs7_ = PKCS7_new(); + if (pkcs7_ == nullptr) { + PKG_LOGE("new PKCS7 data failed."); + return PKG_INVALID_STREAM; + } + + int32_t ret = PKCS7_set_type(pkcs7_, NID_pkcs7_signed); + if (ret <= 0) { + PKG_LOGE("set PKCS7 data type failed."); + return ret; + } + PKCS7_set_detached(pkcs7_, 0); + + ret = UpdateDigestBlock(digestBlock); + if (ret != PKG_SUCCESS) { + PKG_LOGE("update digest block failed."); + return ret; + } + ret = UpdateSignerInfo(signedData, signMethod); + if (ret != PKG_SUCCESS) { + PKG_LOGE("update signer info failed."); + return ret; + } + + return PutDataToBuffer(p7Data); +} + +int32_t Pkcs7SignedData::UpdateDigestBlock(const std::vector &digestBlock) +{ + int32_t ret = PKCS7_content_new(pkcs7_, NID_pkcs7_data); + if (ret <= 0) { + PKG_LOGE("new PKCS7 content failed."); + return ret; + } + + p7Bio_ = PKCS7_dataInit(pkcs7_, nullptr); + if (p7Bio_ == nullptr) { + PKG_LOGE("Pkcs7 data init failed."); + return PKG_NONE_MEMORY; + } + ret = BIO_write(p7Bio_, digestBlock.data(), digestBlock.size()); + if (ret <= 0) { + PKG_LOGE("bio write digest block failed."); + return ret; + } + (void)BIO_flush(p7Bio_); + ret = PKCS7_dataFinal(pkcs7_, p7Bio_); + if (ret <= 0) { + PKG_LOGE("Pkcs7 data final failed."); + return ret; + } + + return PKG_SUCCESS; +} + +int32_t Pkcs7SignedData::UpdateSignerInfo(const std::vector &signedData, uint32_t signMethod) +{ + PKCS7_SIGNER_INFO *p7Si = PKCS7_SIGNER_INFO_new(); + if (p7Si == nullptr) { + PKG_LOGE("new pkcs7 signed info failed."); + return PKG_INVALID_STREAM; + } + + ASN1_OBJECT *digObj = OBJ_nid2obj(EVP_MD_type(EVP_sha256())); + X509_ALGOR_set0(p7Si->digest_alg, digObj, V_ASN1_NULL, NULL); + + ASN1_OBJECT *signObj = GetSignAlgorithmObj(signMethod); + if (signObj != nullptr) { + X509_ALGOR_set0(p7Si->digest_enc_alg, signObj, V_ASN1_NULL, NULL); + } + + int32_t ret = ASN1_STRING_set(p7Si->enc_digest, signedData.data(), signedData.size()); + if (ret <= 0) { + PKG_LOGE("Set signer info enc_digest failed."); + PKCS7_SIGNER_INFO_free(p7Si); + return ret; + } + + ret = sk_PKCS7_SIGNER_INFO_push(pkcs7_->d.sign->signer_info, p7Si); + if (ret <= 0) { + PKG_LOGE("Set signer info failed."); + PKCS7_SIGNER_INFO_free(p7Si); + return ret; + } + + return PKG_SUCCESS; +} + +ASN1_OBJECT *Pkcs7SignedData::GetSignAlgorithmObj(uint32_t signMethod) +{ + switch (signMethod) { + case PKG_SIGN_METHOD_RSA: + return OBJ_nid2obj(NID_sha256WithRSAEncryption); + case PKG_SIGN_METHOD_ECDSA: + return OBJ_nid2obj(NID_ecdsa_with_SHA256); + default: + PKG_LOGE("Invalid sign method."); + return nullptr; + } + + return nullptr; +} + +int32_t Pkcs7SignedData::PutDataToBuffer(PkgBuffer &p7Data) +{ + int32_t p7DataLen = i2d_PKCS7(pkcs7_, NULL); + PKG_CHECK(p7DataLen > 0, return PKG_INVALID_STREAM, "Invalid p7DataLen"); + uint8_t *outBuf = new(std::nothrow) uint8_t[p7DataLen](); + PKG_CHECK(outBuf != nullptr, return PKG_INVALID_STREAM, "malloc mem failed."); + + BIO *p7OutBio = BIO_new(BIO_s_mem()); + PKG_CHECK(p7OutBio != nullptr, delete [] outBuf; return PKG_INVALID_STREAM, "BIO new failed."); + + int32_t ret = i2d_PKCS7_bio(p7OutBio, pkcs7_); + PKG_CHECK(ret > 0, delete [] outBuf; BIO_free(p7OutBio); return ret, "i2d_PKCS7_bio failed."); + + (void)BIO_read(p7OutBio, outBuf, p7DataLen); + p7Data.buffer = outBuf; + p7Data.length = static_cast(p7DataLen); + + BIO_free(p7OutBio); + return PKG_SUCCESS; +} + +int32_t Pkcs7SignedData::ParsePkcs7SignedData(const uint8_t *sourceData, uint32_t sourceDataLen, + std::vector &digestBlock, std::vector &signerInfos) +{ + int32_t ret = VerifyInit(sourceData, sourceDataLen); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Init pkcs7 data failed.!"); + return ret; + } + + return DoParse(digestBlock, signerInfos); +} + +int32_t Pkcs7SignedData::VerifyInit(const uint8_t *sourceData, uint32_t sourceDataLen) +{ + if (sourceData == nullptr || sourceDataLen == 0) { + return PKG_INVALID_PARAM; + } + + p7Bio_ = BIO_new(BIO_s_mem()); + if (p7Bio_ == nullptr) { + PKG_LOGE("BIO_new error!"); + return PKG_INVALID_STREAM; + } + (void)BIO_write(p7Bio_, sourceData, sourceDataLen); + + pkcs7_ = d2i_PKCS7_bio(p7Bio_, nullptr); + if (pkcs7_ == nullptr) { + PKG_LOGE("d2i_PKCS7_bio failed!"); + return PKG_INVALID_STREAM; + } + + return PKG_SUCCESS; +} + +int32_t Pkcs7SignedData::DoParse(std::vector &digestBlock, std::vector &signerInfos) +{ + int32_t p7Type = OBJ_obj2nid(pkcs7_->type); + if (p7Type != NID_pkcs7_signed) { + PKG_LOGE("Invalid pkcs7 data type %d!", p7Type); + return PKG_INVALID_PKG_FORMAT; + } + + PKCS7_SIGNED *signData = pkcs7_->d.sign; + if (signData == nullptr) { + PKG_LOGE("Invalid pkcs7 signed data!"); + return PKG_INVALID_PKG_FORMAT; + } + + return ParseSignedData(digestBlock, signerInfos); +} + +/* + * tools.ietf.org/html/rfc2315#section-9.1 + * SignedData ::= SEQUENCE(0x30) { + * INTEGER(0x02) version Version, + * SET(0x31) digestAlgorithms DigestAlgorithmIdentifiers, + * SEQUENCE(0x30) contentInfo ContentInfo, + * CONTET_SPECIFIC[0](0xA0) certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL, + * CONTET_SPECIFIC[1](0xA1) crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, + * SET(0x31) signerInfos SignerInfos } + */ +int32_t Pkcs7SignedData::ParseSignedData(std::vector &digestBlock, + std::vector &signerInfos) +{ + int32_t ret = ParseContentInfo(digestBlock, pkcs7_->d.sign); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Parse pkcs7 content info failed!"); + return ret; + } + + return ParseSignerInfos(signerInfos); +} + +/* + * tools.ietf.org/html/rfc2315#section-7 + * ContentInfo ::= SEQUENCE(0x30) { + * OBJECT_IDENTIFIER(0x06) contentType ContentType, + * CONTET_SPECIFIC[0](0xA0) content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + * + * tools.ietf.org/html/rfc2315#section-8 + * Data ::= OCTET STRING + */ +int32_t Pkcs7SignedData::ParseContentInfo(std::vector &digestBlock, const PKCS7_SIGNED *signData) +{ + if (signData == nullptr) { + return PKG_INVALID_PARAM; + } + PKCS7 *contentInfo = signData->contents; + if (contentInfo == nullptr) { + PKG_LOGE("Invalid pkcs7 signed data!"); + return PKG_INVALID_PKG_FORMAT; + } + int32_t type = OBJ_obj2nid(contentInfo->type); + if (type != NID_pkcs7_data) { + PKG_LOGE("Invalid pkcs7 signed data %d!", type); + return PKG_INVALID_PKG_FORMAT; + } + + const uint8_t *digest = ASN1_STRING_get0_data(contentInfo->d.data); + if (digest == nullptr) { + PKG_LOGE("Get asn1 obj string failed!"); + return PKG_INVALID_PKG_FORMAT; + } + int32_t digestLen = ASN1_STRING_length(contentInfo->d.data); + if (digestLen <= 0) { + PKG_LOGE("Invalid asn1 obj string len %d!", digestLen); + return PKG_INVALID_PKG_FORMAT; + } + + digestBlock.resize(digestLen); + int32_t ret = memcpy_s(digestBlock.data(), digestLen, digest, digestLen); + if (ret != EOK) { + PKG_LOGE("Fail to memcpy_s digestBlock, digestLen%d", digestLen); + return PKG_NONE_MEMORY; + } + + return PKG_SUCCESS; +} + +/* + * tools.ietf.org/html/rfc2315#section-9.2 + * SignerInfo ::= SEQUENCE(0x30) { + * INTEGER(0x02) version Version, + * SEQUENCE(0x30) issuerAndSerialNumber IssuerAndSerialNumber, + * SEQUENCE(0x30) digestAlgorithm DigestAlgorithmIdentifier, + * CONTET_SPECIFIC[0](0xA0) authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL, + * SEQUENCE(0x30) digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, + * OCTET_STRING(0x30) encryptedDigest EncryptedDigest, + * CONTET_SPECIFIC[1](0xA1) unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL } + */ +int32_t Pkcs7SignedData::ParseSignerInfos(std::vector &signerInfos) +{ + if (PKCS7_get_signer_info(pkcs7_) == nullptr) { + PKG_LOGE("Get pkcs7 signers info failed!"); + return PKG_INVALID_PKG_FORMAT; + } + + int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(PKCS7_get_signer_info(pkcs7_)); + if (signerInfoNum <= 0) { + PKG_LOGE("Invalid signers info num %d!", signerInfoNum); + return PKG_INVALID_PKG_FORMAT; + } + + for (int i = 0; i < signerInfoNum; i++) { + PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(PKCS7_get_signer_info(pkcs7_), i); + Pkcs7SignerInfo signer; + int32_t ret = SignerInfoParse(p7SiTmp, signer); + if (ret != PKG_SUCCESS) { + PKG_LOGE("SignerInfoParse failed!"); + continue; + } + signerInfos.push_back(std::move(signer)); + } + + return PKG_SUCCESS; +} + +int32_t Pkcs7SignedData::SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo) +{ + if (p7SignerInfo == nullptr) { + return PKG_INVALID_PARAM; + } + int32_t ret = ParseSignerInfoX509Algo(signerInfo.digestNid, p7SignerInfo->digest_alg); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Parse signer info digest_alg failed!"); + return ret; + } + ret = ParseSignerInfoX509Algo(signerInfo.digestEncryptNid, p7SignerInfo->digest_enc_alg); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Parse signer info digest_enc_alg failed!"); + return ret; + } + + const uint8_t *encDigest = ASN1_STRING_get0_data(p7SignerInfo->enc_digest); + if (encDigest == nullptr) { + PKG_LOGE("Get asn1 obj string failed!"); + return PKG_INVALID_PKG_FORMAT; + } + int32_t encDigestLen = ASN1_STRING_length(p7SignerInfo->enc_digest); + if (encDigestLen <= 0) { + PKG_LOGE("Invalid asn1 obj string len %d!", encDigestLen); + return PKG_INVALID_PKG_FORMAT; + } + + signerInfo.digestEncryptData.resize(encDigestLen); + ret = memcpy_s(signerInfo.digestEncryptData.data(), + signerInfo.digestEncryptData.size(), encDigest, encDigestLen); + if (ret != EOK) { + PKG_LOGE("Fail to memcpy_s digestEncryptData, encDigestLen %d", encDigestLen); + return PKG_NONE_MEMORY; + } + + return PKG_SUCCESS; +} + +int32_t Pkcs7SignedData::ParseSignerInfoX509Algo(int32_t &algoNid, const X509_ALGOR *x509Algo) +{ + if (x509Algo == nullptr) { + return PKG_INVALID_PARAM; + } + + const ASN1_OBJECT *algObj = nullptr; + X509_ALGOR_get0(&algObj, nullptr, nullptr, x509Algo); + if (algObj == nullptr) { + PKG_LOGE("Signer info ASN1_OBJECT null!"); + return PKG_INVALID_PKG_FORMAT; + } + algoNid = OBJ_obj2nid(algObj); + if (algoNid <= 0) { + PKG_LOGE("Invalid Signer info ASN1_OBJECT!"); + return PKG_INVALID_PKG_FORMAT; + } + + return PKG_SUCCESS; +} +} // namespace hpackage diff --git a/services/package/pkg_verify/pkcs7_signed_data.h b/services/package/pkg_verify/pkcs7_signed_data.h new file mode 100644 index 0000000000000000000000000000000000000000..65d6027286b3f2190d49a015fb7d17be76dc8e24 --- /dev/null +++ b/services/package/pkg_verify/pkcs7_signed_data.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef PKCS7_SIGNED_DATA_H +#define PKCS7_SIGNED_DATA_H + +#include +#include +#include +#include +#include "pkg_manager.h" + +namespace hpackage { +struct Pkcs7SignerInfo { + int32_t digestNid; + int32_t digestEncryptNid; + std::vector digestEncryptData; +}; + +class Pkcs7SignedData { +public: + Pkcs7SignedData(); + + ~Pkcs7SignedData(); + + int32_t BuildPkcs7SignedData(hpackage::PkgBuffer &p7Data, uint32_t signMethod, + const std::vector &digestBlock, const std::vector &signedData); + + int32_t ParsePkcs7SignedData(const uint8_t *sourceData, uint32_t sourceDataLen, + std::vector &digestBlock, std::vector &signerInfos); + +private: + int32_t UpdateDigestBlock(const std::vector &digestBlock); + + int32_t UpdateSignerInfo(const std::vector &signedData, uint32_t signMethod); + + ASN1_OBJECT *GetSignAlgorithmObj(uint32_t signMethod); + + int32_t PutDataToBuffer(hpackage::PkgBuffer &p7Data); + +private: + int32_t VerifyInit(const uint8_t *sourceData, uint32_t sourceDataLen); + + int32_t DoParse(std::vector &digestBlock, std::vector &signerInfos); + + int32_t ParseSignedData(std::vector &digestBlock, std::vector &signerInfos); + + int32_t ParseContentInfo(std::vector &digestBlock, const PKCS7_SIGNED *signData); + + int32_t ParseSignerInfos(std::vector &signerInfos); + + int32_t SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo); + + int32_t ParseSignerInfoX509Algo(int32_t &algoNid, const X509_ALGOR *x509Algo); + +private: + PKCS7 *pkcs7_; + BIO *p7Bio_; +}; +} // namespace hpackage +#endif diff --git a/services/package/pkg_verify/pkg_verify_util.cpp b/services/package/pkg_verify/pkg_verify_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..404f144c4291c0460c447d9fb00312b4b520bf7b --- /dev/null +++ b/services/package/pkg_verify/pkg_verify_util.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2022 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 "pkg_verify_util.h" +#include +#include +#include +#include "pkcs7_signed_data.h" +#include "pkg_algorithm.h" +#include "pkg_utils.h" +#include "securec.h" +#include "zip_pkg_parse.h" + +namespace hpackage { +static constexpr uint32_t HASH_SOURCE_BLOCK_LEN = 4096; +static constexpr uint32_t ZIP_EOCD_FIXED_PART_LEN = 22; +static constexpr uint32_t PKG_FOOTER_SIZE = 6; +static constexpr uint32_t PKG_HASH_CONTENT_LEN = SHA256_DIGEST_LENGTH; + +static int g_algIdAndNid[][2] = { + {NID_sha256, PKG_DIGEST_TYPE_SHA256}, +}; + +static int ConvertNidToMethod(int algId) +{ + int nid = PKG_DIGEST_TYPE_NONE; + for (int i = 0; i < sizeof(g_algIdAndNid) / sizeof(g_algIdAndNid[0]); i++) { + if (algId == g_algIdAndNid[i][0]) { + nid = g_algIdAndNid[i][1]; + } + } + + return nid; +} + +int32_t SignPkg::SignPackage(PkgStreamPtr outStream) const +{ + std::vector digestBlock; + std::vector signData; + int32_t ret = CreateSignResult(digestBlock, signData); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Create sign result failed."); + return ret; + } + + PkgBuffer p7Data; + Pkcs7SignedData pkcs7; + ret = pkcs7.BuildPkcs7SignedData(p7Data, signMethod_, digestBlock, signData); + if (p7Data.buffer == nullptr || p7Data.length == 0) { + PKG_LOGE("Create pkcs7 signed data failed."); + return PKG_INVALID_SIGNATURE; + } + + ZipPkgParse zipParse; + ret = zipParse.CheckZipPkg(pkgStream_); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Invalid unsigned zip format."); + delete [] p7Data.buffer; + return ret; + } + + ret = zipParse.WriteZipSignedData(outStream, p7Data, pkgStream_); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Invalid unsigned zip format."); + delete [] p7Data.buffer; + return ret; + } + + delete [] p7Data.buffer; + return PKG_SUCCESS; +} + +int32_t SignPkg::CreateSignResult(std::vector &digestBlock, std::vector &signedData) const +{ + size_t fileLen = pkgStream_->GetFileLength(); + PKG_CHECK(fileLen > ZIP_EOCD_FIXED_PART_LEN, return PKG_INVALID_PARAM, "Invalid zip file "); + size_t srcDataLen = fileLen - ZIP_EOCD_FIXED_PART_LEN; + + std::vector digest(PKG_HASH_CONTENT_LEN); + int32_t ret = CalcSha256ByBlock(pkgStream_, srcDataLen, digest); + if (ret != PKG_SUCCESS) { + PKG_LOGE("calc pkg sha256 digest failed."); + return ret; + } + + ret = CreateDigestBlock(digestBlock, digest); + if (ret != PKG_SUCCESS) { + PKG_LOGE("create digest content failed"); + return ret; + } + + return SignPackageDigest(digest, signedData); +} + +int32_t SignPkg::CreateDigestBlock(std::vector &digestBlock, const std::vector &digest) const +{ + if (digest.empty()) { + return PKG_INVALID_PARAM; + } + size_t digestBlockLen = digest.size() + sizeof(uint32_t); + digestBlock.resize(digestBlockLen); + + size_t offset = 0; + WriteLE16(digestBlock.data(), EVP_MD_type(EVP_sha256())); + offset += sizeof(uint16_t); + WriteLE16(digestBlock.data() + offset, digest.size()); + offset += sizeof(uint16_t); + + PKG_CHECK(digestBlock.size() >= offset, return PKG_INVALID_PARAM, "digestBlock size "); + int32_t ret = memcpy_s(digestBlock.data() + offset, + digestBlock.size() - offset, digest.data(), digest.size()); + if (ret != EOK) { + PKG_LOGE("Fail to memcpy_s digestData, dataLen: %d", digest.size()); + return PKG_NONE_MEMORY; + } + + return PKG_SUCCESS; +} + +int32_t SignPkg::SignPackageDigest(std::vector &digest, std::vector &signData) const +{ + if (digest.size() != PKG_HASH_CONTENT_LEN) { + return PKG_INVALID_PARAM; + } + SignAlgorithm::SignAlgorithmPtr signAlgorithm = + PkgAlgorithmFactory::GetSignAlgorithm(privateKey_, signMethod_, PKG_DIGEST_TYPE_SHA256); + if (signAlgorithm == nullptr) { + PKG_LOGE("Invalid sign algo"); + return PKG_INVALID_ALGORITHM; + } + + PkgBuffer digestBuffer(digest); + signData.clear(); + size_t signDataLen = 0; + int32_t ret = signAlgorithm->SignBuffer(digestBuffer, signData, signDataLen); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Fail to Sign package"); + return ret; + } + + PKG_LOGI("SignPackageBuffer success %u", signDataLen); + return PKG_SUCCESS; +} + +int32_t PkgVerifyUtil::VerifyPkcs7SignedData(const PkgStreamPtr pkgStream, + const size_t signatureStart, const size_t signatureSize) +{ + size_t fileLen = pkgStream->GetFileLength(); + PKG_CHECK(fileLen > signatureSize, return PKG_INVALID_PARAM, "Invalid signature size[%zu]", signatureSize); + + std::vector digestBlock; + std::vector signerInfos; + + size_t p7DataLen = signatureSize - PKG_FOOTER_SIZE; + PkgBuffer p7Data(p7DataLen); + size_t readLen = 0; + int32_t ret = pkgStream->Read(p7Data, signatureStart, p7DataLen, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "read signature failed", pkgStream->GetFileName().c_str()); + + Pkcs7SignedData pkcs7; + ret = pkcs7.ParsePkcs7SignedData(p7Data.buffer, p7Data.length, digestBlock, signerInfos); + if (ret != PKG_SUCCESS) { + PKG_LOGE("ParsePkcs7SignedData() error, ret[%d]", ret); + return ret; + } + + ret = ParseDigestBlock(digestBlock); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Parse digest block failed."); + return ret; + } + PKG_CHECK(fileLen > (signatureSize + ZIP_EOCD_FIXED_PART_LEN), + return PKG_INVALID_PARAM, "Invalid signature srcDataLen"); + size_t srcDataLen = fileLen - signatureSize - ZIP_EOCD_FIXED_PART_LEN; + + return VerifySignedData(pkgStream, srcDataLen, signerInfos); +} + +int32_t PkgVerifyUtil::VerifySignedData(const PkgStreamPtr srcData, const size_t dataLen, + std::vector &signerInfos) const +{ + int32_t ret = VerifyDigestEncryptData(srcData, dataLen, signerInfos); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Verify digest encryptData failed."); + return ret; + } + + return HashCheck(srcData, dataLen); +} + +int32_t PkgVerifyUtil::ParseDigestBlock(const std::vector &digestBlock) +{ + if (digestBlock.size() == 0) { + PKG_LOGE("Invalid digest block info."); + return PKG_INVALID_PARAM; + } + + size_t offset = 0; + digestBlock_.algorithmId = ReadLE16(digestBlock.data() + offset); + offset += sizeof(uint16_t); + digestBlock_.digestLen = ReadLE16(digestBlock.data() + offset); + offset += sizeof(uint16_t); + if ((digestBlock_.digestLen + offset) != digestBlock.size()) { + PKG_LOGE("Invalid digestLen[%zu] and digestBlock len[%zu]", digestBlock_.digestLen, digestBlock.size()); + return PKG_INVALID_DIGEST; + } + digestBlock_.digestData.resize(digestBlock_.digestLen); + int32_t ret = memcpy_s(digestBlock_.digestData.data(), digestBlock_.digestLen, + digestBlock.data() + offset, digestBlock_.digestLen); + if (ret != EOK) { + PKG_LOGE("Fail to memcpy_s subBlock, dataLen: %d", digestBlock_.digestLen); + return PKG_INVALID_DIGEST; + } + + return PKG_SUCCESS; +} + +int32_t PkgVerifyUtil::VerifyDigestEncryptData(const PkgStreamPtr srcData, const size_t dataLen, + std::vector &signerInfos) const +{ + if (signerInfos.size() == 0) { + PKG_LOGE("Invalid signer info."); + return PKG_INVALID_PARAM; + } + + int32_t ret = PKG_SUCCESS; + std::vector::iterator iter; + for (iter = signerInfos.begin(); iter < signerInfos.end(); iter++) { + ret = SingleDigestEncryptVerify(*iter, srcData, dataLen); + if (ret == PKG_SUCCESS) { + PKG_LOGE("pkcs7 signer info verify success."); + break; + } + } + + return ret; +} + +int32_t PkgVerifyUtil::SingleDigestEncryptVerify(Pkcs7SignerInfo &signer, + const PkgStreamPtr srcData, const size_t dataLen) const +{ + uint8_t digestMethod = static_cast(ConvertNidToMethod(signer.digestNid)); + + return VerifyPackageDigest(signer.digestEncryptData, digestBlock_.digestData, digestMethod); +} + +int32_t PkgVerifyUtil::VerifyPackageDigest(const std::vector &digestEncryptData, + const std::vector &digest, const uint8_t digestMethod) const +{ + if (digestMethod > PKG_DIGEST_TYPE_MAX) { + PKG_LOGE("Invalid digest digestMethod %zu.", digestMethod); + return PKG_INVALID_SIGNATURE; + } + if (digestEncryptData.size() == 0) { + PKG_LOGE("Digest EncryptData is empty."); + return PKG_INVALID_SIGNATURE; + } + + SignAlgorithm::SignAlgorithmPtr verifyAlgorithm = + PkgAlgorithmFactory::GetVerifyAlgorithm(pubKey_, digestMethod); + if (verifyAlgorithm == nullptr) { + PKG_LOGE("Invalid verify algo"); + return PKG_INVALID_SIGNATURE; + } + + return verifyAlgorithm->VerifyBuffer(digest, digestEncryptData); +} + +int32_t PkgVerifyUtil::HashCheck(const PkgStreamPtr srcData, const size_t dataLen) const +{ + if (srcData == nullptr || dataLen == 0) { + return PKG_INVALID_PARAM; + } + if (digestBlock_.digestData.empty()) { + PKG_LOGE("Invalid digest block vector."); + return PKG_INVALID_DIGEST; + } + + size_t digestLen = digestBlock_.digestLen; + if (digestLen != PKG_HASH_CONTENT_LEN) { + PKG_LOGE("calc pkg sha256 digest failed."); + return PKG_INVALID_PARAM; + } + std::vector sourceDigest(digestBlock_.digestLen); + int32_t ret = CalcSha256ByBlock(srcData, dataLen, sourceDigest); + if (ret != PKG_SUCCESS) { + PKG_LOGE("calc pkg sha256 digest failed."); + return ret; + } + + if (memcmp(digestBlock_.digestData.data(), sourceDigest.data(), digestLen) != EOK) { + PKG_LOGE("Failed to memcmp data."); + return PKG_INVALID_DIGEST; + } + + return PKG_SUCCESS; +} + +int32_t CalcSha256ByBlock(const PkgStreamPtr srcData, const size_t dataLen, std::vector &result) +{ + if (srcData == nullptr || dataLen == 0) { + return PKG_INVALID_PARAM; + } + if (result.size() != PKG_HASH_CONTENT_LEN) { + PKG_LOGE("Invalid digest result len %zu.", result.size()); + return PKG_INVALID_DIGEST; + } + SHA256_CTX ctx; + SHA256_Init(&ctx); + + size_t offset = 0; + size_t remainLen = dataLen; + size_t blockLen = HASH_SOURCE_BLOCK_LEN; + PkgBuffer buffer(blockLen); + size_t readLen = 0; + int32_t ret = PKG_SUCCESS; + while (remainLen >= blockLen) { + ret = srcData->Read(buffer, offset, blockLen, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail read data"); + SHA256_Update(&ctx, buffer.buffer, blockLen); + offset += blockLen; + remainLen -= blockLen; + } + if (remainLen > 0) { + ret = srcData->Read(buffer, offset, remainLen, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail read data"); + SHA256_Update(&ctx, buffer.buffer, remainLen); + } + + if (SHA256_Final(result.data(), &ctx) != 1) { + PKG_LOGE("SHA256_Final(), error\n"); + return PKG_INVALID_DIGEST; + } + + return PKG_SUCCESS; +} +} // namespace hpackage diff --git a/services/package/pkg_verify/pkg_verify_util.h b/services/package/pkg_verify/pkg_verify_util.h new file mode 100644 index 0000000000000000000000000000000000000000..f3e838bf46240a3fdbc7aa4f408e12e1c710ebbe --- /dev/null +++ b/services/package/pkg_verify/pkg_verify_util.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef PKG_VERIFY_UTIL_H +#define PKG_VERIFY_UTIL_H + +#include +#include "pkcs7_signed_data.h" +#include "pkg_stream.h" + +namespace hpackage { +struct DigestBlock { + uint16_t algorithmId; + uint16_t digestLen; + std::vector digestData; +}; + +class PkgVerifyUtil { +public: + explicit PkgVerifyUtil(const std::string &publicKey) : pubKey_(publicKey) {} + + ~PkgVerifyUtil() {} + + int32_t VerifyPkcs7SignedData(const hpackage::PkgStreamPtr pkgStream, const size_t signatureStart, + const size_t signatureSize); + +private: + int32_t VerifySignedData(const hpackage::PkgStreamPtr srcData, const size_t dataLen, + std::vector &signerInfos) const; + + int32_t ParseDigestBlock(const std::vector &digestBlock); + + int32_t VerifyDigestEncryptData(const hpackage::PkgStreamPtr srcData, const size_t dataLen, + std::vector &signerInfos) const; + + int32_t SingleDigestEncryptVerify(Pkcs7SignerInfo &signer, + const hpackage::PkgStreamPtr srcData, const size_t dataLen) const; + + int32_t VerifyPackageDigest(const std::vector &digestEncryptData, + const std::vector &digest, const uint8_t digestMethod) const; + + int32_t HashCheck(const hpackage::PkgStreamPtr srcData, const size_t dataLen) const; + +private: + std::string pubKey_; + DigestBlock digestBlock_ {}; +}; + +class SignPkg { +public: + SignPkg(hpackage::PkgStreamPtr inStream, const std::string &keyPath, uint32_t signMethod) + : pkgStream_(inStream), privateKey_(keyPath), signMethod_(signMethod) {} + + ~SignPkg() {} + + int32_t SignPackage(hpackage::PkgStreamPtr outStream) const; + +private: + int32_t SignPackageDigest(std::vector &digest, std::vector &signData) const; + + int32_t CreateSignResult(std::vector &digestBlock, std::vector &signedData) const; + + int32_t CreateDigestBlock(std::vector &digestBlock, const std::vector &digest) const; + +private: + hpackage::PkgStreamPtr pkgStream_; + std::string privateKey_; + uint32_t signMethod_; +}; + +int32_t CalcSha256ByBlock(const hpackage::PkgStreamPtr srcData, const size_t dataLen, std::vector &result); +} // namespace hpackage +#endif diff --git a/services/package/pkg_verify/zip_pkg_parse.cpp b/services/package/pkg_verify/zip_pkg_parse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d76518061f15449adb4e308aba143225b86dd03f --- /dev/null +++ b/services/package/pkg_verify/zip_pkg_parse.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2022 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 "zip_pkg_parse.h" +#include +#include "pkg_utils.h" + +namespace hpackage { +struct Footer { + uint16_t signDataStart; + uint16_t signDataFlag; + uint16_t signDataSize; +}; + +static constexpr uint32_t SOURCE_DATA_WRITE_BLOCK_LEN = 4096; +static constexpr uint32_t ZIP_EOCD_LEN_EXCLUDE_COMMENT = 20; +static constexpr uint32_t ZIP_EOCD_FIXED_PART_LEN = 22; +static constexpr uint32_t PKG_FOOTER_SIZE = 6; +static constexpr uint32_t PKG_ZIP_EOCD_MIN_LEN = ZIP_EOCD_FIXED_PART_LEN + PKG_FOOTER_SIZE; +static constexpr uint32_t ZIP_EOCD_SIGNATURE = 0x06054b50; +static constexpr uint16_t PKG_ZIP_EOCD_FOOTER_FLAG = 0xFFFF; +static constexpr uint32_t SECOND_BYTE = 2; +static constexpr uint32_t THIRD_BYTE = 3; +static const uint8_t ZIP_EOCD_SIGNATURE_BIG_ENDIAN[4] = {0x50, 0x4b, 0x05, 0x06}; + +/* + * ZIP: File Entry(1..n) + CD(1..n) + EOCD(1) + * + * EOCD: FLAG(4 bytes) + FIX PART1(16 bytes) + comment length(2 bytes) + comment('comment length' bytes) + * + * EOCD comment: RESERVED(18 bytes) + SIGNATYRE(variable size) + FOOTER (6 bytes) + * + * FOOTER 6 bytes (little endian) + * append signed result length 2 bytes (SIGNATYRE's length + FOOTER's length) = SIGNATYRE reversed offset + * 0xFFFF 2 bytes + * = .ZIP file comment length 2 bytes + */ +int32_t ZipPkgParse::ParseZipPkg(PkgStreamPtr pkgStream, size_t &signatureStart, size_t &signatureSize) const +{ + if (pkgStream == nullptr) { + return PKG_INVALID_PARAM; + } + size_t fileLen = pkgStream->GetFileLength(); + size_t footerSize = PKG_FOOTER_SIZE; + PKG_CHECK(fileLen > footerSize, return PKG_INVALID_FILE, + "file len[%zu] < footerSize.", pkgStream->GetFileLength()); + size_t footerStart = fileLen - footerSize; + size_t readLen = 0; + PkgBuffer footer(footerSize); + int32_t ret = pkgStream->Read(footer, footerStart, footerSize, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "read FOOTER struct failed %s", pkgStream->GetFileName().c_str()); + + uint16_t signCommentAppendLen = 0; + uint16_t signCommentTotalLen = 0; + ret = ParsePkgFooter(footer.buffer, PKG_FOOTER_SIZE, signCommentAppendLen, signCommentTotalLen); + if (ret != PKG_SUCCESS) { + PKG_LOGE("ParsePkgFooter() error, ret[%d]", ret); + return ret; + } + + size_t eocdTotalLen = ZIP_EOCD_FIXED_PART_LEN + signCommentTotalLen; + PKG_CHECK(fileLen > eocdTotalLen, return PKG_INVALID_PKG_FORMAT, "Invalid eocd len[%zu]", eocdTotalLen); + + size_t zipEocdStart = fileLen - eocdTotalLen; + PkgBuffer zipEocd(eocdTotalLen); + ret = pkgStream->Read(zipEocd, zipEocdStart, eocdTotalLen, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "read zip eocd failed %s", pkgStream->GetFileName().c_str()); + + ret = CheckZipEocd(zipEocd.buffer, eocdTotalLen, signCommentTotalLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "CheckZipEocd() error, ret[%d]", ret); + + PKG_CHECK(fileLen > signCommentTotalLen, return PKG_INVALID_FILE, + "file len[%zu] < signCommentTotalLen[%zu]", fileLen, signCommentTotalLen); + signatureStart = fileLen - signCommentTotalLen; + signatureSize = signCommentTotalLen; + + return PKG_SUCCESS; +} + +int32_t ZipPkgParse::ParsePkgFooter(const uint8_t *footer, size_t length, + uint16_t &signCommentAppendLen, uint16_t &signCommentTotalLen) const +{ + if (length < PKG_FOOTER_SIZE) { + PKG_LOGE("length[%d] < Footer Size[%d]", length, PKG_FOOTER_SIZE); + return PKG_INVALID_PARAM; + } + + Footer signFooter = {0}; + size_t offset = 0; + signFooter.signDataStart = ReadLE16(footer); + offset += sizeof(uint16_t); + signFooter.signDataFlag = ReadLE16(footer + offset); + offset += sizeof(uint16_t); + signFooter.signDataSize = ReadLE16(footer + offset); + if (signFooter.signDataFlag != PKG_ZIP_EOCD_FOOTER_FLAG) { + PKG_LOGE("error FooterFlag[0x%04X]", signFooter.signDataFlag); + return PKG_INVALID_PKG_FORMAT; + } + + signCommentAppendLen = signFooter.signDataStart; + signCommentTotalLen = signFooter.signDataSize; + if ((signCommentAppendLen < PKG_FOOTER_SIZE) || (signCommentTotalLen < PKG_FOOTER_SIZE) || + (signCommentAppendLen > signCommentTotalLen)) { + PKG_LOGE("bad footer length: append[0x%04X], total[0x%04X]", + signCommentAppendLen, signCommentTotalLen); + return PKG_INVALID_PKG_FORMAT; + } + + return PKG_SUCCESS; +} + +int32_t ZipPkgParse::CheckZipEocd(const uint8_t *eocd, size_t length, + uint16_t signCommentTotalLen) const +{ + if (length < PKG_ZIP_EOCD_MIN_LEN) { + PKG_LOGE("bad eocd length: append[0x%04X]", length); + return PKG_INVALID_PKG_FORMAT; + } + + uint32_t eocdSignature = ReadLE32(eocd); + if (eocdSignature != ZIP_EOCD_SIGNATURE) { + PKG_LOGE("bad zip eocd flag[%zu]", eocdSignature); + return PKG_INVALID_PKG_FORMAT; + } + + /* the beginning 4 chars are already checked before, so begin with i = 4; (length - 3) in case for overflow */ + for (size_t i = 4; i < length - 3; i++) { + if (eocd[i] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[0] && + eocd[i + 1] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[1] && + eocd[i + SECOND_BYTE] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[SECOND_BYTE] && + eocd[i + THIRD_BYTE] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[THIRD_BYTE]) { + PKG_LOGE("EOCD marker occurs after start of EOCD"); + return PKG_INVALID_PKG_FORMAT; + } + } + + const uint8_t *zipSignCommentAddr = eocd + ZIP_EOCD_LEN_EXCLUDE_COMMENT; + uint16_t tempLen = ReadLE16(zipSignCommentAddr); + if (signCommentTotalLen != tempLen) { + PKG_LOGE("compare sign comment length: eocd[0x%04X], footer[0x%04X] error", tempLen, signCommentTotalLen); + return PKG_INVALID_PKG_FORMAT; + } + + return PKG_SUCCESS; +} + +int32_t ZipPkgParse::CheckZipPkg(const PkgStreamPtr pkgStream) const +{ + size_t fileLen = pkgStream->GetFileLength(); + if (fileLen <= ZIP_EOCD_FIXED_PART_LEN) { + PKG_LOGE("Invalid file len %zu", fileLen); + return PKG_INVALID_FILE; + } + + PkgBuffer zipEocd(ZIP_EOCD_FIXED_PART_LEN); + size_t eocdStart = fileLen - ZIP_EOCD_FIXED_PART_LEN; + size_t readLen = 0; + int32_t ret = pkgStream->Read(zipEocd, eocdStart, ZIP_EOCD_FIXED_PART_LEN, readLen); + if (ret != PKG_SUCCESS) { + PKG_LOGE("read eocd failed %s", pkgStream->GetFileName().c_str()); + return PKG_INVALID_FILE; + } + + uint32_t eocdSignature = ReadLE32(zipEocd.buffer); + if (eocdSignature != ZIP_EOCD_SIGNATURE) { + PKG_LOGE("Zip pkg has been signed."); + return PKG_INVALID_FILE; + } + + return PKG_SUCCESS; +} + +int32_t ZipPkgParse::WriteZipSignedData(PkgStreamPtr outStream, const PkgBuffer &p7Data, PkgStreamPtr inStream) const +{ + size_t offset = 0; + size_t fileSize = inStream->GetFileLength(); + size_t srcDataLen = fileSize - sizeof(uint16_t); + int32_t ret = WriteSourcePackageData(outStream, inStream, srcDataLen); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Fail to write src data"); + return ret; + } + offset += srcDataLen; + + uint16_t zipCommentLen = p7Data.length + PKG_FOOTER_SIZE; + std::vector buff(sizeof(uint16_t)); + WriteLE16(buff.data(), zipCommentLen); + PkgBuffer buffer(buff); + ret = outStream->Write(buffer, sizeof(uint16_t), offset); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Fail to write zip eocd comment len"); + return ret; + } + offset += sizeof(uint16_t); + + ret = outStream->Write(p7Data, p7Data.length, offset); + if (ret != PKG_SUCCESS) { + PKG_LOGE("Fail to write pkcs7 signed data"); + return ret; + } + offset += p7Data.length; + + return WriteFooter(outStream, zipCommentLen, offset); +} + +int32_t ZipPkgParse::WriteSourcePackageData(PkgStreamPtr outStream, PkgStreamPtr inStream, size_t wirteLen) const +{ + size_t offset = 0; + size_t remainLen = wirteLen; + size_t blockLen = SOURCE_DATA_WRITE_BLOCK_LEN; + PkgBuffer buffer(blockLen); + size_t readLen = 0; + int32_t ret = PKG_SUCCESS; + while (remainLen >= blockLen) { + ret = inStream->Read(buffer, offset, blockLen, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail read data"); + ret = outStream->Write(buffer, blockLen, offset); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write data"); + + offset += blockLen; + remainLen -= blockLen; + } + if (remainLen > 0) { + ret = inStream->Read(buffer, offset, remainLen, readLen); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail read data"); + ret = outStream->Write(buffer, remainLen, offset); + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write data"); + } + + return ret; +} + +int32_t ZipPkgParse::WriteFooter(PkgStreamPtr outStream, uint16_t zipCommentLen, size_t &offset) const +{ + Footer footer = {0}; + footer.signDataStart = zipCommentLen; + footer.signDataFlag = 0xFFFF; + footer.signDataSize = zipCommentLen; + + std::vector buff(sizeof(Footer)); + WriteLE16(buff.data() + offsetof(Footer, signDataStart), footer.signDataStart); + WriteLE16(buff.data() + offsetof(Footer, signDataFlag), footer.signDataFlag); + WriteLE16(buff.data() + offsetof(Footer, signDataSize), footer.signDataSize); + PkgBuffer buffer(buff); + + return outStream->Write(buffer, sizeof(Footer), offset); +} +} // namespace hpackage diff --git a/services/package/pkg_verify/zip_pkg_parse.h b/services/package/pkg_verify/zip_pkg_parse.h new file mode 100644 index 0000000000000000000000000000000000000000..db6e7efa1e075ff323270372a6d6a3d605caf3a9 --- /dev/null +++ b/services/package/pkg_verify/zip_pkg_parse.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef PKG_PARSE_H +#define PKG_PARSE_H + +#include "pkg_stream.h" +#include "pkg_verify_util.h" + +namespace hpackage { +class ZipPkgParse { +public: + ZipPkgParse() {}; + + ~ZipPkgParse() {}; + + int32_t CheckZipPkg(const hpackage::PkgStreamPtr pkgStream) const; + + int32_t ParseZipPkg(hpackage::PkgStreamPtr pkgStream, size_t &signatureStart, + size_t &signatureSize) const; + + int32_t WriteZipSignedData(hpackage::PkgStreamPtr outStream, + const hpackage::PkgBuffer &p7Data, hpackage::PkgStreamPtr inStream) const; + +private: + int32_t ParsePkgFooter(const uint8_t *footer, size_t length, uint16_t &commentAppendLen, + uint16_t &commentTotalLen) const; + + int32_t WriteSourcePackageData(hpackage::PkgStreamPtr outStream, hpackage::PkgStreamPtr inStream, + size_t wirteLen) const; + + int32_t WriteFooter(hpackage::PkgStreamPtr outStream, uint16_t zipCommentLen, size_t &offset) const; + + int32_t CheckZipEocd(const uint8_t *eocd, size_t length, uint16_t commentTotalLen) const; +}; +} // namespace hpackage +#endif diff --git a/services/ptable_parse/BUILD.gn b/services/ptable_parse/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6359acd57f1b8aae541fd29d8551d57ac1fa8ccc --- /dev/null +++ b/services/ptable_parse/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2022 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. + +import("//build/ohos.gni") +SUBSYSTEM_DIR = "//base/update/updater/services/ptable_parse" + +config("updater_config") { + visibility = [ ":*" ] + include_dirs = [ + "//base/update/updater/services/include", + "//base/update/updater/utils/include", + "//base/update/updater/utils/json", + "//third_party/bounds_checking_function/include", + "//drivers/hdf/frameworks/include/utils", + "//base/update/updater/interfaces/kits/include/", + "//base/update/updater/services/include/script", + "//base/update/updater/services/include/package", + "//base/update/updater/services/include/applypatch", + "//base/update/updater/services/include/log", + ] +} + +ohos_static_library("libptableparse") { + sources = [ + "${SUBSYSTEM_DIR}/ptable.cpp", + "${SUBSYSTEM_DIR}/ptable_manager.cpp", + "${SUBSYSTEM_DIR}/ufs_ptable.cpp", + ] + configs = [ ":updater_config" ] + + ldflags = [ "-Wl -std=c++11" ] + + deps = [ + "//base/update/updater/services/log:libupdaterlog", + "//base/update/updater/utils:libutils", + "//third_party/bzip2:libbz2", + "//third_party/cJSON:cjson_static", + "//third_party/zlib:libz", + ] + + part_name = "updater" +} diff --git a/services/ptable_parse/ptable.cpp b/services/ptable_parse/ptable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0719a6ca6262412a6655f31397ea5f1fb99a8dcf --- /dev/null +++ b/services/ptable_parse/ptable.cpp @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2022 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 "ptable.h" + +#include "applypatch/data_writer.h" +#include "log/log.h" +#include "securec.h" + +namespace updater { +const std::string PTABLE_CONFIG_PATH = "/etc/ptable_data.json"; +const std::string PTABLE_DATA_LABEL = "ptableData"; +const std::string EMMC_GPT_DATA_LEN_LABEL = "emmcGptDataLen"; +const std::string LBA_LEN_LABEL = "lbaLen"; +const std::string GPT_HEADER_LEN_LABEL = "gptHeaderLen"; +const std::string BLOCK_SIZE_LABEL = "blockSize"; +const std::string IMG_LUN_SIZE_LABEL = "imgLuSize"; +const std::string START_LUN_NUM_LABEL = "startLunNumber"; +const std::string WRITE_DEVICE_LUN_SIZE_LABEL = "writeDeviceLunSize"; +const std::string DEFAULT_LUN_NUM_LABEL = "defaultLunNum"; + +std::vector Ptable::GetPtablePartitionInfo() const +{ + return partitionInfo_; +} + +uint32_t Ptable::GetPtablePartitionNum() const +{ + return partitionInfo_.size(); +} + +bool Ptable::InitPtable() +{ + if (!partitionInfo_.empty()) { + std::vector().swap(partitionInfo_); + } + if (!ParsePtableData()) { + LOG(ERROR) << "parse PtableData from json file error"; + return false; + } + return true; +} + +bool Ptable::ParsePtableDataNode(const JsonNode &ptableDataNode) +{ + std::map ptableDataVars = { + {EMMC_GPT_DATA_LEN_LABEL, &ptableData_.emmcGptDataLen}, + {LBA_LEN_LABEL, &ptableData_.lbaLen}, + {GPT_HEADER_LEN_LABEL, &ptableData_.gptHeaderLen}, + {BLOCK_SIZE_LABEL, &ptableData_.blockSize}, + {IMG_LUN_SIZE_LABEL, &ptableData_.imgLuSize}, + {START_LUN_NUM_LABEL, &ptableData_.startLunNumber}, + {WRITE_DEVICE_LUN_SIZE_LABEL, &ptableData_.writeDeviceLunSize}, + {DEFAULT_LUN_NUM_LABEL, &ptableData_.defaultLunNum}, + }; + + for (auto dataVar : ptableDataVars) { + auto dataValue = ptableDataNode[dataVar.first.c_str()].As(); + if (!dataValue) { + LOG(ERROR) << "parse json failed! " << dataVar.first << " is nullptr!"; + return false; + } + *(dataVar.second) = *dataValue; + LOG(ERROR) << "set " << dataVar.first << " : " << *dataValue; + } + return true; +} + +bool Ptable::ParsePtableData() +{ + memset_s(&ptableData_, sizeof(ptableData_), 0, sizeof(ptableData_)); + std::ifstream ifs(std::string {PTABLE_CONFIG_PATH}); + if (!ifs.is_open()) { + LOG(ERROR) << PTABLE_CONFIG_PATH << " not exist"; + return false; + } + + // get root node + std::string content {std::istreambuf_iterator {ifs}, {}}; + cJSONPtr root(cJSON_Parse(content.c_str()), cJSON_Delete); + if (root == nullptr) { + LOG(ERROR) << PTABLE_CONFIG_PATH << " contained json invalid"; + return false; + } + + JsonNode node(root.get(), false); + const JsonNode &ptableDataNode = node[PTABLE_DATA_LABEL]; + bool ret = ParsePtableDataNode(ptableDataNode); + ptableData_.dataValid = ret; + return ret; +} + +uint32_t Ptable::GetDefaultImageSize() const +{ + return ptableData_.emmcGptDataLen + ptableData_.defaultLunNum * ptableData_.imgLuSize; +} + +bool Ptable::CheckFileExist(const std::string &fileName) +{ + struct stat buffers; + if (memset_s(&buffers, sizeof(buffers), 0, sizeof(buffers)) != EOK) { + LOG(WARNING) << "memset_s fail"; + } + if (stat(fileName.c_str(), &buffers) == 0) { + LOG(INFO) << fileName << " is exist"; + return true; + } + LOG(INFO) << fileName << " is not exist"; + return false; +} + +bool Ptable::MemReadWithOffset(const std::string &filePath, const uint64_t offset, + uint8_t *outData, const uint32_t dataSize) +{ + if (filePath.length() == 0 || outData == nullptr || dataSize == 0) { + LOG(ERROR) << "invaild input"; + return false; + } + + std::ifstream fin(filePath, std::ios::in); + if (fin.fail()) { + LOG(ERROR) << "open " << filePath << " fail"; + return false; + } + + fin.seekg(offset, std::ios::beg); + if (fin.tellg() != offset) { + LOG(ERROR) << "seekp 0x" << std::hex << offset << " bytes in " << filePath << + " failed. Now is in 0x" << std::hex << fin.tellg() << std::dec; + fin.close(); + return false; + } + + if (!fin.read((char *)(outData), dataSize)) { + LOG(ERROR) << "read 0x" << std::hex << dataSize << " bytes in " << filePath << + " failed. only read 0x" << std::hex << fin.gcount() << std::dec; + fin.close(); + return false; + } + fin.close(); + return true; +} + +uint32_t Ptable::Reflect(uint32_t data, const uint32_t len) +{ + uint32_t ref = 0; + for (auto i = 0; i < len; i++) { + if (data & 0x1) { + ref |= (1 << ((len - 1) - i)); + } + data = (data >> 1); + } + return ref; +} + +uint32_t Ptable::CalculateCrc32(const uint8_t *buffer, const uint32_t len) +{ + if (buffer == nullptr || len == 0) { + LOG(INFO) << "invaild input"; + return 0; + } + const uint32_t byteLen = 8; // 8:length of unit (i.e. byte) + uint32_t msb; + const uint64_t polynomial = 0x104C11DB7LL; // IEEE 32bit polynomial + uint32_t regs = 0xFFFFFFFF; // init to all ones + const uint32_t regsMask = 0xFFFFFFFF; // ensure only 32 bit answer + uint32_t regsMsb; + for (auto i = 0; i < len; i++) { + uint32_t dataByte = buffer[i]; + dataByte = Reflect(dataByte, 8); // 8:length of unit (i.e. byte) + for (auto j = 0; j < byteLen; j++) { + msb = dataByte >> (byteLen - 1); // get MSB + msb &= 1; // ensure just 1 bit + regsMsb = (regs >> 31) & 1; // 31:32-1, MSB of regs + regs = regs << 1; // shift regs for CRC-CCITT + if (regsMsb ^ msb) { // MSB is a 1 + regs = regs ^ polynomial; // XOR with generator poly + } + regs = regs & regsMask; // Mask off excess upper bits + dataByte <<= 1; // get to next bit + } + } + regs = regs & regsMask; + uint32_t ret = Reflect(regs, 32) ^ 0xFFFFFFFF; // 32:32bit + return ret; +} + +bool Ptable::VerifyMbrMagicNum(const uint8_t *buffer, const uint32_t size) +{ + // avoid checking past end of buffer + if (size < (MBR_MAGIC_NUM_POS + 1)) { + LOG(ERROR) << "size < (TABLE_SIGNATURE + 1)"; + return false; + } + // check to see if magic number(0x55AA) exists at pos 0x1FE + if ((buffer[MBR_MAGIC_NUM_POS] != MBR_MAGIC_NUM_0) || + (buffer[MBR_MAGIC_NUM_POS + 1] != MBR_MAGIC_NUM_1)) { + LOG(ERROR) << "MBR magic number does not match, magic buffer is " << *(buffer + MBR_MAGIC_NUM_POS); + return false; + } + return true; +} + +bool Ptable::CheckProtectiveMbr(const uint8_t *gptImage, const uint32_t imgLen) +{ + if (!VerifyMbrMagicNum(gptImage, imgLen)) { + LOG(ERROR) << "MBR magic number verify failed!"; + return false; + } + + // process each of the four partitions in the MBR, find a Protective MBR(0xEE) + uint32_t type; + for (uint32_t i = 0; i < MBR_GPT_MAX_NUM; i++) { + // type 0xEE indicates the protective MBR and GPT partitions exist + if (MBR_GPT_ENTRY + i * MBR_GPT_ENTRY_SIZE + GPT_TYPE_SIGN_OFFSET >= imgLen) { + LOG(INFO) << "not find Protective MBR(type: 0xEE) in this partition"; + return false; + } + type = gptImage[MBR_GPT_ENTRY + i * MBR_GPT_ENTRY_SIZE + GPT_TYPE_SIGN_OFFSET]; + if (type == MBR_PROTECTIVE_GPT_TYPE) { + LOG(INFO) << "type is MBR_PROTECTIVE_GPT_TYPE(0xEE), GPT partitions exist"; + return true; + } + LOG(INFO) << "the " << i << " main GPT's type=0x" << std::hex << type << std::dec; + } + LOG(INFO) << "not find Protective MBR(type: 0xEE) in this partition"; + return false; +} + +bool Ptable::CheckIfValidGpt(const uint8_t *gptImage, const uint32_t gptImageLen) +{ + // 8 is the length of EFI_MAGIC_NUMBER + if (gptImageLen < 8) { + LOG(ERROR) << "gptImageLen is less than 8."; + return false; + } + // get magic number + uint64_t gptMagic = GET_LLWORD_FROM_BYTE(gptImage); + if (gptMagic != EFI_MAGIC_NUMBER) { + LOG(ERROR) << "invaild partiton with gptMagic:0x" << std::hex << gptMagic << std::dec; + return false; + } + return true; +} + +bool Ptable::GetCapacity(const std::string &filePath, uint64_t &lunCapacity) +{ + if (filePath.empty()) { + LOG(ERROR) << "filePath is empty or lunCapacity is nullptr"; + return false; + } + std::ifstream fin(filePath, std::ios::in); + if (!fin.is_open()) { + LOG(ERROR) << "open " << filePath << " fail"; + return false; + } + + uint64_t sector = 0; + fin >> sector; + if (sector == 0) { + LOG(ERROR) << "read data from " << filePath << " fail"; + fin.close(); + return false; + } + + uint64_t capacity = sector * SECTOR_SIZE; + LOG(INFO) << "lun capacity = 0x" << std::hex << capacity << std::dec; + lunCapacity = capacity; + fin.close(); + return true; +} + +bool Ptable::GetPartitionGptHeaderInfo(const uint8_t *buffer, const uint32_t bufferLen, GPTHeaderInfo& gptHeaderInfo) +{ + if (buffer == nullptr || bufferLen < LBA_LENGTH) { + LOG(ERROR) << "input invalid"; + return false; + } + + // Check GPT Signature + if (!CheckIfValidGpt(buffer, bufferLen)) { + LOG(ERROR) << "invaild partiton with gptMagic"; + return false; + } + gptHeaderInfo.headerSize = GET_LWORD_FROM_BYTE(buffer + HEADER_SIZE_OFFSET); + gptHeaderInfo.firstUsableLba = GET_LLWORD_FROM_BYTE(buffer + FIRST_USABLE_LBA_OFFSET); + gptHeaderInfo.maxPartitionCount = GET_LWORD_FROM_BYTE(buffer + PARTITION_COUNT_OFFSET); + gptHeaderInfo.partitionEntrySize = GET_LWORD_FROM_BYTE(buffer + PENTRY_SIZE_OFFSET); + if (gptHeaderInfo.maxPartitionCount == 0 || gptHeaderInfo.partitionEntrySize == 0) { + LOG(ERROR) << "invalid gpt header info"; + return false; + } + return true; +} + +bool Ptable::CheckGptHeader(uint8_t *buffer, const uint32_t bufferLen, const uint64_t lbaNum, + GPTHeaderInfo& gptHeaderInfo) +{ + if (bufferLen < LBA_LENGTH || lbaNum == 0) { + LOG(ERROR) << "bufferLen < LBA_LENGTH || lbaNum == 0"; + return false; + } + + if (gptHeaderInfo.headerSize < GPT_HEADER_SIZE || gptHeaderInfo.headerSize > bufferLen) { + LOG(ERROR) << "GPT Header size is invaild"; + return false; + } + uint32_t orgCrcVal = GET_LWORD_FROM_BYTE(buffer + HEADER_CRC_OFFSET); + // Write CRC field to 0 before calculating the crc of the whole rest of GPT header + PUT_LONG(buffer + HEADER_CRC_OFFSET, 0); + uint32_t crcVal = CalculateCrc32(buffer, gptHeaderInfo.headerSize); + if (crcVal != orgCrcVal) { + LOG(ERROR) << "Header crc mismatch crcVal = " << std::hex << crcVal << " with orgCrcVal = " << + orgCrcVal << std::dec; + return false; + } + PUT_LONG(buffer + HEADER_CRC_OFFSET, crcVal); + + uint32_t currentLba = GET_LLWORD_FROM_BYTE(buffer + PRIMARY_HEADER_OFFSET); + uint32_t lastUsableLba = GET_LLWORD_FROM_BYTE(buffer + LAST_USABLE_LBA_OFFSET); + uint32_t partition0 = GET_LLWORD_FROM_BYTE(buffer + PARTITION_ENTRIES_OFFSET); + + // check for first and last lba range + if (gptHeaderInfo.firstUsableLba > lbaNum || lastUsableLba > lbaNum) { + LOG(ERROR) << "invalid usable lba " << gptHeaderInfo.firstUsableLba << ", last is " << lastUsableLba << + " lbaNum is " << lbaNum; + return false; + } + // check for partition entry size + if (gptHeaderInfo.partitionEntrySize != PARTITION_ENTRY_SIZE || + gptHeaderInfo.maxPartitionCount > (MIN_PARTITION_ARRAY_SIZE / PARTITION_ENTRY_SIZE)) { + LOG(ERROR) << "invalid parition entry size or max count"; + return false; + } + // GPT header should always be the 0x1 LBA, partition entry should always the 0x2 LBA + if (currentLba != 0x1 || partition0 != 0x2) { + LOG(ERROR) << "starting LBA mismatch"; + return false; + } + LOG(INFO) << "ufs gpt header check ok"; + return true; +} + +bool Ptable::PartitionCheckGptHeader(const uint8_t *gptImage, const uint32_t len, const uint64_t lbaNum, + const uint32_t blockSize, GPTHeaderInfo& gptHeaderInfo) +{ + if (len < ptableData_.writeDeviceLunSize || lbaNum == 0) { + LOG(ERROR) << "len < ptableData_.writeDeviceLunSize || lbaNum == 0"; + return false; + } + + uint8_t *buffer = new(std::nothrow) uint8_t[blockSize](); + if (buffer == nullptr) { + LOG(ERROR) << "new buffer failed!"; + return false; + } + if (memcpy_s(buffer, blockSize, gptImage + blockSize, blockSize) != EOK) { + LOG(ERROR) << "copy gpt header fail"; + delete [] buffer; + return false; + } + + if (!CheckGptHeader(buffer, blockSize, lbaNum, gptHeaderInfo)) { + LOG(ERROR) << "CheckGptHeader fail"; + delete [] buffer; + return false; + } + + uint32_t partition0 = GET_LLWORD_FROM_BYTE(&buffer[PARTITION_ENTRIES_OFFSET]); + uint32_t orgCrcVal = GET_LWORD_FROM_BYTE(&buffer[PARTITION_CRC_OFFSET]); + delete [] buffer; + + uint32_t crcVal = CalculateCrc32(gptImage + partition0 * blockSize, + gptHeaderInfo.maxPartitionCount * gptHeaderInfo.partitionEntrySize); + if (crcVal != orgCrcVal) { + LOG(ERROR) << "partition entires crc mismatch crcVal =" << std::hex << crcVal << " with orgCrcVal =" << + orgCrcVal << std::dec; + return false; + } + LOG(INFO) << "UfsPartitionCheckGptHeader ok"; + return true; +} + +void Ptable::PrintPtableInfo() const +{ + if (partitionInfo_.empty()) { + LOG(ERROR) << "ptable vector is empty!"; + return; + } + + LOG(INFO) << "ptnInfo : ==========================================="; + LOG(INFO) << "partition count = " << std::dec << partitionInfo_.size(); + for (size_t i = 0; i < partitionInfo_.size(); i++) { + LOG(INFO) << "ptable.entry[" << i << "].name=" << partitionInfo_[i].dispName.c_str() << + ", startAddr=0x" << std::hex << partitionInfo_[i].startAddr << ", size=0x" << + partitionInfo_[i].partitionSize << ", lun=" << std::dec << partitionInfo_[i].lun; + } + LOG(INFO) << "ptnInfo : ==========================================="; +} + +void Ptable::PrintPtableInfo(const std::vector &ptnInfo) const +{ + if (ptnInfo.empty()) { + LOG(ERROR) << "ptable vector is empty!"; + return; + } + + LOG(INFO) << "ptnInfo : ==========================================="; + LOG(INFO) << "partition count = " << std::dec << ptnInfo.size(); + for (size_t i = 0; i < ptnInfo.size(); i++) { + LOG(INFO) << "ptable.entry[" << i << "].name=" << ptnInfo[i].dispName.c_str() << ", startAddr=0x" << + std::hex << ptnInfo[i].startAddr << ", size=0x" << ptnInfo[i].partitionSize << ", lun=" << + std::dec << ptnInfo[i].lun; + } + LOG(INFO) << "ptnInfo : ==========================================="; +} + +void Ptable::ParsePartitionName(const uint8_t *data, const uint32_t dataLen, + std::string &name, const uint32_t nameLen) +{ + if (data == nullptr || dataLen == 0 || nameLen == 0) { + LOG(ERROR) << "dataLen == 0 || nameLen == 0"; + return; + } + char utf16Name[MAX_GPT_NAME_SIZE] = {0}; + if (memcpy_s(utf16Name, sizeof(utf16Name), data, dataLen) != EOK) { + LOG(ERROR) << "memcpy name fail"; + return; + } + + std::string outName; + // convert utf8 to utf16, 2 bytes for 1 charactor of partition name + for (uint32_t n = 0; n < nameLen && n < (MAX_GPT_NAME_SIZE / 2) && utf16Name[n * 2] != '\0'; n++) { + outName = outName + utf16Name[n * 2]; + } + for (uint32_t i = 0; i < outName.size(); i++) { + outName[i] = static_cast(toupper(outName[i])); + } + name = outName; + return; +} + +bool Ptable::WriteBufferToPath(const std::string &path, const uint64_t offset, + const uint8_t *buffer, const uint32_t size) +{ + std::unique_ptr writer = DataWriter::CreateDataWriter(WRITE_RAW, path, offset); + if (writer == nullptr) { + LOG(ERROR) << "create writer class failed!"; + return false; + } + bool ret = writer->Write(buffer, size); + if (!ret) { + LOG(ERROR) << "writer to " << path << " with offset " << offset << " failed "; + DataWriter::ReleaseDataWriter(writer); + return false; + } + DataWriter::ReleaseDataWriter(writer); + return true; +} + +void Ptable::SetPartitionName(const std::string &name, uint8_t *data, const uint32_t size) +{ + if (data == nullptr || size == 0) { + LOG(ERROR) << "invalid input"; + return; + } + // convert utf8 to utf16, 2 bytes for 1 charactor of partition name + if (name.length() * 2 >= MAX_GPT_NAME_SIZE) { + LOG(ERROR) << "name size too large"; + return; + } + + char utf16Name[MAX_GPT_NAME_SIZE] = {0}; + for (uint32_t i = 0; i <= name.length(); i++) { + // convert utf8 to utf16, 2 bytes for 1 charactor of partition name + utf16Name[i * 2] = static_cast(tolower(name[i])); + } + if (memcpy_s(data, size, utf16Name, sizeof(utf16Name)) != EOK) { + LOG(ERROR) << "copy name failed"; + } + return; +} + +bool Ptable::GetPartionInfoByName(const std::string &partitionName, PtnInfo &ptnInfo, int32_t &index) +{ + if (partitionInfo_.empty()) { + LOG(ERROR) << "get partition failed! partitionInfo_ is empty"; + return false; + } + for (int32_t i = 0; i < static_cast(partitionInfo_.size()); i++) { + if (partitionInfo_[i].dispName.size() == partitionName.size() && + strcasecmp(partitionInfo_[i].dispName.c_str(), partitionName.c_str()) == 0) { + index = i; + ptnInfo = partitionInfo_[i]; + return true; + } + } + LOG(ERROR) << "get partition info failed! Not found partition:" << partitionName; + return false; +} +} // namespace updater \ No newline at end of file diff --git a/services/ptable_parse/ptable.h b/services/ptable_parse/ptable.h new file mode 100644 index 0000000000000000000000000000000000000000..e627a6f36f558daea938c660b1f5e825adc56c21 --- /dev/null +++ b/services/ptable_parse/ptable.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef UPDATER_PTABLE_H +#define UPDATER_PTABLE_H + +#include "macros.h" +#include "json_node.h" + +namespace updater { +class Ptable { +public: + Ptable() = default; + DISALLOW_COPY_MOVE(Ptable); + virtual ~Ptable() {} + + static constexpr uint32_t GPT_PARTITION_TYPE_GUID_LEN = 16; + const std::string PREFIX_UFS_NODE = "/dev/block/sd"; + const std::string PREFIX_SYS_CLASS_BLOCK = "/sys/class/block/sd"; + + struct PtnInfo { + uint64_t startAddr; + uint64_t partitionSize; + uint8_t partitionTypeGuid[GPT_PARTITION_TYPE_GUID_LEN]; + uint32_t lun; + std::string dispName; + }; + + std::vector GetPtablePartitionInfo() const; + uint32_t GetPtablePartitionNum() const; + bool InitPtable(); + uint32_t GetDefaultImageSize() const; + void PrintPtableInfo() const; + void PrintPtableInfo(const std::vector &ptnInfo) const; + bool GetPartionInfoByName(const std::string &partitionName, PtnInfo &ptnInfo, int32_t &index); + + virtual bool ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize) = 0; + virtual bool LoadPtableFromDevice() = 0; + virtual bool WritePartitionTable() = 0; + +protected: + const std::string USERDATA_PARTITION = "USERDATA"; + static constexpr uint32_t PARTITION_ENTRY_SIZE = 128; + static constexpr uint32_t MAX_PARTITION_NUM = 128; + static constexpr uint32_t FIRST_LBA_OFFSET = 32; + static constexpr uint32_t LAST_LBA_OFFSET = 40; + static constexpr uint32_t GPT_PARTITION_NAME_OFFSET = 56; + static constexpr uint32_t MAX_GPT_NAME_SIZE = 72; + static constexpr uint32_t PARTITION_ENTRIES_OFFSET = 72; + static constexpr uint32_t PARTITION_CRC_OFFSET = 88; + static constexpr uint32_t GPT_DISP_NAME_LEN = 32; + static constexpr uint64_t DEFAULT_SECTOR_NUM = (4 * 1024 * 1024 * 2 - 1); + static constexpr uint32_t BACKUP_HEADER_OFFSET = 32; + static constexpr uint32_t LAST_USABLE_LBA_OFFSET = 48; + static constexpr uint32_t PARTITION_ENTRY_LAST_LBA = 40; + static constexpr uint32_t PARTITION_COUNT_OFFSET = 80; + static constexpr uint32_t PENTRY_SIZE_OFFSET = 84; + static constexpr uint32_t HEADER_CRC_OFFSET = 16; + static constexpr uint32_t GPT_CRC_LEN = 92; + static constexpr uint32_t GPT_ENTRYS_SIZE = 128 * 128; + + // set 32 bits data + inline void PUT_LONG(uint8_t *x, const uint32_t y) + { + *(x) = (y) & 0xff; + *((x) + 1) = ((y) >> 8) & 0xff; + *((x) + 2) = ((y) >> 16) & 0xff; + *((x) + 3) = ((y) >> 24) & 0xff; + } + + // set 64 bits data + inline void PUT_LONG_LONG(uint8_t *x, const uint64_t y) + { + *(x) = (y) & 0xff; + *((x) + 1) = (((y) >> 8) & 0xff); + *((x) + 2) = (((y) >> 16) & 0xff); + *((x) + 3) = (((y) >> 24) & 0xff); + *((x) + 4) = (((y) >> 32) & 0xff); + *((x) + 5) = (((y) >> 40) & 0xff); + *((x) + 6) = (((y) >> 48) & 0xff); + *((x) + 7) = (((y) >> 56) & 0xff); + } + + // LWORD = 4 bytes (32 bits) + inline uint32_t GET_LWORD_FROM_BYTE(const uint8_t *x) + { + uint32_t res = (unsigned int)*(x) | + ((unsigned int)*(x + 1) << 8) | + ((unsigned int)*(x + 2) << 16) | + ((unsigned int)*(x + 3) << 24); + return res; + } + + // LLWORD = 8 bytes (64 bits) + inline uint64_t GET_LLWORD_FROM_BYTE(const uint8_t *x) + { + uint64_t res = (unsigned long long)*(x) | + ((unsigned long long)*(x + 1) << 8) | + ((unsigned long long)*(x + 2) << 16) | + ((unsigned long long)*(x + 3) << 24) | + ((unsigned long long)*(x + 4) << 32) | + ((unsigned long long)*(x + 5) << 40) | + ((unsigned long long)*(x + 6) << 48) | + ((unsigned long long)*(x + 7) << 56); + return res; + } + + struct GPTHeaderInfo { + uint32_t headerSize; + uint32_t partitionEntrySize; + uint32_t maxPartitionCount; + uint64_t firstUsableLba; + }; + + struct PtableData { + bool dataValid; + uint32_t emmcGptDataLen; + uint32_t lbaLen; + uint32_t gptHeaderLen; + uint32_t blockSize; + uint32_t imgLuSize; + uint32_t startLunNumber; + uint32_t writeDeviceLunSize; + uint32_t defaultLunNum; + }; + + std::vector partitionInfo_; + PtableData ptableData_; + + PtableData GetPtableData() const; + bool MemReadWithOffset(const std::string &filePath, const uint64_t offset, + uint8_t *outData, const uint32_t dataSize); + bool CheckProtectiveMbr(const uint8_t *gptImage, const uint32_t imgLen); + bool CheckIfValidGpt(const uint8_t *gptImage, const uint32_t gptImageLen); + bool GetCapacity(const std::string &filePath, uint64_t &lunCapacity); + bool GetPartitionGptHeaderInfo(const uint8_t *buffer, const uint32_t bufferLen, GPTHeaderInfo& gptHeaderInfo); + bool PartitionCheckGptHeader(const uint8_t *gptImage, const uint32_t len, const uint64_t lbaNum, + const uint32_t blockSize, GPTHeaderInfo& gptHeaderInfo); + void ParsePartitionName(const uint8_t *data, const uint32_t dataLen, + std::string &name, const uint32_t nameLen); + uint32_t CalculateCrc32(const uint8_t *buffer, const uint32_t len); + bool WritePtablePartition(const std::string &path, uint64_t offset, const uint8_t *buffer, uint32_t size); + bool CheckFileExist(const std::string &fileName); + bool WriteBufferToPath(const std::string &path, const uint64_t offset, const uint8_t *buffer, const uint32_t size); + +private: + static constexpr uint64_t MBR_MAGIC_NUM_POS = 0x1FE; + static constexpr uint8_t MBR_MAGIC_NUM_0 = 0x55; + static constexpr uint8_t MBR_MAGIC_NUM_1 = 0xAA; + static constexpr uint32_t MBR_GPT_MAX_NUM = 4; // one disk has most 4 main partitions + static constexpr uint32_t MBR_GPT_ENTRY = 0x1BE; + static constexpr uint32_t MBR_GPT_ENTRY_SIZE = 0x010; + static constexpr uint32_t GPT_TYPE_SIGN_OFFSET = 0x04; + static constexpr uint32_t MBR_PROTECTIVE_GPT_TYPE = 0xEE; + static constexpr uint64_t EFI_MAGIC_NUMBER = 0x5452415020494645; // GPT SIGNATURE(8 bytes), little-end, (EFI PART) + static constexpr uint32_t SECTOR_SIZE = 512; + static constexpr uint32_t LBA_LENGTH = SECTOR_SIZE; + static constexpr uint32_t HEADER_SIZE_OFFSET = 12; + static constexpr uint32_t FIRST_USABLE_LBA_OFFSET = 40; + static constexpr uint32_t GPT_HEADER_SIZE = 92; + static constexpr uint32_t PRIMARY_HEADER_OFFSET = 24; + static constexpr uint32_t MIN_PARTITION_ARRAY_SIZE = 0x4000; + + bool VerifyMbrMagicNum(const uint8_t *buffer, const uint32_t size); + uint32_t Reflect(uint32_t data, const uint32_t len); + + bool CheckGptHeader(uint8_t *buffer, const uint32_t bufferLen, const uint64_t lbaNum, + GPTHeaderInfo& gptHeaderInfo); + void SetPartitionName(const std::string &name, uint8_t *data, const uint32_t size); + bool ParsePtableDataNode(const JsonNode &ptableDataNode); + bool ParsePtableData(); +}; +} // namespace updater +#endif // UPDATER_PTABLE_H \ No newline at end of file diff --git a/services/ptable_parse/ptable_manager.cpp b/services/ptable_parse/ptable_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..183cf9f252ea838d46b4b845c23f8bc422ab3567 --- /dev/null +++ b/services/ptable_parse/ptable_manager.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2022 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 "ptable_manager.h" + +#include "log/log.h" +#include "securec.h" + +namespace updater { +// class PtableManager +PtableManager::PtableManager() : pPtable_(nullptr) +{ + InitPtablePtr(); +} + +PtableManager::StorageType PtableManager::GetDeviceStorageType() +{ + return storage_; +} + +void PtableManager::SetDeviceStorageType() +{ + if (storage_ != StorageType::STORAGE_UNKNOWN) { + return; + } + if (IsUfsDevice()) { + storage_ = StorageType::STORAGE_UFS; + LOG(INFO) << "is UFS DEVICE"; + } else { + storage_ = StorageType::STORAGE_EMMC; + LOG(INFO) << "is EMMC DEVICE"; + } +} + +bool PtableManager::IsUfsDevice() +{ + return true; +} + +void PtableManager::ReloadDevicePartition(hpackage::PkgManager *pkgManager) +{ + return LoadPartitionInfo(pkgManager); +} + +void PtableManager::InitPtablePtr() +{ + SetDeviceStorageType(); + if (pPtable_ == nullptr) { + if (GetDeviceStorageType() == StorageType::STORAGE_UFS) { + pPtable_ = std::make_unique(); + } else { + pPtable_ = nullptr; + } + } +} + +bool PtableManager::InitPtableManager() +{ + if (pPtable_ == nullptr) { + LOG(ERROR) << "pPtable_ is nullptr"; + return false; + } + if (!pPtable_->InitPtable()) { + LOG(ERROR) << "init ptable error"; + return false; + } + return true; +} + +int32_t PtableManager::GetPartitionInfoIndexByName(const std::vector &ptnInfo, + const std::string &name) +{ + if (ptnInfo.empty() || name.size() == 0) { + LOG(ERROR) << "invalid input: ptnInfo is empty or name is null"; + return -1; + } + + for (size_t i = 0; i < ptnInfo.size(); i++) { + if (ptnInfo[i].dispName == name) { + return i; + } + } + return -1; +} + +bool PtableManager::IsPartitionChanged(const std::vector &devicePtnInfo, + const std::vector &pkgPtnInfo, const std::string &partitionName) +{ + if (pkgPtnInfo.empty()) { + LOG(INFO) << "No ptable in package. Ptable no changed!"; + return false; + } + if (devicePtnInfo.empty()) { + LOG(WARNING) << "ptable sizes in device and package are different, partition is changed"; + return true; + } + int32_t deviceIndex = GetPartitionInfoIndexByName(devicePtnInfo, partitionName); + if (deviceIndex < 0) { + LOG(ERROR) << "can't find the " << partitionName << " partition in device ptable!"; + return true; + } + int32_t updateIndex = GetPartitionInfoIndexByName(pkgPtnInfo, partitionName); + if (updateIndex < 0) { + LOG(ERROR) << "can't find the " << partitionName << " partition in package ptable!"; + return true; + } + bool ret = false; + if (devicePtnInfo[deviceIndex].startAddr != pkgPtnInfo[updateIndex].startAddr) { + LOG(INFO) << partitionName << " start address is changed:"; + LOG(INFO) << "[" << partitionName << "]: device ptable[" << deviceIndex << "] startAddr = 0x" << + devicePtnInfo[deviceIndex].startAddr << ", in package ptable[" << updateIndex << "] startAddr is 0x" << + pkgPtnInfo[updateIndex].startAddr; + ret = true; + } + if (devicePtnInfo[deviceIndex].partitionSize != pkgPtnInfo[updateIndex].partitionSize) { + LOG(INFO) << partitionName << " partition size is changed:"; + LOG(INFO) << "[" << partitionName << "]: device ptable[" << deviceIndex << "] partitionSize = 0x" << + devicePtnInfo[deviceIndex].partitionSize << ", in package ptable[" << updateIndex << + "] partitionSize is 0x" << pkgPtnInfo[updateIndex].partitionSize; + ret = true; + } + return ret; +} + +bool PtableManager::IsPtableChanged(const std::vector &devicePtnInfo, + const std::vector &pkgPtnInfo) +{ + if (pkgPtnInfo.empty()) { + LOG(INFO) << "No ptable in package. Ptable no changed!"; + return false; + } + if (devicePtnInfo.empty() || pkgPtnInfo.size() != devicePtnInfo.size()) { + LOG(WARNING) << "ptable sizes in device and package are different, ptable is changed"; + return true; + } + for (size_t i = 0; i < pkgPtnInfo.size(); i++) { + if (devicePtnInfo[i].dispName != pkgPtnInfo[i].dispName) { + LOG(WARNING) << "module_name in ptable is different:"; + LOG(WARNING) << "ptable NAME in device is " << devicePtnInfo[i].dispName << + ", in package is " << pkgPtnInfo[i].dispName; + return true; + } + if (devicePtnInfo[i].startAddr != pkgPtnInfo[i].startAddr) { + LOG(WARNING) << pkgPtnInfo[i].dispName << " start address is different:"; + LOG(WARNING) << "Device ptable [" << devicePtnInfo[i].dispName << "] startAddr is 0x" << + devicePtnInfo[i].startAddr; + LOG(WARNING) << "Package ptable [" << pkgPtnInfo[i].dispName << "] startAddr is 0x" << + pkgPtnInfo[i].startAddr; + return true; + } + if (devicePtnInfo[i].partitionSize != pkgPtnInfo[i].partitionSize) { + LOG(WARNING) << pkgPtnInfo[i].dispName << " partition size is different:"; + LOG(WARNING) << "Device ptable [" << devicePtnInfo[i].dispName << "] partitionSize is 0x" << + devicePtnInfo[i].partitionSize; + LOG(WARNING) << "Package ptable [" << pkgPtnInfo[i].dispName << "] partitionSize is 0x" << + pkgPtnInfo[i].partitionSize; + return true; + } + } + return false; +} + +bool PtableManager::WritePtableToDevice() +{ + if (pPtable_ == nullptr) { + LOG(ERROR) << "Write ptable to device failed! pPtable_ is nullptr"; + return false; + } + if (!pPtable_->WritePartitionTable()) { + LOG(ERROR) << "Write ptable to device failed! Please load ptable first!"; + return false; + } + LOG(INFO) << "Write ptable to device success!"; + return true; +} + +void PtableManager::PrintPtableInfo() +{ + if (pPtable_ != nullptr) { + LOG(ERROR) << "print partition info:"; + pPtable_->PrintPtableInfo(); + return; + } + + LOG(INFO) << "print partition info failed!"; + return; +} + +bool PtableManager::GetPartionInfoByName(const std::string &partitionName, Ptable::PtnInfo &ptnInfo, int32_t &index) +{ + if (pPtable_ == nullptr) { + LOG(ERROR) << "GetPartionInfoByName failed! pPtable_ is nullptr"; + return false; + } + std::string standardPtnName = partitionName; + standardPtnName.erase(std::remove(standardPtnName.begin(), standardPtnName.end(), '/'), standardPtnName.end()); + if (pPtable_->GetPartionInfoByName(standardPtnName, ptnInfo, index)) { + LOG(INFO) << "GetPartionInfoByName success!"; + return true; + } + LOG(ERROR) << "GetPartionInfoByName failed! Not found " << standardPtnName; + return false; +} + +bool PtableManager::GetPartionInfoByName(const std::string &partitionName, Ptable::PtnInfo &ptnInfo) +{ + int32_t index = -1; + return GetPartionInfoByName(partitionName, ptnInfo, index); +} + +// class PackagePtable +PackagePtable::PackagePtable() : PtableManager() {} + +void PackagePtable::LoadPartitionInfo([[maybe_unused]] hpackage::PkgManager *pkgManager) +{ + if (pkgManager == nullptr) { + LOG(ERROR) << "pkgManager is nullptr"; + return; + } + if (!InitPtableManager()) { + LOG(ERROR) << "init ptable manager error"; + return; + } + + uint32_t imgBufSize = pPtable_->GetDefaultImageSize(); + PKG_CHECK(imgBufSize > 0, return, "Invalid imgBufSize"); + uint8_t *imageBuf = new(std::nothrow) uint8_t[imgBufSize](); + + if (imageBuf == nullptr) { + LOG(ERROR) << "new ptable_buffer error"; + return; + } + if (!GetPtableBufferFromPkg(pkgManager, imageBuf, imgBufSize)) { + LOG(ERROR) << "get ptable buffer failed"; + delete [] imageBuf; + return; + } + + if (!pPtable_->ParsePartitionFromBuffer(imageBuf, imgBufSize)) { + LOG(ERROR) << "get ptable from ptable image buffer failed"; + delete [] imageBuf; + return; + } + delete [] imageBuf; + LOG(INFO) << "print package partition info:"; + pPtable_->PrintPtableInfo(); + return; +} + +bool PackagePtable::GetPtableBufferFromPkg(hpackage::PkgManager *pkgManager, uint8_t *&imageBuf, uint32_t size) +{ + if (pkgManager == nullptr) { + LOG(ERROR) << "pkgManager is nullptr"; + return false; + } + + std::string ptableName = "/ptable"; + const hpackage::FileInfo *info = pkgManager->GetFileInfo(ptableName); + if (info == nullptr) { + LOG(ERROR) << "Can not get file info " << ptableName; + return false; + } + hpackage::PkgManager::StreamPtr outStream = nullptr; + (void)pkgManager->CreatePkgStream(outStream, ptableName, info->unpackedSize, + hpackage::PkgStream::PkgStreamType_MemoryMap); + if (outStream == nullptr) { + LOG(ERROR) << "Error to create output stream"; + return false; + } + + if (pkgManager->ExtractFile(ptableName, outStream) != hpackage::PKG_SUCCESS) { + LOG(ERROR) << "Error to extract ptable"; + pkgManager->ClosePkgStream(outStream); + return false; + } + + size_t bufSize = 0; + uint8_t* buffer = nullptr; + outStream->GetBuffer(buffer, bufSize); + if (memcpy_s(imageBuf, size, buffer, std::min((size_t)size, bufSize))) { + LOG(ERROR) << "memcpy to imageBuf fail"; + pkgManager->ClosePkgStream(outStream); + return false; + } + pkgManager->ClosePkgStream(outStream); + return true; +} + +// class DevicePtable +DevicePtable::DevicePtable() : PtableManager() {} + +void DevicePtable::LoadPartitionInfo([[maybe_unused]] hpackage::PkgManager *pkgManager) +{ + (void)pkgManager; + if (!InitPtableManager()) { + LOG(ERROR) << "init ptable manager error"; + return; + } + if (!pPtable_->LoadPtableFromDevice()) { + LOG(ERROR) << "load device parititon to ram fail"; + return; + } + + LOG(INFO) << "print device partition info:"; + pPtable_->PrintPtableInfo(); + return; +} + +bool DevicePtable::ComparePartition(PtableManager &newPtbManager, std::string partitionName) +{ + if (pPtable_ == nullptr || newPtbManager.pPtable_ == nullptr) { + LOG(ERROR) << "input pPtable point is nullptr, compare failed!"; + return false; + } + if (IsPartitionChanged(pPtable_->GetPtablePartitionInfo(), + newPtbManager.pPtable_->GetPtablePartitionInfo(), partitionName)) { + LOG(INFO) << partitionName << " are different"; + return true; + } + LOG(INFO) << partitionName << " are the same"; + return false; +} + +bool DevicePtable::ComparePtable(PtableManager &newPtbManager) +{ + if (pPtable_ == nullptr || newPtbManager.pPtable_ == nullptr) { + LOG(ERROR) << "input pPtable point is nullptr, compare failed!"; + return false; + } + if (IsPtableChanged(pPtable_->GetPtablePartitionInfo(), + newPtbManager.pPtable_->GetPtablePartitionInfo())) { + LOG(INFO) << "two ptables are different"; + return true; + } + LOG(INFO) << "two ptables are the same"; + return false; +} +} // namespace updater \ No newline at end of file diff --git a/services/ptable_parse/ptable_manager.h b/services/ptable_parse/ptable_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..064115187694fe9743e939ccaf846e19ea13d319 --- /dev/null +++ b/services/ptable_parse/ptable_manager.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef UPDATER_PTABLE_MANAGER_H +#define UPDATER_PTABLE_MANAGER_H + +#include "package/pkg_manager.h" + +namespace updater { +class PtableManager { +public: + DISALLOW_COPY_MOVE(PtableManager); + virtual ~PtableManager() {} + + enum class StorageType { + STORAGE_UNKNOWN, + STORAGE_EMMC, + STORAGE_UFS, + }; + + virtual void LoadPartitionInfo([[maybe_unused]] hpackage::PkgManager *pkgManager = nullptr) = 0; + void ReloadDevicePartition(hpackage::PkgManager *pkgManager); + bool WritePtableToDevice(); + void PrintPtableInfo(); + bool GetPartionInfoByName(const std::string &partitionName, Ptable::PtnInfo &ptnInfo, int32_t &index); + bool GetPartionInfoByName(const std::string &partitionName, Ptable::PtnInfo &ptnInfo); + + std::unique_ptr pPtable_; + StorageType storage_ = StorageType::STORAGE_UNKNOWN; + +protected: + PtableManager(); + void InitPtablePtr(); + bool InitPtableManager(); + void SetDeviceStorageType(); + bool IsUfsDevice(); + bool IsPartitionChanged(const std::vector &devicePtnInfo, + const std::vector &pkgPtnInfo, const std::string &partitionName); + bool IsPtableChanged(const std::vector &devicePtnInfo, + const std::vector &pkgPtnInfo); + int32_t GetPartitionInfoIndexByName(const std::vector &ptnInfo, const std::string &name); + + StorageType GetDeviceStorageType(); +}; + + +class PackagePtable : public PtableManager { +public: + DISALLOW_COPY_MOVE(PackagePtable); + ~PackagePtable() override {} + static PackagePtable& GetInstance() + { + static PackagePtable instance; + return instance; + } + + void LoadPartitionInfo([[maybe_unused]] hpackage::PkgManager *pkgManager = nullptr) override; + +private: + PackagePtable(); + bool GetPtableBufferFromPkg(hpackage::PkgManager *pkgManager, uint8_t *&imageBuf, uint32_t size); +}; + + +class DevicePtable : public PtableManager { +public: + DISALLOW_COPY_MOVE(DevicePtable); + ~DevicePtable() override {} + static DevicePtable& GetInstance() + { + static DevicePtable instance; + return instance; + } + + void LoadPartitionInfo([[maybe_unused]] hpackage::PkgManager *pkgManager = nullptr) override; + bool ComparePtable(PtableManager &newPtbManager); + bool ComparePartition(PtableManager &newPtbManager, std::string partitionName); +private: + DevicePtable(); +}; +} // namespace updater +#endif // UPDATER_PTABLE_MANAGER_H \ No newline at end of file diff --git a/services/ptable_parse/ufs_ptable.cpp b/services/ptable_parse/ufs_ptable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f73798674c0622b6df8e5cc8bfcc3bf171653087 --- /dev/null +++ b/services/ptable_parse/ufs_ptable.cpp @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2022 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 "ufs_ptable.h" + +#include +#include +#include +#include + +#include "log/log.h" +#include "securec.h" + +namespace updater { +uint32_t UfsPtable::GetDeviceLunNum() +{ + return deviceLunNum_; +} + +uint64_t UfsPtable::GetDeviceLunCapacity(const uint32_t lunIndex) +{ + char lunIndexName = 'a' + lunIndex; + std::string capacityPath = PREFIX_SYS_CLASS_BLOCK + lunIndexName + "/size"; + uint64_t capacity = 0; + GetCapacity(capacityPath, capacity); + return capacity; +} + +void UfsPtable::SetDeviceLunNum() +{ + if (deviceLunNum_ > 0) { + return; + } + uint32_t lunIndex; + for (lunIndex = 0; lunIndex < MAX_LUN_NUMBERS; lunIndex++) { + char lunIndexName = 'a' + lunIndex; + std::string ufsNode = PREFIX_UFS_NODE + lunIndexName; + if (!CheckFileExist(ufsNode)) { + LOG(ERROR) << "file " << ufsNode << " is not exist"; + break; + } + } + deviceLunNum_ = lunIndex; + return; +} + +bool UfsPtable::ParseGptHeaderByUfsLun(const uint8_t *gptImage, const uint32_t len, + const uint32_t lun, const uint32_t blockSize) +{ + GPTHeaderInfo gptHeaderInfo; + (void)memset_s(&gptHeaderInfo, sizeof(GPTHeaderInfo), 0, sizeof(GPTHeaderInfo)); + if (!GetPartitionGptHeaderInfo(gptImage + blockSize, blockSize, gptHeaderInfo)) { + LOG(ERROR) << "GetPartitionGptHeaderInfo fail"; + return false; + } + uint64_t lunDeviceSize = GetDeviceLunCapacity(lun); + uint32_t lunLbaNum = lunDeviceSize / MIN_UFS_WRITE_SIZE; + return PartitionCheckGptHeader(gptImage, len, lunLbaNum, blockSize, gptHeaderInfo); +} + +bool UfsPtable::UfsReadGpt(const uint8_t *gptImage, const uint32_t len, + const uint32_t lun, const uint32_t blockSize) +{ + if (gptImage == nullptr || len < ptableData_.writeDeviceLunSize || lun >= MAX_LUN_NUMBERS || blockSize == 0) { + LOG(ERROR) << "invaild input"; + return false; + } + if (!ParseGptHeaderByUfsLun(gptImage, len, lun, blockSize)) { + LOG(ERROR) << "Primary signature invalid"; + return false; + } + + uint32_t partEntryCnt = blockSize / PARTITION_ENTRY_SIZE; + uint32_t partition0 = GET_LLWORD_FROM_BYTE(gptImage + blockSize + PARTITION_ENTRIES_OFFSET); + + uint32_t count = 0; + const uint8_t *data = nullptr; + for (uint32_t i = 0; i < (MAX_PARTITION_NUM / partEntryCnt) && count < MAX_PARTITION_NUM; i++) { + data = gptImage + (partition0 + i) * blockSize; + for (uint32_t j = 0; j < partEntryCnt; j++) { + uint8_t typeGuid[GPT_PARTITION_TYPE_GUID_LEN] = {0}; + if (memcpy_s(typeGuid, sizeof(typeGuid), &data[(j * PARTITION_ENTRY_SIZE)], sizeof(typeGuid)) != EOK) { + LOG(ERROR) << "memcpy guid fail"; + } + if (typeGuid[0] == 0x00 && typeGuid[1] == 0x00) { // 0x00 means no partition + i = MAX_PARTITION_NUM / partEntryCnt; + break; + } + uint64_t firstLba = GET_LLWORD_FROM_BYTE(&data[(j * PARTITION_ENTRY_SIZE) + FIRST_LBA_OFFSET]); + uint64_t lastLba = GET_LLWORD_FROM_BYTE(&data[(j * PARTITION_ENTRY_SIZE) + LAST_LBA_OFFSET]); + // add a new partition info into partitionInfo_ vector + PtnInfo newPtnInfo; + (void)memset_s(&newPtnInfo, sizeof(newPtnInfo), 0, sizeof(newPtnInfo)); + newPtnInfo.startAddr = firstLba * (uint64_t)MIN_UFS_WRITE_SIZE; + // General algorithm : calculate partition size by lba + newPtnInfo.partitionSize = (lastLba - firstLba + 1) * (uint64_t)MIN_UFS_WRITE_SIZE; + const uint8_t *nameOffset = data + (j * PARTITION_ENTRY_SIZE + GPT_PARTITION_NAME_OFFSET); + // 2 bytes for 1 charactor of partition name + ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, newPtnInfo.dispName, MAX_GPT_NAME_SIZE / 2); + (void)memcpy_s(newPtnInfo.partitionTypeGuid, sizeof(newPtnInfo.partitionTypeGuid), + typeGuid, sizeof(typeGuid)); + newPtnInfo.lun = lun; + partitionInfo_.push_back(newPtnInfo); + count++; + } + } + return true; +} + + +void UfsPtable::UfsPatchGptHeader(UfsPartitionDataInfo &ptnDataInfo, const uint32_t blockSize) +{ + // mbr len + gptHeader len = 2 blockSize + if (blockSize == 0 || ptnDataInfo.writeDataLen < 2 * blockSize || ptnDataInfo.lunSize == 0) { + LOG(ERROR) << "invaild argument"; + return; + } + uint64_t cardSizeSector = ptnDataInfo.lunSize / MIN_UFS_WRITE_SIZE; + if (cardSizeSector == 0) { + cardSizeSector = DEFAULT_SECTOR_NUM; + } + // Patching primary header + uint8_t *primaryGptHeader = ptnDataInfo.data + blockSize; + PUT_LONG_LONG(primaryGptHeader + BACKUP_HEADER_OFFSET, (cardSizeSector - 1)); + PUT_LONG_LONG(primaryGptHeader + LAST_USABLE_LBA_OFFSET, (cardSizeSector - 1)); + // Find last partition + uint32_t totalPart = 0; + while (*(primaryGptHeader + blockSize + totalPart * PARTITION_ENTRY_SIZE) != 0) { + totalPart++; + } + if (totalPart == 0) { + LOG(ERROR) << "no partition exist"; + return; + } + // Patching last partition + uint8_t *lastPartOffset = primaryGptHeader + blockSize + (totalPart - 1) * PARTITION_ENTRY_SIZE; + uint64_t lastLba = GET_LLWORD_FROM_BYTE(lastPartOffset + PARTITION_ENTRY_LAST_LBA); + uint64_t firstLba = GET_LLWORD_FROM_BYTE(lastPartOffset + FIRST_LBA_OFFSET); + // General algorithm : calculate partition size by lba + uint64_t partitionSize = (lastLba - firstLba + 1) * MIN_UFS_WRITE_SIZE; + std::string partitionName; + uint8_t *nameOffset = lastPartOffset + GPT_PARTITION_NAME_OFFSET; + // 2 bytes for 1 charactor of partition name + ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, partitionName, MAX_GPT_NAME_SIZE / 2); + if (partitionName == USERDATA_PARTITION || (totalPart == 1 && partitionSize == 0)) { + // patch userdata or only one partition + PUT_LONG_LONG(lastPartOffset + PARTITION_ENTRY_LAST_LBA, (cardSizeSector - 1)); + LOG(INFO) << "partitionSize=" << partitionSize << ", partition_name:" << partitionName; + } + + // Updating CRC of the Partition entry array in both headers + uint32_t partCount = GET_LWORD_FROM_BYTE(primaryGptHeader + PARTITION_COUNT_OFFSET); + uint32_t entrySize = GET_LWORD_FROM_BYTE(primaryGptHeader + PENTRY_SIZE_OFFSET); + // mbr len + gptHeader len = 2 blockSize + uint32_t crcValue = CalculateCrc32(ptnDataInfo.data + (blockSize * 2), partCount * entrySize); + PUT_LONG(primaryGptHeader + PARTITION_CRC_OFFSET, crcValue); + // Clearing CRC fields to calculate + PUT_LONG(primaryGptHeader + HEADER_CRC_OFFSET, 0); + crcValue = CalculateCrc32(primaryGptHeader, GPT_CRC_LEN); + PUT_LONG(primaryGptHeader + HEADER_CRC_OFFSET, crcValue); + return; +} + +// blocksize is 4096, lbaLen is 512. Because in ptable.img block is 512 while in device block is 4096 +bool UfsPtable::ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize) +{ + if (ptbImgBuffer == nullptr) { + LOG(ERROR) << "input param invalid"; + return false; + } + + uint32_t imgBlockSize = ptableData_.lbaLen; // 512 + uint32_t deviceBlockSize = ptableData_.blockSize; // 4096 + if (imgBufSize < ptableData_.emmcGptDataLen + ptableData_.imgLuSize) { + LOG(ERROR) << "input param invalid imgBufSize"; + return false; + } + + SetDeviceLunNum(); + LOG(INFO) << "lun number of ptable:" << deviceLunNum_; + + for (uint32_t i = 0; i < deviceLunNum_; i++) { + UfsPartitionDataInfo newLunPtnDataInfo; + (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE); + uint8_t *lunStart = GetPtableImageUfsLunPmbrStart(ptbImgBuffer, i); + uint8_t *gptHeaderStart = GetPtableImageUfsLunGptHeaderStart(ptbImgBuffer, i); + // first block is mbr, second block is gptHeader + if (!CheckProtectiveMbr(lunStart, imgBlockSize) || !CheckIfValidGpt(gptHeaderStart, imgBlockSize)) { + newLunPtnDataInfo.isGptVaild = false; + ufsPtnDataInfo_.push_back(newLunPtnDataInfo); + continue; + } + // for hisi: change ptable.img(512 bytes/block) into format of device(4096 bytes/block) + if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, lunStart, imgBlockSize) != EOK) { + LOG(WARNING) << "memcpy_s pmbr fail"; + } + if (memcpy_s(newLunPtnDataInfo.data + deviceBlockSize, TMP_DATA_SIZE - deviceBlockSize, + gptHeaderStart, imgBlockSize) != EOK) { + LOG(WARNING) << "memcpy_s gpt header fail"; + } + // skip 2 lba length to set gpt entry + if (memcpy_s(newLunPtnDataInfo.data + 2 * deviceBlockSize, TMP_DATA_SIZE - 2 * deviceBlockSize, + GetPtableImageUfsLunEntryStart(ptbImgBuffer, i), GPT_ENTRYS_SIZE) != EOK) { + LOG(WARNING) << "memcpy_s gpt data fail"; + } + newLunPtnDataInfo.writeDataLen = ptableData_.writeDeviceLunSize; + newLunPtnDataInfo.lunIndex = i + ptableData_.startLunNumber; + newLunPtnDataInfo.lunSize = GetDeviceLunCapacity(newLunPtnDataInfo.lunIndex); + UfsPatchGptHeader(newLunPtnDataInfo, deviceBlockSize); + newLunPtnDataInfo.isGptVaild = true; + ufsPtnDataInfo_.push_back(newLunPtnDataInfo); + if (!UfsReadGpt(newLunPtnDataInfo.data, newLunPtnDataInfo.writeDataLen, + newLunPtnDataInfo.lunIndex, deviceBlockSize)) { + LOG(ERROR) << "parse ufs gpt fail"; + return false; + } + } + return true; +} + +bool UfsPtable::ReadAndCheckMbr(const uint32_t lunIndex, const uint32_t blockSize) +{ + if (blockSize <= 0 || lunIndex < 0 || lunIndex > deviceLunNum_) { + LOG(ERROR) << "blockSize <= 0"; + return false; + } + + uint8_t *buffer = new(std::nothrow) uint8_t[blockSize](); + if (buffer == nullptr) { + LOG(ERROR) << "new buffer failed!"; + return false; + } + char lunIndexName = 'a' + lunIndex; + std::string ufsNode = PREFIX_UFS_NODE + lunIndexName; + if (!MemReadWithOffset(ufsNode, 0, buffer, blockSize)) { + LOG(ERROR) << "read " << blockSize << " bytes from ufsNode " << ufsNode << " failed!"; + delete [] buffer; + return false; + } + + bool result = CheckProtectiveMbr(buffer, blockSize); + + delete [] buffer; + return result; +} + +int32_t UfsPtable::GetLunNumFromNode(const std::string &ufsNode) +{ + if (PREFIX_UFS_NODE.length() + 1 != ufsNode.length()) { + LOG(ERROR) << "ufsNode length is " << ufsNode.length() << ", \ + not equal to PREFIX_UFS_NODE(" << PREFIX_UFS_NODE.length() << ") + 1"; + return -1; + } + char ufsLunIndex = ufsNode.back(); + // such as : 'a' - 'a' + return (ufsLunIndex - 'a'); +} + +bool UfsPtable::LoadPartitionInfoFromLun(const uint32_t lunIndex, const uint32_t imgLen) +{ + if (imgLen == 0 || lunIndex < 0 || lunIndex > deviceLunNum_) { + LOG(ERROR) << "imgLen or lunIndex is invaild"; + return false; + } + char lunIndexName = 'a' + lunIndex; + std::string ufsNode = PREFIX_UFS_NODE + lunIndexName; + + uint8_t *buffer = new(std::nothrow) uint8_t[imgLen](); + if (buffer == nullptr) { + LOG(ERROR) << "new buffer failed!"; + return false; + } + if (!MemReadWithOffset(ufsNode, 0, buffer, imgLen)) { + LOG(ERROR) << "read " << imgLen << " bytes from ufsNode " << ufsNode << " failed!"; + delete [] buffer; + return false; + } + UfsPartitionDataInfo newLunPtnDataInfo; + newLunPtnDataInfo.isGptVaild = true; + newLunPtnDataInfo.lunIndex = lunIndex; + newLunPtnDataInfo.lunSize = imgLen; + newLunPtnDataInfo.writeDataLen = imgLen; + (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE); + if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, buffer, imgLen) != EOK) { + LOG(WARNING) << "memcpy_s mbr fail"; + } + + ufsPtnDataInfo_.push_back(newLunPtnDataInfo); + int32_t result = UfsReadGpt(buffer, imgLen, lunIndex, MIN_UFS_WRITE_SIZE); + delete [] buffer; + return result; +} + +uint32_t UfsPtable::LoadAllLunPartitions() +{ + uint32_t lunIndex; + for (lunIndex = 0; lunIndex < deviceLunNum_; lunIndex++) { + if (ReadAndCheckMbr(lunIndex, MIN_UFS_WRITE_SIZE)) { + LoadPartitionInfoFromLun(lunIndex, ptableData_.writeDeviceLunSize); + } + } + return lunIndex; +} + +bool UfsPtable::LoadPtableFromDevice() +{ + if (!partitionInfo_.empty()) { + LOG(INFO) << "ptable is already loaded to ram"; + return true; + } + SetDeviceLunNum(); + if (LoadAllLunPartitions() == 0) { + LOG(ERROR) << "init ptable to ram fail"; + return false; + } + LOG(INFO) << "init ptable to ram ok"; + return true; +} + +bool UfsPtable::WritePartitionTable() +{ + if (ufsPtnDataInfo_.empty()) { + LOG(ERROR) << "ufsPtnDataInfo_ is empty, write failed!"; + return false; + } + for (uint32_t i = 0; i < ufsPtnDataInfo_.size(); i++) { + uint64_t writeDataLen = ufsPtnDataInfo_[i].writeDataLen; + char lunIndexName = 'a' + ufsPtnDataInfo_[i].lunIndex; + std::string ufsNode = PREFIX_UFS_NODE + lunIndexName; + LOG(INFO) << "ufs node name:" << ufsNode << ", writeDataLen = " << writeDataLen; + + if (!ufsPtnDataInfo_[i].isGptVaild) { + LOG(WARNING) << "invaild ptable, no need to update"; + continue; + } + if (!WriteBufferToPath(ufsNode, 0, ufsPtnDataInfo_[i].data, writeDataLen)) { + LOG(ERROR) << "write first gpt fail"; + return false; + } + } + return true; +} + +uint8_t *UfsPtable::GetPtableImageUfsLunPmbrStart(uint8_t *imageBuf, const uint32_t lunIndex) +{ + uint32_t pmbrStart = ptableData_.emmcGptDataLen + lunIndex * ptableData_.imgLuSize; + LOG(INFO) << "GetPtableImageUfsLunPmbrStart : " << std::hex << pmbrStart << std::dec; + return imageBuf + pmbrStart; +} + +uint8_t *UfsPtable::GetPtableImageUfsLunGptHeaderStart(uint8_t *imageBuf, const uint32_t lunIndex) +{ + uint32_t gptHeaderStart = ptableData_.emmcGptDataLen + lunIndex * ptableData_.imgLuSize + ptableData_.lbaLen; + LOG(INFO) << "GetPtableImageUfsLunGptHeaderStart : " << std::hex << gptHeaderStart << std::dec; + return imageBuf + gptHeaderStart; +} + +uint8_t *UfsPtable::GetPtableImageUfsLunEntryStart(uint8_t *imageBuf, const uint32_t lunIndex) +{ + uint32_t entryStart = ptableData_.emmcGptDataLen + lunIndex * ptableData_.imgLuSize + + ptableData_.lbaLen + ptableData_.gptHeaderLen; + LOG(INFO) << "GetPtableImageUfsLunEntryStart : " << std::hex << entryStart << std::dec; + return imageBuf + entryStart; +} +} // namespace updater diff --git a/services/ptable_parse/ufs_ptable.h b/services/ptable_parse/ufs_ptable.h new file mode 100644 index 0000000000000000000000000000000000000000..f36f4ab79b32b8a5eef53f6aaae237b9af8e5120 --- /dev/null +++ b/services/ptable_parse/ufs_ptable.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef UPDATER_UFS_PTABLE_H +#define UPDATER_UFS_PTABLE_H + +namespace updater { +class UfsPtable : public Ptable { +public: + UfsPtable() = default; + DISALLOW_COPY_MOVE(UfsPtable); + ~UfsPtable() override {} + + uint32_t GetDeviceLunNum(); + bool ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize) override; + bool LoadPtableFromDevice() override; + bool WritePartitionTable() override; + +private: + static constexpr uint32_t TMP_DATA_SIZE = 32 * 1024; + static constexpr uint32_t MAX_LUN_NUMBERS = 26; + static constexpr uint32_t MIN_UFS_WRITE_SIZE = 4096; + + struct UfsPartitionDataInfo { + bool isGptVaild; + uint32_t lunIndex; + uint64_t lunSize; // lun device density + uint32_t writeDataLen; // data len written to UFS + uint8_t data[TMP_DATA_SIZE]; // ptable image data + }; + + uint32_t deviceLunNum_ { 0 }; + std::vector ufsPtnDataInfo_; + + uint64_t GetDeviceLunCapacity(const uint32_t lunIndex); + bool UfsReadGpt(const uint8_t *gptImage, const uint32_t len, const uint32_t lun, const uint32_t blockSize); + bool ParseGptHeaderByUfsLun(const uint8_t *gptImage, const uint32_t len, const uint32_t lun, + const uint32_t blockSize); + void UfsPatchGptHeader(UfsPartitionDataInfo &ptnDataInfo, const uint32_t blockSize); + uint32_t LoadAllLunPartitions(); + bool ReadAndCheckMbr(const uint32_t lunIndex, const uint32_t blockSize); + bool LoadPartitionInfoFromLun(const uint32_t lunIndex, const uint32_t imgLen); + int32_t GetLunNumFromNode(const std::string &ufsNode); + void SetDeviceLunNum(); + uint8_t *GetPtableImageUfsLunPmbrStart(uint8_t *imageBuf, const uint32_t lunIndex); + uint8_t *GetPtableImageUfsLunGptHeaderStart(uint8_t *imageBuf, const uint32_t lunIndex); + uint8_t *GetPtableImageUfsLunEntryStart(uint8_t *imageBuf, const uint32_t lunIndex); +}; +} // namespace updater +#endif // UPDATER_UFS_PTABLE_H \ No newline at end of file diff --git a/services/script/script_instruction/script_instructionhelper.cpp b/services/script/script_instruction/script_instructionhelper.cpp index dbb2e2618c52f8b146e66905c384c64ea5432458..fd388d0dc99705fe8ed976bfb6c9b4ea702a47e2 100644 --- a/services/script/script_instruction/script_instructionhelper.cpp +++ b/services/script/script_instruction/script_instructionhelper.cpp @@ -52,7 +52,7 @@ void ScriptInstructionHelper::ReleaseBasicInstructionHelper() g_instructionHelper = nullptr; } -ScriptInstructionHelper::~ScriptInstructionHelper() +ScriptInstructionHelper::~ScriptInstructionHelper() { if (instrLib_ != nullptr) { dlclose(instrLib_); diff --git a/services/script/script_interpreter/script_context.h b/services/script/script_interpreter/script_context.h index 78718f828a1448e83c109d6e0629ad6054a6b839..ce681b7d99cc37f9327c561540648ad2050b6e8b 100644 --- a/services/script/script_interpreter/script_context.h +++ b/services/script/script_interpreter/script_context.h @@ -61,6 +61,7 @@ public: static std::string ScriptToString(UScriptValuePtr value); static UScriptValuePtr GetRightCompluteValue(UScriptValuePtr rightValue); + private: UScriptValueType type_; }; @@ -131,6 +132,7 @@ public: UScriptValuePtr ComputerReturn(int32_t action, UScriptValuePtr rightValue, UScriptValuePtr defReturn) const; std::string ToString() override; + private: int32_t ComputerLogic(UScriptValuePtr rightValue) const; std::string value_; @@ -200,14 +202,14 @@ public: virtual ~UScriptInstructionContext() {} - virtual int32_t PushParam(int32_t value) override; - virtual int32_t PushParam(float value) override; - virtual int32_t PushParam(const std::string &value) override; - virtual int32_t GetParamCount() override; - virtual ParamType GetParamType(int32_t index) override; - virtual int32_t GetParam(int32_t index, int32_t &value) override; - virtual int32_t GetParam(int32_t index, float &value) override; - virtual int32_t GetParam(int32_t index, std::string &value) override; + int32_t PushParam(int32_t value) override; + int32_t PushParam(float value) override; + int32_t PushParam(const std::string &value) override; + int32_t GetParamCount() override; + ParamType GetParamType(int32_t index) override; + int32_t GetParam(int32_t index, int32_t &value) override; + int32_t GetParam(int32_t index, float &value) override; + int32_t GetParam(int32_t index, std::string &value) override; int32_t AddInputParam(UScriptValuePtr value); diff --git a/services/script/script_interpreter/script_expression.cpp b/services/script/script_interpreter/script_expression.cpp index 048d1b38644e12913d2b3a509827327b422ef3eb..c113900cfd8867513ceae6547bf2c46d89a96b4c 100644 --- a/services/script/script_interpreter/script_expression.cpp +++ b/services/script/script_interpreter/script_expression.cpp @@ -43,7 +43,7 @@ UScriptExpression* AssignExpression::AddIdentifier(UScriptExpression *expression // binary operator UScriptExpression* BinaryExpression::CreateExpression(ExpressionAction action, - UScriptExpression *left, + UScriptExpression *left, UScriptExpression *right) { return new BinaryExpression(action, left, right); @@ -128,7 +128,7 @@ UScriptValuePtr BinaryExpression::Execute(ScriptInterpreter &inter, UScriptConte left = left_->Execute(inter, local); } - if (action_ == OR_OPERATOR && left_ != nullptr && left->IsTrue()) { + if (action_ == OR_OPERATOR && left != nullptr && left->IsTrue()) { INTERPRETER_LOGE(inter, local, "BinaryExpression::Execute left:%s %s", UScriptValue::ScriptToString(left).c_str(), opStr[action_].c_str()); return std::make_shared(1); diff --git a/services/script/script_interpreter/script_interpreter.cpp b/services/script/script_interpreter/script_interpreter.cpp index 0531a914aa55d4d4b57904a2f8de52e8f3b6e255..0597ff514949f2ebeaae91a6999ceb3a75b276d2 100644 --- a/services/script/script_interpreter/script_interpreter.cpp +++ b/services/script/script_interpreter/script_interpreter.cpp @@ -36,6 +36,7 @@ int32_t ScriptInterpreter::ExecuteScript(ScriptManagerImpl *manager, hpackage::P USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Fail to loadScript script %s", pkgStream->GetFileName().c_str()); ret = inter->Execute(); delete inter; + inter = nullptr; USCRIPT_LOGI("ExecuteScript finish ret: %d script: %s ", ret, pkgStream->GetFileName().c_str()); return ret; @@ -59,20 +60,12 @@ ScriptInterpreter::~ScriptInterpreter() } functions_.clear(); contextStack_.clear(); - delete scanner_; - delete parser_; } int32_t ScriptInterpreter::LoadScript(hpackage::PkgManager::StreamPtr pkgStream) { - scanner_ = new Scanner(this); - parser_ = new Parser(scanner_, this); - if (scanner_ == nullptr || parser_ == nullptr) { - USCRIPT_LOGE("Fail to open fstream %s", pkgStream->GetFileName().c_str()); - delete parser_; - delete scanner_; - return USCRIPT_ERROR_CREATE_OBJ; - } + scanner_ = std::make_unique(this); + parser_ = std::make_unique(scanner_.get(), this); scanner_->set_debug(0); scanner_->SetPkgStream(pkgStream); int32_t ret = parser_->parse(); diff --git a/services/script/script_interpreter/script_interpreter.h b/services/script/script_interpreter/script_interpreter.h index adced81b722bfad2a376c37dc0297a20a54f6a5c..e946005c5ae3758811183e9f99b5d42687029753 100644 --- a/services/script/script_interpreter/script_interpreter.h +++ b/services/script/script_interpreter/script_interpreter.h @@ -80,8 +80,8 @@ private: std::map functions_; std::vector contextStack_; ScriptManagerImpl* scriptManager_ = nullptr; - Parser* parser_ = nullptr; - Scanner* scanner_ = nullptr; + std::unique_ptr parser_; + std::unique_ptr scanner_; int32_t instanceId_ = 0; }; } // namespace uscript diff --git a/services/script/script_interpreter/script_param.cpp b/services/script/script_interpreter/script_param.cpp index a5e98acb50de62733c3a7f0bbf074e5556b00934..83343e33449fd838497ff21a5b36430a66437f88 100644 --- a/services/script/script_interpreter/script_param.cpp +++ b/services/script/script_interpreter/script_param.cpp @@ -30,7 +30,8 @@ ScriptParams::~ScriptParams() ScriptParams* ScriptParams::CreateParams(UScriptExpression *expression) { - auto params = new ScriptParams(); + auto params = new(std::nothrow) ScriptParams(); + USCRIPT_CHECK(params != nullptr, return nullptr, "Create params failed"); params->AddParams(expression); return params; } @@ -38,7 +39,8 @@ ScriptParams* ScriptParams::CreateParams(UScriptExpression *expression) ScriptParams* ScriptParams::AddParams(ScriptParams *params, UScriptExpression *expression) { if (params == nullptr) { - params = new ScriptParams(); + params = new(std::nothrow) ScriptParams(); + USCRIPT_CHECK(params != nullptr, return nullptr, "Create params failed"); } params->AddParams(expression); return params; diff --git a/services/script/script_interpreter/script_statement.cpp b/services/script/script_interpreter/script_statement.cpp index 135d3235cd59cea8a813c1a53dea2ce5d1892fad..e30ecb4ed94cf070c86035ce7d61f76d238c9afb 100644 --- a/services/script/script_interpreter/script_statement.cpp +++ b/services/script/script_interpreter/script_statement.cpp @@ -87,7 +87,7 @@ UScriptStatement* UScriptStatement::CreateIfStatement(UScriptExpression *conditi UScriptStatementList *list2, UScriptStatement *nextIfState) { - auto ifStatement = new UScriptIfStatement(condition, list1); + auto ifStatement = new(std::nothrow) UScriptIfStatement(condition, list1); USCRIPT_CHECK(ifStatement != nullptr, return nullptr, "Create if statement failed "); ifStatement->AddFalseStatementList(list2); ifStatement->AddNextStatement(reinterpret_cast(nextIfState)); @@ -111,7 +111,7 @@ UScriptStatement* UScriptStatement::CreateWhileStatement(UScriptExpression *cond UScriptStatementList* UScriptStatementList::CreateInstance(UScriptStatement *statement) { - auto list = new UScriptStatementList(); + auto list = new(std::nothrow) UScriptStatementList(); USCRIPT_CHECK(list != nullptr, return nullptr, "Failed to create statement list "); list->AddScriptStatement(statement); return list; @@ -319,7 +319,8 @@ UScriptReturnStatement::~UScriptReturnStatement() UScriptReturnStatement* UScriptReturnStatement::CreateStatement(ScriptParams *params) { - auto statement = new UScriptReturnStatement(); + auto statement = new(std::nothrow) UScriptReturnStatement(); + USCRIPT_CHECK(statement != nullptr, return nullptr, "Create statement failed"); if (params != nullptr) { statement->AddParams(params); } diff --git a/services/script/script_manager/script_managerImpl.cpp b/services/script/script_manager/script_managerImpl.cpp index e0889b3fe88162061ff648a99b5466b79b129cdb..d284b5d7193bc15d8cc0585ac48924fd33ce5804 100644 --- a/services/script/script_manager/script_managerImpl.cpp +++ b/services/script/script_manager/script_managerImpl.cpp @@ -33,7 +33,8 @@ ScriptManager* ScriptManager::GetScriptManager(UScriptEnv *env) USCRIPT_CHECK(env != nullptr, return nullptr, "Env null"); if (g_scriptManager == nullptr) { - g_scriptManager = new ScriptManagerImpl(env); + g_scriptManager = new(std::nothrow) ScriptManagerImpl(env); + USCRIPT_CHECK(g_scriptManager != nullptr, return nullptr, "Create g_scriptManager failed"); (void)g_scriptManager->Init(); } return g_scriptManager; @@ -84,14 +85,16 @@ int32_t ScriptManagerImpl::Init() PkgManager::PkgManagerPtr manager = scriptEnv_->GetPkgManager(); USCRIPT_CHECK(manager != nullptr, return USCRIPT_INVALID_PARAM, "Failed to get pkg manager"); - // Register other instructions from scripts + // Register other instructions from scripts int32_t ret = USCRIPT_SUCCESS; const FileInfo *info = manager->GetFileInfo(REGISTER_CMD_SCRIPT_NAME); if (info != nullptr) { ret = ExtractAndExecuteScript(manager, REGISTER_CMD_SCRIPT_NAME); } + USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to extract and execute script "); + // Collect scripts - ret |= ExtractAndExecuteScript(manager, LOAD_SCRIPT_NAME); + ret = ExtractAndExecuteScript(manager, LOAD_SCRIPT_NAME); USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to extract and execute script "); return USCRIPT_SUCCESS; } @@ -144,7 +147,7 @@ int32_t ScriptManagerImpl::ExecuteScript(int32_t priority) int32_t retCode = USCRIPT_SUCCESS; task.workSize = threadNumber; task.processor = [&](int iter) { - for (size_t i = iter; i < scriptFiles_[priority].size(); i += threadNumber) { + for (size_t i = iter; i < scriptFiles_[priority].size(); i += static_cast(threadNumber)) { ret = ExtractAndExecuteScript(manager, scriptFiles_[priority][i]); if (ret != USCRIPT_SUCCESS) { USCRIPT_LOGE("Failed to execute script %s", scriptFiles_[priority][i].c_str()); diff --git a/services/script/script_manager/script_manager_impl.h b/services/script/script_manager/script_manager_impl.h index 7a39a231edb4706e94031bd9369c31313df4ff76..b7741a47522d7b974991fa51aea9740adbbc0f69 100644 --- a/services/script/script_manager/script_manager_impl.h +++ b/services/script/script_manager/script_manager_impl.h @@ -33,7 +33,7 @@ public: explicit ScriptManagerImpl(UScriptEnv *env) : scriptEnv_(env) {} virtual ~ScriptManagerImpl(); int32_t Init(); - virtual int32_t ExecuteScript(int32_t priority) override; + int32_t ExecuteScript(int32_t priority) override; private: int32_t ExtractAndExecuteScript(hpackage::PkgManager::PkgManagerPtr manager, diff --git a/services/script/threadpool/thread_pool.h b/services/script/threadpool/thread_pool.h index 1de1d89e18f6cf9e53992262dfdcfaa0753a1778..38e4780d6ac9fe0c1e5a578b56cdd4683394d503 100644 --- a/services/script/threadpool/thread_pool.h +++ b/services/script/threadpool/thread_pool.h @@ -46,6 +46,7 @@ public: { return threadNumber_; } + private: void ThreadRun(int32_t threadIndex); void RunTask(Task &&task, int32_t index); diff --git a/services/script/threadpool/threadpool.cpp b/services/script/threadpool/threadpool.cpp index 686cd29c06365732afe3ff38ea166aea1da841ca..09be46b8c3b2e5b0d600ed56dd957857903d839e 100644 --- a/services/script/threadpool/threadpool.cpp +++ b/services/script/threadpool/threadpool.cpp @@ -152,7 +152,7 @@ void ThreadPool::RunTask(Task &&task, int32_t index) *taskQueue_[index].subTaskFlag[i] = true; } - // Execute first task + // Execute first task taskQueue_[index].task.processor(0); bool complete = true; do { diff --git a/services/script/yacc/lexer.cpp b/services/script/yacc/lexer.cpp index efe26b4c1c0485bb9614a5730ba25a9f424953ca..cbe0c5c42ad202c81676e03da82cc92d77dab872 100755 --- a/services/script/yacc/lexer.cpp +++ b/services/script/yacc/lexer.cpp @@ -489,8 +489,6 @@ static const flex_int16_t yy_chk[168] = { #include #include -#include -#include #include #include "parser.hpp" // 包含由parser.y生成的头文件 #include "scanner.h" // 包含yyFlexLexer子类的头文件 @@ -549,7 +547,7 @@ static int yy_flex_strlen(const char *); * is returned in "result". */ #ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ +#define YY_INPUT(buf, result, max_size) \ if ((int)(result = LexerInput((char *)buf, max_size)) < 0)\ YY_FATAL_ERROR("input in flex scanner failed"); #endif @@ -839,7 +837,8 @@ do_action: /* This label is used only to access EOF actions. */ YY_BREAK case 34: YY_RULE_SETUP { - return Parser::make_NUMBER(std::strtol(yytext,(&yytext+yyleng), 10),loc); + const int decimal = 10; + return Parser::make_NUMBER(std::strtol(yytext, (&yytext + yyleng), decimal), loc); } YY_BREAK case 35: @@ -1337,14 +1336,13 @@ int yyFlexLexer::yyinput() /** Immediately switch to a different input stream. * @param input_file A readable stream. - * + * * @note This function does not reset the start condition to @c INITIAL . */ void yyFlexLexer::yyrestart(std::istream& input_file) { - if (!YY_CURRENT_BUFFER) { - yyensure_buffer_stack (); + yyensure_buffer_stack(); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); } diff --git a/services/script/yacc/location.hh b/services/script/yacc/location.hh index a70f5c733215108e8f456c3692abb13ffb12103c..7da7259db4ce4df1c3ba4393428dee396d78ea78 100755 --- a/services/script/yacc/location.hh +++ b/services/script/yacc/location.hh @@ -73,6 +73,7 @@ namespace uscript { counter_type line; /// Current column number. counter_type column; + private: /// Compute max (min, lhs+rhs). static counter_type add_ (counter_type lhs, counter_type rhs, counter_type min) diff --git a/services/script/yacc/parser.cpp b/services/script/yacc/parser.cpp index 04e8b2515549ac97d291b6a5c8734eb4407d0402..e5451344a863fdedfd4ecf14af7c2f0ca39bc502 100755 --- a/services/script/yacc/parser.cpp +++ b/services/script/yacc/parser.cpp @@ -36,8 +36,6 @@ void Parser::error(const location_type& loc, const std::string& msg) LOG(updater::ERROR) << "error " << msg << " loc " << loc << std::endl; } -#include "parser.hpp" - #ifndef YY_ #if defined YYENABLE_NLS && YYENABLE_NLS #if ENABLE_NLS @@ -414,7 +412,7 @@ Parser::Parser(uscript::Scanner* scanner_yyarg, uscript::ScriptInterpreter* inte case symbol_kind::S_LT: // LT /* fallthrough */ case symbol_kind::S_LE: // LE - /* fallthrough */ + /* fallthrough */ case symbol_kind::S_LP: // LP /* fallthrough */ case symbol_kind::S_RP: // RP @@ -1286,11 +1284,11 @@ yyreduce: break; } case 37: { // primary_expression: SUB primary_expression - yylhs.value.as() =yystack_[0].value.as(); + yylhs.value.as() = yystack_[0].value.as(); break; } case 38: { // primary_expression: LP expression RP - yylhs.value.as() =yystack_[1].value.as(); + yylhs.value.as() = yystack_[1].value.as(); break; } case 39: { // primary_expression: IDENTIFIER diff --git a/services/script/yacc/parser.hpp b/services/script/yacc/parser.hpp index fb1716ed4a3b2cb42981b0b1a00f5eab69f9a482..92cb07ab5c04f18d389f7754e9a88648a3dc6583 100755 --- a/services/script/yacc/parser.hpp +++ b/services/script/yacc/parser.hpp @@ -803,6 +803,7 @@ private: semantic_type value; /// The location. location_type location; + private: #if YY_CPLUSPLUS < 201103L /// Assignment operator. @@ -1383,6 +1384,7 @@ private: const Parser &yyparser_; const symbol_type &yyla_; }; + private: #if YY_CPLUSPLUS < 201103L /// Non copyable. @@ -1592,10 +1594,12 @@ private: { return stack_[range_ - i]; } + private: const stack& stack_; index_type range_; }; + private: #if YY_CPLUSPLUS < 201103L /// Non copyable. diff --git a/services/ui/input_event.cpp b/services/ui/input_event.cpp index 5867bb6eb06252d5998a7361df04b42021ded55a..2c97f10668783805ae48039b37f6eefd275c22ee 100644 --- a/services/ui/input_event.cpp +++ b/services/ui/input_event.cpp @@ -22,7 +22,7 @@ namespace updater { constexpr int TOUCH_LOW_TH = 50; constexpr int TOUCH_HIGH_TH = 90; constexpr int INIT_DEFAULT_VALUE = 255; -constexpr int LABEL_HEIGHT = 64; +constexpr int LABEL_HEIGHT = 80; constexpr int LABEL_OFFSET_2 = 2; constexpr int LABEL_OFFSET_3 = 3; constexpr int DIALOG_START_Y = 550; diff --git a/services/ui/updater_ui_const.h b/services/ui/updater_ui_const.h index 99381a701fa5358c3648bc06b065a40f42d008ad..5dd2d03b0b1752862df7741cdcf856a02cf141fc 100644 --- a/services/ui/updater_ui_const.h +++ b/services/ui/updater_ui_const.h @@ -53,8 +53,8 @@ constexpr int DIALOG_OK_ID = 200; constexpr int DIALOG_CANCEL_ID = 201; constexpr int DIALOG_CANCEL_X = 340; constexpr int DIALOG_OK_WIDTH = 150; -constexpr int SCREEN_WIDTH = 480; -constexpr int SCREEN_HEIGHT = 960; +constexpr int SCREEN_WIDTH = 720; +constexpr int SCREEN_HEIGHT = 1280; constexpr int MEDIAN_NUMBER = 2; } // namespace updater #endif /* UPDATE_UI_HOS_UPDATER_H */ \ No newline at end of file diff --git a/services/updater.cpp b/services/updater.cpp index 3aa34d7466ef35e69d5b6d67960fefc21e64c5fe..3906813da3e59a23e5b83d9268718522795f4305 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -71,6 +71,30 @@ int GetUpdatePackageInfo(PkgManager::PkgManagerPtr pkgManager, const std::string return PKG_SUCCESS; } +static int OtaUpdatePreCheck(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath) +{ + if (pkgManager == nullptr) { + LOG(ERROR) << "Fail to GetPackageInstance"; + return UPDATE_CORRUPT; + } + char realPath[PATH_MAX + 1] = {0}; + if (realpath(packagePath.c_str(), realPath) == nullptr) { + return PKG_INVALID_FILE; + } + if (access(realPath, F_OK) != 0) { + LOG(ERROR) << "package does not exist!"; + return PKG_INVALID_FILE; + } + + int32_t ret = pkgManager->VerifyOtaPackage(packagePath, utils::GetCertName()); + if (ret != PKG_SUCCESS) { + LOG(INFO) << "VerifyOtaPackage fail ret :"<< ret; + return ret; + } + + return PKG_SUCCESS; +} + int UpdatePreProcess(PkgManager::PkgManagerPtr pkgManager, const std::string &path) { int ret = -1; @@ -113,25 +137,80 @@ int UpdatePreProcess(PkgManager::PkgManagerPtr pkgManager, const std::string &pa return ret; } -static void ProgressSmoothHandler() +UpdaterStatus IsSpaceCapacitySufficient(const std::string &packagePath) +{ + PkgManager::PkgManagerPtr pkgManager = hpackage::PkgManager::CreatePackageInstance(); + UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return UPDATE_CORRUPT); + std::vector fileIds; + int ret = pkgManager->LoadPackageWithoutUnPack(packagePath, fileIds); + UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "LoadPackageWithoutUnPack failed", + PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT); + + const FileInfo *info = pkgManager->GetFileInfo("update.bin"); + UPDATER_ERROR_CHECK(info != nullptr, "update.bin is not exist", + PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT); + PkgManager::ReleasePackageInstance(pkgManager); + + struct statvfs64 updaterVfs; + if (access("/sdcard/updater", 0) == 0) { + UPDATER_ERROR_CHECK(statvfs64("/sdcard", &updaterVfs) >= 0, "Statvfs read /sdcard error!", return UPDATE_ERROR); + } else { + UPDATER_ERROR_CHECK(statvfs64("/data", &updaterVfs) >= 0, "Statvfs read /data error!", return UPDATE_ERROR); + } + + auto freeSpaceSize = static_cast(updaterVfs.f_bfree); + auto blockSize = static_cast(updaterVfs.f_bsize); + uint64_t totalFreeSize = freeSpaceSize * blockSize; + if (totalFreeSize <= static_cast(info->unpackedSize + MAX_LOG_SPACE)) { + LOG(ERROR) << "Can not update, free space is not enough"; + ShowText(GetUpdateInfoLabel(), "free space is not enough..."); + return UPDATE_ERROR; + } + return UPDATE_SUCCESS; +} + +static inline void ProgressSmoothHandler() { while (g_tmpProgressValue < FULL_PERCENT_PROGRESS) { - int gap = FULL_PERCENT_PROGRESS - g_tmpProgressValue; - int increase = gap / PROGRESS_VALUE_CONST; + int increase = (FULL_PERCENT_PROGRESS - g_tmpProgressValue) / PROGRESS_VALUE_CONST; g_tmpProgressValue += increase; if (g_tmpProgressValue >= FULL_PERCENT_PROGRESS || increase == 0) { break; - } else { - if (GetProgressBar() != nullptr) { - GetProgressBar()->SetProgressValue(g_tmpProgressValue); - } - std::this_thread::sleep_for(std::chrono::milliseconds(SHOW_FULL_PROGRESS_TIME)); + } + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(g_tmpProgressValue); + } + std::this_thread::sleep_for(std::chrono::milliseconds(SHOW_FULL_PROGRESS_TIME)); + } +} + +#ifdef UPDATER_USE_PTABLE +bool PtableProcess(PkgManager::PkgManagerPtr pkgManager, PackageUpdateMode updateMode) +{ + DevicePtable& devicePtb = DevicePtable::GetInstance(); + devicePtb.LoadPartitionInfo(); + PackagePtable& packagePtb = PackagePtable::GetInstance(); + packagePtb.LoadPartitionInfo(pkgManager); + if (!devicePtb.ComparePtable(packagePtb)) { + LOG(INFO) << "Ptable NOT changed, no need to process!"; + return true; + } + if (updateMode == HOTA_UPDATE) { + if (devicePtb.ComparePartition(packagePtb, "USERDATA")) { + LOG(ERROR) << "Hota update not allow userdata partition change!"; + return false; } } + if (!packagePtb.WritePtableToDevice()) { + LOG(ERROR) << "Ptable changed, write new ptable failed!"; + return false; + } + return true; } +#endif UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath, - int retryCount) + int retryCount, PackageUpdateMode updateMode) { if (GetProgressBar() != nullptr) { GetProgressBar()->Hide(); @@ -140,12 +219,21 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons UPDATER_ERROR_CHECK(pkgManager != nullptr, "Fail to GetPackageInstance", return UPDATE_CORRUPT); TextLabel *updateInfoLabel = GetUpdateInfoLabel(); UPDATER_ERROR_CHECK(updateInfoLabel != nullptr, "Fail to updateInfoLabel", return UPDATE_CORRUPT); + UPDATER_CHECK_ONLY_RETURN(SetupPartitions(updateMode) == 0, + ShowText(GetUpdateInfoLabel(), "Install failed..."); + return UPDATE_ERROR); LOG(INFO) << "Verify package..."; updateInfoLabel->SetText("Verify package..."); UPDATER_ERROR_CHECK(access(packagePath.c_str(), 0) == 0, "package is not exist", ShowText(GetUpdateInfoLabel(), "package is not exist"); return UPDATE_CORRUPT); + + int32_t verifyret = OtaUpdatePreCheck(pkgManager, packagePath); + UPDATER_ERROR_CHECK(verifyret == PKG_SUCCESS, "Verify ota package Fail...", + ShowText(GetUpdateInfoLabel(), "Verify ota package Fail..."); + return UPDATE_CORRUPT); + if (retryCount > 0) { LOG(INFO) << "Retry for " << retryCount << " time(s)"; } else { @@ -160,13 +248,20 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons } } - int32_t verifyret = GetUpdatePackageInfo(pkgManager, packagePath); + verifyret = GetUpdatePackageInfo(pkgManager, packagePath); UPDATER_ERROR_CHECK(verifyret == PKG_SUCCESS, "Verify package Fail...", ShowText(GetUpdateInfoLabel(), "Verify package Fail..."); return UPDATE_CORRUPT); LOG(INFO) << "Package verified. start to install package..."; int32_t versionRet = UpdatePreProcess(pkgManager, packagePath); UPDATER_ERROR_CHECK(versionRet == PKG_SUCCESS, "Version Check Fail...", return UPDATE_CORRUPT); +#ifdef UPDATER_USE_PTABLE + if (!PtableProcess(pkgManager, updateMode)) { + LOG(ERROR) << "Ptable process failed!"; + return UPDATE_CORRUPT; + } +#endif + int maxTemperature; UpdaterStatus updateRet = StartUpdaterProc(pkgManager, packagePath, retryCount, maxTemperature); if (updateRet == UPDATE_SUCCESS) { @@ -245,7 +340,7 @@ static void HandleChildOutput(const std::string &buffer, int32_t bufferLen, } else if (outputHeader == "set_progress") { HandleProgressSet(output); } else { - LOG(DEBUG) << "Child process returns unexpected message: " << outputHeader; + LOG(DEBUG) << "Child process returns unexpected message."; } } diff --git a/services/updater_binary/BUILD.gn b/services/updater_binary/BUILD.gn index a6acef5840a2eb7c4654b3b7db47fa19c229bcb2..700f582fc91937dcb6ffb34895da97561e21f56c 100644 --- a/services/updater_binary/BUILD.gn +++ b/services/updater_binary/BUILD.gn @@ -22,6 +22,7 @@ config("updater_config") { "//base/update/updater/services/include/log", "//base/update/updater/services/include", "//base/update/updater/utils/include", + "//base/update/updater/utils/json", "//base/update/updater/services/include/applypatch", "//third_party/cJSON", "//third_party/openssl/include", @@ -58,8 +59,22 @@ ohos_executable("updater_binary") { "//third_party/zlib:libz", ] + if (defined(binary_custom_lib)) { + deps += binary_custom_lib + } + + if (defined(use_ptable)) { + include_dirs = [ "//base/update/updater/services/ptable_parse" ] + deps += [ "//base/update/updater/services/ptable_parse:libptableparse" ] + defines = [ "UPDATER_USE_PTABLE" ] + } + external_deps = [ "init:libbegetutil" ] install_enable = true + install_images = [ + "system", + "updater", + ] part_name = "updater" } diff --git a/services/updater_binary/update_image_block.cpp b/services/updater_binary/update_image_block.cpp index 32ff33b9fb8f82320fe0b823c565677d1ba8bbfd..aec85b3220571d5affcce5a056e7c4181e777f6e 100644 --- a/services/updater_binary/update_image_block.cpp +++ b/services/updater_binary/update_image_block.cpp @@ -54,7 +54,7 @@ static int ExtractNewData(const PkgBuffer &buffer, size_t size, size_t start, bo size_t toWrite = std::min(size, info->writer->GetBlocksSize() - info->writer->GetTotalWritten()); // No more data to write. UPDATER_CHECK_ONLY_RETURN(toWrite != 0, break); - bool ret = info->writer->Write(const_cast(addr), toWrite, WRITE_BLOCK, ""); + bool ret = info->writer->Write(const_cast(addr), toWrite); std::ostringstream logMessage; logMessage << "Write " << toWrite << " byte(s) failed"; UPDATER_ERROR_CHECK(ret == true, logMessage.str(), return hpackage::PKG_INVALID_STREAM); @@ -192,7 +192,7 @@ static int32_t ExecuteTransferCommand(int fd, const std::vector &li pthread_mutex_unlock(&writerThreadInfo->mutex); ret = pthread_join(globalParams->thread, nullptr); std::ostringstream logMessage; - logMessage << "pthread join returned with " << strerror(ret); + logMessage << "pthread join returned with " << ret; UPDATER_WARNING_CHECK_NOT_RETURN(ret == 0, logMessage.str()); if (globalParams->storeCreated != -1) { Store::DoFreeSpace(globalParams->storeBase); diff --git a/services/updater_binary/update_partitions.cpp b/services/updater_binary/update_partitions.cpp index 89c13a3165560a7d10ee657bb8d88c5b8f3a3e4b..415eadbff5f029bbb0d06c9d9d22903d12a227fc 100644 --- a/services/updater_binary/update_partitions.cpp +++ b/services/updater_binary/update_partitions.cpp @@ -53,11 +53,11 @@ int UpdatePartitions::ParsePartitionInfo(const std::string &partitionInfo, Parti cJSON* item = cJSON_GetObjectItem(thisPartition, "start"); UPDATER_ERROR_CHECK(item != nullptr, "Error get start", free(myPartition); myPartition = nullptr; break); - myPartition->start = item->valueint; + myPartition->start = static_cast(item->valueint); item = cJSON_GetObjectItem(thisPartition, "length"); UPDATER_ERROR_CHECK(item != nullptr, "Error get length", free(myPartition); myPartition = nullptr; break); - myPartition->length = item->valueint; + myPartition->length = static_cast(item->valueint); myPartition->partNum = 0; myPartition->devName = "mmcblk0px"; @@ -85,7 +85,7 @@ int UpdatePartitions::DoNewPartitions(PartitonList &newPartList) if (ret <= 0) { LOG(INFO) << "do_partitions FAIL "; } else if (ret == 1) { - LOG(INFO) << "partitions not changed, Skip"; + LOG(INFO) << "partitions not changed,Skip."; } else if (ret > 1) { LOG(INFO) << "do_partitions success reboot"; #ifndef UPDATER_UT @@ -115,6 +115,9 @@ int32_t UpdatePartitions::Execute(uscript::UScriptEnv &env, uscript::UScriptCont UPDATER_ERROR_CHECK(info != nullptr, "Error to get file info", return USCRIPT_ERROR_EXECUTE); std::string tmpPath = "/data/updater"; std::string tmpPath1 = tmpPath + filePath; + char realPath[PATH_MAX + 1] = {}; + UPDATER_ERROR_CHECK(realpath(tmpPath1.c_str(), realPath) != nullptr, + "Error to create tmpPath1", return USCRIPT_ERROR_EXECUTE); ret = env.GetPkgManager()->CreatePkgStream(outStream, tmpPath1, info->unpackedSize, PkgStream::PkgStreamType_Write); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream", @@ -122,14 +125,14 @@ int32_t UpdatePartitions::Execute(uscript::UScriptEnv &env, uscript::UScriptCont ret = env.GetPkgManager()->ExtractFile(filePath, outStream); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file", env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE); - FILE *fp = fopen(tmpPath1.c_str(), "rb"); + FILE *fp = fopen(realPath, "rb"); if (!fp) { LOG(ERROR) << "Open " << tmpPath1 << " failed: " << errno; env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE; } char partitionInfo[MAX_LOG_BUF_SIZE]; - int32_t partitionCount = fread(partitionInfo, 1, MAX_LOG_BUF_SIZE, fp); + size_t partitionCount = fread(partitionInfo, 1, MAX_LOG_BUF_SIZE, fp); fclose(fp); if (partitionCount <= LEAST_PARTITION_COUNT) { env.GetPkgManager()->ClosePkgStream(outStream); diff --git a/services/updater_binary/update_processor.cpp b/services/updater_binary/update_processor.cpp index 8bcc08c0af0badf4efa0a63807de54f4f9041ebd..e27fbcfee3085b10f3e7aef0b61e4c9322456192 100644 --- a/services/updater_binary/update_processor.cpp +++ b/services/updater_binary/update_processor.cpp @@ -21,6 +21,9 @@ #include "applypatch/partition_record.h" #include "log.h" #include "pkg_manager.h" +#ifdef UPDATER_USE_PTABLE +#include "ptable_manager.h" +#endif #include "script_instruction.h" #include "script_manager.h" #include "update_image_block.h" @@ -33,6 +36,8 @@ using namespace updater; namespace updater { size_t UScriptInstructionRawImageWrite::totalSize_ = 0; size_t UScriptInstructionRawImageWrite::readSize_ = 0; +const std::string PREFIX_PARTITION_NODE = "/dev/block/by-name/"; +const std::string PREFIX_UFS_NODE = "/dev/block/sd"; UpdaterEnv::~UpdaterEnv() { if (factory_ != nullptr) { @@ -59,7 +64,7 @@ UScriptInstructionFactoryPtr UpdaterEnv::GetInstructionFactory() const std::vector UpdaterEnv::GetInstructionNames() const { static std::vector updaterCmds = { - "sparse_image_write", "sha_check", "first_block_check", "block_update", + "sha_check", "first_block_check", "block_update", "raw_image_write", "update_partitions" }; return updaterCmds; @@ -68,9 +73,7 @@ const std::vector UpdaterEnv::GetInstructionNames() const int32_t UpdaterInstructionFactory::CreateInstructionInstance(UScriptInstructionPtr& instr, const std::string& name) { - if (name == "sparse_image_write") { - instr = new UScriptInstructionSparseImageWrite(); - } else if (name == "sha_check") { + if (name == "sha_check") { instr = new UScriptInstructionShaCheck(); } else if (name == "first_block_check") { instr = new UScriptInstructionBlockCheck(); @@ -99,7 +102,7 @@ int UScriptInstructionRawImageWrite::RawImageWriteProcessor(const PkgBuffer &buf return PKG_SUCCESS; } - bool ret = writer->Write(const_cast(buffer.buffer), size, WRITE_RAW, ""); + bool ret = writer->Write(const_cast(buffer.buffer), size); if (!ret) { LOG(ERROR) << "Write " << size << " byte(s) failed"; return PKG_INVALID_STREAM; @@ -108,7 +111,6 @@ int UScriptInstructionRawImageWrite::RawImageWriteProcessor(const PkgBuffer &buf if (totalSize_ != 0) { readSize_ += size; writer->GetUpdaterEnv()->PostMessage("set_progress", std::to_string((float)readSize_ / totalSize_)); - writer->GetUpdaterEnv()->PostMessage("data", std::to_string(size)); } return PKG_SUCCESS; @@ -119,9 +121,6 @@ int32_t UScriptInstructionRawImageWrite::Execute(uscript::UScriptEnv &env, uscri std::string partitionName; int32_t ret = context.GetParam(0, partitionName); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get partitionName", return ret); - std::string imageFilename; - ret = context.GetParam(1, imageFilename); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get imageFilename", return ret); if (env.IsRetry()) { LOG(DEBUG) << "Retry updater, check if current partition updated already during last time"; @@ -134,22 +133,37 @@ int32_t UScriptInstructionRawImageWrite::Execute(uscript::UScriptEnv &env, uscri LOG(INFO) << "UScriptInstructionRawImageWrite::Execute " << partitionName; UPDATER_ERROR_CHECK(env.GetPkgManager() != nullptr, "Error to get pkg manager", return USCRIPT_ERROR_EXECUTE); - std::unique_ptr writer = DataWriter::CreateDataWriter(WRITE_RAW, partitionName, - static_cast(&env)); + std::string writePath; + uint64_t offset = 0; + uint64_t partitionSize = 0; + if (GetWritePathAndOffset(partitionName, writePath, offset, partitionSize) != USCRIPT_SUCCESS) { + LOG(ERROR) << "Get partition:%s WritePathAndOffset fail \'" << + partitionName.substr(1, partitionName.size()) << "\'."; + return USCRIPT_ERROR_EXECUTE; + } + + std::unique_ptr writer = DataWriter::CreateDataWriter(WRITE_RAW, writePath, + static_cast(&env), offset); UPDATER_ERROR_CHECK(writer != nullptr, "Error to create writer", return USCRIPT_ERROR_EXECUTE); // Extract partition information hpackage::PkgManager::StreamPtr outStream = nullptr; - const FileInfo *info = env.GetPkgManager()->GetFileInfo(imageFilename); + const FileInfo *info = env.GetPkgManager()->GetFileInfo(partitionName); UPDATER_ERROR_CHECK(info != nullptr, "Error to get file info", DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); totalSize_ = info->unpackedSize; +#ifdef UPDATER_USE_PTABLE + UPDATER_ERROR_CHECK(partitionSize >= totalSize_, + "partition size: " << partitionSize << " is short than image size: " << totalSize_, + DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); +#endif + ret = env.GetPkgManager()->CreatePkgStream(outStream, - imageFilename, RawImageWriteProcessor, writer.get()); + partitionName, RawImageWriteProcessor, writer.get()); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream", DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); - ret = env.GetPkgManager()->ExtractFile(imageFilename, outStream); + ret = env.GetPkgManager()->ExtractFile(partitionName, outStream); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file", env.GetPkgManager()->ClosePkgStream(outStream); DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); @@ -164,57 +178,6 @@ int32_t UScriptInstructionRawImageWrite::Execute(uscript::UScriptEnv &env, uscri return ret; } -int32_t UScriptInstructionSparseImageWrite::Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context) -{ - std::string partitionName; - int32_t ret = context.GetParam(0, partitionName); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get param", return ret); - - if (env.IsRetry()) { - LOG(DEBUG) << "Retry updater, check if current partition updated already during last time."; - bool isUpdated = PartitionRecord::GetInstance().IsPartitionUpdated(partitionName); - if (isUpdated) { - LOG(INFO) << partitionName << " already updated, skip"; - return USCRIPT_SUCCESS; - } - } - LOG(INFO) << "UScriptInstructionSparseImageWrite::Execute " << partitionName; - UPDATER_ERROR_CHECK(env.GetPkgManager() != nullptr, "Error to get pkg manager", return USCRIPT_ERROR_EXECUTE); - - hpackage::PkgManager::StreamPtr outStream = nullptr; - const FileInfo *info = env.GetPkgManager()->GetFileInfo(partitionName); - UPDATER_ERROR_CHECK(info != nullptr, "Error to get file info", return USCRIPT_ERROR_EXECUTE); - - ret = env.GetPkgManager()->CreatePkgStream(outStream, - partitionName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream", - return USCRIPT_ERROR_EXECUTE); - - ret = env.GetPkgManager()->ExtractFile(partitionName, outStream); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file", - env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE); - std::unique_ptr writer = DataWriter::CreateDataWriter(WRITE_SPARSE, partitionName); - UPDATER_ERROR_CHECK(writer != nullptr, "Error to create writer", - env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE); - - size_t size = 0; - uint8_t* buffer = nullptr; - outStream->GetBuffer(buffer, size); - - ret = writer->Write(buffer, size, WRITE_SPARSE, partitionName); - if (ret != true) { - LOG(ERROR) << "writer " << partitionName.substr(1, partitionName.size()) << " failed "; - ret = USCRIPT_ERROR_EXECUTE; - } else { - PartitionRecord::GetInstance().RecordPartitionUpdateStatus(partitionName, true); - ret = USCRIPT_SUCCESS; - } - - env.GetPkgManager()->ClosePkgStream(outStream); - DataWriter::ReleaseDataWriter(writer); - return ret; -} - int ExecUpdate(PkgManager::PkgManagerPtr pkgManager, int retry, PostMessageFunction postMessage) { UpdaterEnv* env = new UpdaterEnv(pkgManager, postMessage, retry); @@ -233,6 +196,32 @@ int ExecUpdate(PkgManager::PkgManagerPtr pkgManager, int retry, PostMessageFunct delete env; return ret; } + +int UScriptInstructionRawImageWrite::GetWritePathAndOffset(const std::string &partitionName, std::string &writePath, + uint64_t &offset, uint64_t &partitionSize) +{ +#ifdef UPDATER_USE_PTABLE + PackagePtable& packagePtb = PackagePtable::GetInstance(); + Ptable::PtnInfo ptnInfo; + if (!packagePtb.GetPartionInfoByName(partitionName, ptnInfo)) { + LOG(ERROR) << "Datawriter: cannot find device path for partition \'" << + partitionName.substr(1, partitionName.size()) << "\'."; + return USCRIPT_ERROR_EXECUTE; + } + char lunIndexName = 'a' + ptnInfo.lun; + writePath = PREFIX_UFS_NODE + lunIndexName; + offset = ptnInfo.startAddr; + partitionSize = ptnInfo.partitionSize; +#else + writePath = GetBlockDeviceByMountPoint(partitionName); + if (writePath.empty()) { + LOG(ERROR) << "Datawriter: cannot find device path for partition \'" << + partitionName.substr(1, partitionName.size()) << "\'."; + return USCRIPT_ERROR_EXECUTE; + } +#endif + return USCRIPT_SUCCESS; +} } // updater int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath) @@ -248,8 +237,14 @@ int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::vector components; int32_t ret = pkgManager->LoadPackage(packagePath, keyPath, components); UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "Fail to load package", + fclose(pipeWrite); + pipeWrite = nullptr; PkgManager::ReleasePackageInstance(pkgManager); return EXIT_INVALID_ARGS); +#ifdef UPDATER_USE_PTABLE + PackagePtable& packagePtb = PackagePtable::GetInstance(); + packagePtb.LoadPartitionInfo(pkgManager); +#endif ret = updater::ExecUpdate(pkgManager, retry, [&pipeWrite](const char *cmd, const char *content) { diff --git a/services/updater_binary/update_processor.h b/services/updater_binary/update_processor.h index 3ed2a86fe7481673935e0fb891c62c94d3792ada..1be4484dcb88a6db7ec36f3ad891df83906e4a25 100644 --- a/services/updater_binary/update_processor.h +++ b/services/updater_binary/update_processor.h @@ -37,21 +37,17 @@ public: virtual ~UpdaterInstructionFactory() {} }; -class UScriptInstructionSparseImageWrite : public uscript::UScriptInstruction { -public: - UScriptInstructionSparseImageWrite() {} - virtual ~UScriptInstructionSparseImageWrite() {} - int32_t Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context) override; -}; - class UScriptInstructionRawImageWrite : public uscript::UScriptInstruction { public: UScriptInstructionRawImageWrite() {} virtual ~UScriptInstructionRawImageWrite() {} int32_t Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context) override; + private: static int RawImageWriteProcessor(const hpackage::PkgBuffer &buffer, size_t size, size_t start, bool isFinish, const void* context); + int GetWritePathAndOffset(const std::string &partitionName, std::string &writePath, uint64_t &offset, + uint64_t &partitionSize); static size_t totalSize_; static size_t readSize_; }; @@ -66,5 +62,6 @@ enum EXIT_CODES { }; int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath); +void GetPartitionPathFromName(const std::string &partitionName, std::string &partitionPath); #endif /* UPDATE_PROCESSOR_H */ diff --git a/services/updater_main.cpp b/services/updater_main.cpp index 9b393a6d3f2354c575c7d419565461fb553ad043..3fe28dd0a88cea72ce1a0e8ceee2a53c7526ab49 100644 --- a/services/updater_main.cpp +++ b/services/updater_main.cpp @@ -77,7 +77,7 @@ static void SetRetryCountToMisc(int retryCount, const std::vector a "SetRetryCountToMisc snprintf_s failed", return); UPDATER_ERROR_CHECK(!strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1), "SetRetryCountToMisc strncat_s failed", return); - UPDATER_ERROR_CHECK_NOT_RETURN(WriteUpdaterMessage(MISC_FILE, msg) == true, "Write command to misc failed."); + UPDATER_ERROR_CHECK_NOT_RETURN(WriteUpdaterMiscMsg(msg) == true, "Write command to misc failed."); } static int DoFactoryReset(FactoryResetMode mode, const std::string &path) @@ -130,8 +130,8 @@ UpdaterStatus UpdaterFromSdcard() LOG(INFO) << "UpdaterFromSdcard start, sdcard updaterPath : " << SDCARD_CARD_PKG_PATH; g_logLabel->SetText("Don't remove SD Card!"); - usleep(DISPLAY_TIME); - UpdaterStatus updateRet = DoInstallUpdaterPackage(pkgManager, SDCARD_CARD_PKG_PATH.c_str(), 0); + utils::UsSleep(DISPLAY_TIME); + UpdaterStatus updateRet = DoInstallUpdaterPackage(pkgManager, SDCARD_CARD_PKG_PATH.c_str(), 0, SDCARD_UPDATE); if (updateRet != UPDATE_SUCCESS) { std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); g_logLabel->SetText("SD Card update failed!"); @@ -167,7 +167,7 @@ static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, const std::v } UPDATER_CHECK_ONLY_RETURN(SetupPartitions() == 0, ShowText(GetUpdateInfoLabel(), "Setup partitions failed"); return UPDATE_ERROR); - status = DoInstallUpdaterPackage(manager, upParams.updatePackage, upParams.retryCount); + status = DoInstallUpdaterPackage(manager, upParams.updatePackage, upParams.retryCount, HOTA_UPDATE); if (status != UPDATE_SUCCESS) { std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); std::string errMsg = ((status == UPDATE_SPACE_NOTENOUGH) ? "Free space is not enough" : "Update failed!"); @@ -194,6 +194,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, if (upParams.updatePackage != "") { ShowUpdateFrame(true); status = InstallUpdaterPackage(upParams, args, manager); + WriteOtaResult(status); UPDATER_CHECK_ONLY_RETURN(status == UPDATE_SUCCESS, return status); } else if (upParams.factoryWipeData) { LOG(INFO) << "Factory level FactoryReset begin"; @@ -231,7 +232,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, } static UpdaterStatus StartUpdater(PkgManager::PkgManagerPtr manager, const std::vector &args, - char **argv) + char **argv, PackageUpdateMode &mode) { UpdaterParams upParams { false, false, 0, "" @@ -251,8 +252,10 @@ static UpdaterStatus StartUpdater(PkgManager::PkgManagerPtr manager, const std:: std::string option = OPTIONS[optionIndex].name; if (option == "update_package") { upParams.updatePackage = optarg; + mode = HOTA_UPDATE; } else if (option == "retry_count") { upParams.retryCount = atoi(optarg); + mode = HOTA_UPDATE; } else if (option == "factory_wipe_data") { upParams.factoryWipeData = true; } else if (option == "user_wipe_data") { @@ -280,13 +283,16 @@ int UpdaterMain(int argc, char **argv) { UpdaterStatus status = UPDATE_UNKNOWN; PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance(); + UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_INIT_EVENT); std::vector args = ParseParams(argc, argv); LOG(INFO) << "Ready to start"; #ifndef UPDATER_UT UpdaterUiInit(); #endif - status = StartUpdater(manager, args, argv); + UpdaterInit::GetInstance().InvokeEvent(UPDATER_INIT_EVENT); + PackageUpdateMode mode = UNKNOWN_UPDATE; + status = StartUpdater(manager, args, argv, mode); std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); #ifndef UPDATER_UT if (status != UPDATE_SUCCESS && status != UPDATE_SKIP) { diff --git a/services/updater_main.h b/services/updater_main.h index fef8b7a8b443e726941a18bff640c4d59e83bc6b..4b8e7a21c3167b23830005e91f4e07a5b9e32ba0 100644 --- a/services/updater_main.h +++ b/services/updater_main.h @@ -18,9 +18,46 @@ #include #include #include +#include "macros.h" #include "updater/updater.h" namespace updater { +enum UpdaterInitEvent { + UPDATER_PRE_INIT_EVENT = 0, + UPDATER_INIT_EVENT, + UPDATER_POST_INIT_EVENT, + + UPDATER_INIT_EVENT_BUTT +}; + +using InitHandler = void (*)(void); + +class UpdaterInit { + DEFINE_COMMON_FOR_SINGLETON(UpdaterInit) +public: + void InvokeEvent(enum UpdaterInitEvent eventId) + { + if (eventId >= UPDATER_INIT_EVENT_BUTT) { + return; + } + for (const auto &handler : initEvent_[eventId]) { + if (handler != nullptr) { + handler(); + } + } + } + void SubscribeEvent(enum UpdaterInitEvent eventId, InitHandler handler) + { + if (eventId < UPDATER_INIT_EVENT_BUTT) { + initEvent_[eventId].push_back(handler); + } + } +private: + UpdaterInit() = default; + ~UpdaterInit() = default; + std::vector initEvent_[UPDATER_INIT_EVENT_BUTT]; +}; + enum FactoryResetMode { USER_WIPE_DATA = 0, FACTORY_WIPE_DATA, diff --git a/services/updater_utils.cpp b/services/updater_utils.cpp index dc928c749c9385ec5f244a57ee364f11bad13224..fdf6d385c7a3e738ea7693c31dbd16e2a909fa32 100755 --- a/services/updater_utils.cpp +++ b/services/updater_utils.cpp @@ -30,86 +30,9 @@ #include "updater_ui.h" #include "utils.h" -namespace { -static constexpr int USER_ROOT_AUTHORITY = 0; -static constexpr int GROUP_SYS_AUTHORITY = 1000; -} namespace updater { using namespace hpackage; using namespace updater::utils; -void CompressLogs(const std::string &name) -{ - PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); - UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return); - std::vector> files; - // Build the zip file to be packaged - std::vector testFileNames; - std::string realName = name.substr(name.find_last_of("/") + 1); - testFileNames.push_back(realName); - for (auto name : testFileNames) { - ZipFileInfo file; - file.fileInfo.identity = name; - file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; - file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; - std::string fileName = "/data/updater/log/" + name; - files.push_back(std::pair(fileName, file)); - } - - PkgInfo pkgInfo; - pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; - pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; - pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; - - char realTime[MAX_TIME_SIZE] = { 0 }; - auto sysTime = std::chrono::system_clock::now(); - auto currentTime = std::chrono::system_clock::to_time_t(sysTime); - struct tm *localTime = std::localtime(¤tTime); - if (localTime != nullptr) { - std::strftime(realTime, sizeof(realTime), "%H_%M_%S", localTime); - } - char pkgName[MAX_LOG_NAME_SIZE]; - UPDATER_CHECK_ONLY_RETURN(snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1, - "/data/updater/log/%s_%s.zip", realName.c_str(), realTime) != -1, return); - int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files); - UPDATER_CHECK_ONLY_RETURN(ret != 0, return); - UPDATER_CHECK_ONLY_RETURN(DeleteFile(name) == 0, return); -} - -bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog) -{ - UPDATER_WARING_CHECK(MountForPath(UPDATER_LOG_DIR) == 0, "MountForPath /data/log failed!", return false); - if (access(UPDATER_LOG_DIR.c_str(), 0) != 0) { - UPDATER_ERROR_CHECK(!MkdirRecursive(UPDATER_LOG_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), - "MkdirRecursive error!", return false); - UPDATER_ERROR_CHECK(chown(UPDATER_PATH.c_str(), USER_ROOT_AUTHORITY, GROUP_SYS_AUTHORITY) == 0, - "Chown failed!", return false); - UPDATER_ERROR_CHECK(chmod(UPDATER_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0, - "Chmod failed!", return false); - } - - FILE *dFp = fopen(dLog.c_str(), "ab+"); - UPDATER_ERROR_CHECK(dFp != nullptr, "open log failed", return false); - - FILE *sFp = fopen(sLog.c_str(), "r"); - UPDATER_ERROR_CHECK(sFp != nullptr, "open log failed", fclose(dFp); - return false); - - char buf[MAX_LOG_BUF_SIZE]; - size_t bytes; - while ((bytes = fread(buf, 1, sizeof(buf), sFp)) != 0) { - int ret = fwrite(buf, 1, bytes, dFp); - if (ret < 0) { - break; - } - } - (void)fseek(dFp, 0, SEEK_END); - UPDATER_INFO_CHECK(ftell(dFp) < MAX_LOG_SIZE, "log size greater than 5M!", CompressLogs(dLog)); - sync(); - (void)fclose(sFp); - (void)fclose(dFp); - return true; -} - static bool IsDir(const std::string &path) { struct stat st {}; @@ -129,7 +52,8 @@ static bool DeleteUpdaterPath(const std::string &path) struct dirent *dp = nullptr; while ((dp = readdir(pDir.get())) != nullptr) { std::string currentName(dp->d_name); - if (currentName[0] != '.' && (currentName.compare("log") != 0)) { + if (currentName[0] != '.' && (currentName.compare("log") != 0) && + (currentName.compare(UPDATER_RESULT_FILE) != 0)) { std::string tmpName(path); tmpName.append("/" + currentName); if (IsDir(tmpName)) { @@ -146,9 +70,12 @@ static bool DeleteUpdaterPath(const std::string &path) static bool ClearMisc() { struct UpdateMessage cleanBoot {}; - UPDATER_ERROR_CHECK(WriteUpdaterMessage(MISC_FILE, cleanBoot) == true, + UPDATER_ERROR_CHECK(WriteUpdaterMiscMsg(cleanBoot) == true, "ClearMisc clear boot message to misc failed", return false); - auto fp = std::unique_ptr(fopen(MISC_FILE.c_str(), "rb+"), fclose); + auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH); + UPDATER_INFO_CHECK(!miscBlockDev.empty(), "cannot get block device of partition", miscBlockDev = MISC_FILE); + LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev; + auto fp = std::unique_ptr(fopen(miscBlockDev.c_str(), "rb+"), fclose); UPDATER_FILE_CHECK(fp != nullptr, "WriteVersionCode fopen failed", return false); (void)fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET); off_t clearOffset = 0; @@ -178,32 +105,14 @@ bool IsSDCardExist(const std::string &sdcardPath) } } -void PostUpdaterForSdcard(std::string &updaterLogPath, std::string &stageLogPath, std::string &errorCodePath) -{ - if (SetupPartitions() != 0) { - ShowText(GetUpdateInfoLabel(), "Mount data failed."); - LOG(ERROR) << "Mount for /data failed."; - std::string sdcardPath = GetBlockDeviceByMountPoint(SDCARD_PATH); - if (IsSDCardExist(sdcardPath)) { - if (MountForPath(SDCARD_PATH) != 0) { - int ret = mount(sdcardPath.c_str(), SDCARD_PATH.c_str(), "vfat", 0, NULL); - UPDATER_WARING_CHECK(ret == 0, "Mount for /sdcard failed!", return); - } - updaterLogPath = "/sdcard/updater/log/updater_log"; - stageLogPath = "/sdcard/updater/log/updater_stage_log"; - errorCodePath = "/sdcard/updater/log/error_code.log"; - } - } - return; -} - void PostUpdater(bool clearMisc) { STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater"; - std::string updaterLogPath = "/data/updater/log/updater_log"; - std::string stageLogPath = "/data/updater/log/updater_stage_log"; - std::string errorCodePath = "/data/updater/log/error_code.log"; - PostUpdaterForSdcard(updaterLogPath, stageLogPath, errorCodePath); + std::string updaterLogPath = UPDATER_LOG; + std::string stageLogPath = UPDATER_STAGE_LOG; + std::string errorCodePath = ERROR_CODE_PATH; + + (void)SetupPartitions(); // clear update misc partition. if (clearMisc) { UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); @@ -231,51 +140,21 @@ void PostUpdater(bool clearMisc) ret = CopyUpdaterLogs(flashd::FLASHD_HDC_LOG_PATH, UPDATER_HDC_LOG); UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error hdc log failed!"); - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + mode_t mode = 0640; chmod(updaterLogPath.c_str(), mode); - chmod(stageLogPath.c_str(), mode); + chmod(UPDATER_HDC_LOG.c_str(), mode); chmod(errorCodePath.c_str(), mode); STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater"; ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath); + chmod(stageLogPath.c_str(), mode); UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy stage log failed!"); } -int IsSpaceCapacitySufficient(const std::string &packagePath) -{ - hpackage::PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance(); - UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return UPDATE_CORRUPT); - std::vector fileIds; - int ret = pkgManager->LoadPackageWithoutUnPack(packagePath, fileIds); - UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "LoadPackageWithoutUnPack failed", - PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT); - const FileInfo *info = pkgManager->GetFileInfo("update.bin"); - UPDATER_ERROR_CHECK(info != nullptr, "update.bin is not exist", - PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT); - uint64_t needSpace = static_cast(info->unpackedSize); - PkgManager::ReleasePackageInstance(pkgManager); - - struct statvfs64 updaterVfs {}; - if (strncmp(packagePath.c_str(), SDCARD_CARD_PATH.c_str(), SDCARD_CARD_PATH.size()) == 0) { // for sdcard - ret = statvfs64(SDCARD_PATH.c_str(), &updaterVfs); - UPDATER_ERROR_CHECK(ret >= 0, "Statvfs read /sdcard error!", return UPDATE_ERROR); - } else { - needSpace += MAX_LOG_SPACE; - ret = statvfs64(UPDATER_PATH.c_str(), &updaterVfs); - UPDATER_ERROR_CHECK(ret >= 0, "Statvfs read /data error!", return UPDATE_ERROR); - } - auto freeSpaceSize = static_cast(updaterVfs.f_bfree); - auto blockSize = static_cast(updaterVfs.f_bsize); - uint64_t totalFreeSize = freeSpaceSize * blockSize; - UPDATER_ERROR_CHECK(totalFreeSize > needSpace, - "Can not update, free space is not enough", return UPDATE_SPACE_NOTENOUGH); - return UPDATE_SUCCESS; -} - std::vector ParseParams(int argc, char **argv) { struct UpdateMessage boot {}; // read from misc - UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(MISC_FILE, boot) == true, + UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMiscMsg(boot) == true, "ReadUpdaterMessage MISC_FILE failed!"); // if boot.update is empty, read from command.The Misc partition may have dirty data, // so strlen(boot.update) is not used, which can cause system exceptions. @@ -300,7 +179,7 @@ int GetBootMode(int &mode) #endif struct UpdateMessage boot {}; // read from misc - bool ret = ReadUpdaterMessage(MISC_FILE, boot); + bool ret = ReadUpdaterMiscMsg(boot); if (!ret) { return -1; } diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 7a945c0c9fa2b216b0588e8a97cec7590d60addd..1892aa405e3520a74e76750cbab8ccdd685e2ac0 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -14,16 +14,23 @@ import("//build/ohos.gni") ohos_static_library("libutils") { - sources = [ "utils.cpp" ] + sources = [ + "json/json_node.cpp", + "utils.cpp", + ] include_dirs = [ "include", "//base/update/updater/interfaces/kits/include/", "//base/update/updater/services/include/", "//third_party/bounds_checking_function/include", + "//third_party/cJSON", ] - deps = [ "//third_party/bounds_checking_function:libsec_static" ] + deps = [ + "//third_party/bounds_checking_function:libsec_static", + "//third_party/cJSON:cjson_static", + ] external_deps = [ "init:libbegetutil" ] subsystem_name = "updater" diff --git a/utils/include/macros.h b/utils/include/macros.h new file mode 100644 index 0000000000000000000000000000000000000000..860d06c18d7f1826b47cd46e6193f3efac83d06e --- /dev/null +++ b/utils/include/macros.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef MACRO_H +#define MACRO_H + +#define DISALLOW_COPY_MOVE_ASSIGN(ClassName) \ + ClassName &operator = (const ClassName &) = delete; \ + ClassName &operator = (ClassName &&) = delete + +#define DISALLOW_COPY_MOVE_CONSTRUCT(ClassName) \ + ClassName(const ClassName &) = delete; \ + ClassName(ClassName &&) = delete + +#define DISALLOW_COPY_MOVE(ClassName) \ + DISALLOW_COPY_MOVE_ASSIGN(ClassName); \ + DISALLOW_COPY_MOVE_CONSTRUCT(ClassName) + +#define DEFINE_COMMON_FOR_SINGLETON(className) \ + DISALLOW_COPY_MOVE(className); \ + public: \ + static className &GetInstance() \ + { \ + static className instance; \ + return instance; \ + } + +#endif \ No newline at end of file diff --git a/utils/include/utils.h b/utils/include/utils.h index 62366084e62e2ca8e8aab82947224f6cd2a734a6..42d6a101abf94fcfcb0f2b0d2e8b578f660b6cb8 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -55,6 +55,10 @@ bool ReadFully(int fd, void* data, size_t size); bool ReadFileToString(int fd, std::string &content); bool WriteStringToFile(int fd, const std::string& content); std::string GetLocalBoardId(); +bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog); +void CompressLogs(const std::string &name); +void WriteOtaResult(const int status); +void UsSleep(int usec); } // utils } // updater #endif // UPDATER_UTILS_H diff --git a/utils/json/json_node.cpp b/utils/json/json_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce02483da29f75cb433610684e5777ec045d25fb --- /dev/null +++ b/utils/json/json_node.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2022 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 "json_node.h" + +#include "log/log.h" + +namespace updater { +namespace { +inline const std::unordered_map &GetJsonTypeMap() +{ + static const std::unordered_map jsonTypeMap { + { cJSON_Object, NodeType::OBJECT }, { cJSON_Array, NodeType::ARRAY }, { cJSON_Number, NodeType::INT }, + { cJSON_String, NodeType::STRING }, { cJSON_False, NodeType::BOOL }, { cJSON_True, NodeType::BOOL }, + { cJSON_NULL, NodeType::NUL }, + }; + return jsonTypeMap; +} + +inline const JsonNode &GetInvalidNode() +{ + static JsonNode emptyNode = {}; // used for invalid json node + return emptyNode; +} +} // namespace + +JsonNode::JsonNode() : type_ {NodeType::UNKNOWN} +{ +} + +JsonNode::JsonNode(const std::string &str, bool needDeletecJSON) : JsonNode(cJSON_Parse(str.c_str()), needDeletecJSON) +{ +} + +JsonNode::JsonNode(const cJSON *root, bool needDelete) +{ + if (root == nullptr || cJSON_IsInvalid(root)) { + LOG(ERROR) << "root is not valid"; + type_ = NodeType::UNKNOWN; + if (needDelete) { + cJSON_Delete(const_cast(root)); + } + return; + } + if (auto it = GetJsonTypeMap().find(root->type); it != GetJsonTypeMap().end()) { + type_ = it->second; + } + innerNodesList_.clear(); + Parse(root); +} + +void JsonNode::Parse(const cJSON *root) +{ + cJSON *element {}; + size_ = 1; + switch (type_) { + case NodeType::OBJECT: { + innerObj_ = std::make_optional(); + auto &optNodeMap = std::get>(innerObj_); + cJSON_ArrayForEach(element, root) + { + std::unique_ptr uPtr = std::make_unique(element, false); + innerNodesList_.push_back(*uPtr); + (*optNodeMap).emplace(element->string, std::move(uPtr)); + } + size_ = static_cast(innerNodesList_.size()); + break; + } + case NodeType::ARRAY: { + innerObj_ = std::make_optional(); + auto &optNodeVec = std::get>(innerObj_); + cJSON_ArrayForEach(element, root) + { + std::unique_ptr uPtr = std::make_unique(element, false); + innerNodesList_.push_back(*uPtr); + (*optNodeVec).push_back(std::move(uPtr)); + } + size_ = static_cast(innerNodesList_.size()); + break; + } + case NodeType::INT: + innerObj_ = std::make_optional(root->valueint); + innerNodesList_.push_back(*this); + break; + case NodeType::STRING: + innerObj_ = std::make_optional(root->valuestring); + innerNodesList_.push_back(*this); + break; + case NodeType::BOOL: + innerObj_ = std::make_optional(root->type == cJSON_True); + innerNodesList_.push_back(*this); + break; + case NodeType::NUL: + break; + default: + LOG(ERROR) << "unknown node type"; + break; + } + if (root->string) { + key_ = root->string; + } +} + +JsonNode::~JsonNode() = default; + +const JsonNode &JsonNode::operator[](int idx) const +{ + auto optVec = std::get_if>(&innerObj_); + if (optVec == nullptr || *optVec == std::nullopt) { + return GetInvalidNode(); // type not matched + } + const NodeVec &nodeVec = **optVec; + if (idx < 0 || idx >= size_) { + return GetInvalidNode(); + } + return *nodeVec[idx]; +} + +const JsonNode &JsonNode::operator[](const std::string &key) const +{ + auto optMap = std::get_if>(&innerObj_); + if (optMap == nullptr || *optMap == std::nullopt) { + return GetInvalidNode(); // type not matched + } + const NodeMap &nodeMap = **optMap; + if (auto it = nodeMap.find(key); it != nodeMap.end()) { + return *(it->second); + } + return GetInvalidNode(); +} + +std::list>::const_iterator JsonNode::begin() const +{ + return innerNodesList_.cbegin(); +} + +std::list>::const_iterator JsonNode::end() const +{ + return innerNodesList_.cend(); +} +} // namespace updater \ No newline at end of file diff --git a/utils/json/json_node.h b/utils/json/json_node.h new file mode 100644 index 0000000000000000000000000000000000000000..f0d3363819d76d47f4453be3bacacad5414d644c --- /dev/null +++ b/utils/json/json_node.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef JSON_NODE_H +#define JSON_NODE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cJSON.h" +#include "macros.h" +#include "traits_util.h" + +namespace updater { +class JsonNode; + +enum class NodeType { OBJECT, INT, STRING, ARRAY, BOOL, NUL, UNKNOWN }; + +using NodeMap = std::unordered_map>; +using NodeVec = std::vector>; +using cJSONPtr = std::unique_ptr; + +template +using optionalVariant = std::variant ...>; + +class JsonNode { + DISALLOW_COPY_MOVE(JsonNode); +public: + JsonNode(); + explicit JsonNode(const std::string &str, bool needDeletecJSON = true); + explicit JsonNode(const cJSON *root, bool needDeletecJSON = true); + ~JsonNode(); + + const JsonNode &operator[](int idx) const; + const JsonNode &operator[](const std::string &key) const; + + template + std::optional As() const + { + if (auto optPtr = std::get_if>>(&innerObj_); optPtr) { + return *optPtr; + } + return std::nullopt; + } + + template + bool operator==(T rhs) const + { + if (auto optPtr = std::get_if>>(&innerObj_); optPtr) { + return *optPtr == rhs; + } + return false; + } + + int Size() const + { + return size_; + } + NodeType Type() const + { + return type_; + } + std::optional Key() const + { + return key_; + } + std::list>::const_iterator begin() const; + std::list>::const_iterator end() const; +private: + void Parse(const cJSON *root); + template + void Assign(T rhs) + { + if (innerObj_.valueless_by_exception()) { + innerObj_ = std::optional(rhs); + } + if (auto optPtr = std::get_if>(&innerObj_); optPtr) { + *optPtr = std::optional(rhs); + } + } + int size_ {1}; + NodeType type_ {NodeType::UNKNOWN}; /* json node type */ + std::optional key_ {std::nullopt}; /* key for object items */ + optionalVariant innerObj_ {}; + std::list> innerNodesList_ {}; +}; +} + +#endif // NODE_H \ No newline at end of file diff --git a/utils/json/json_visitor.h b/utils/json/json_visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..d3af6ee1272ece3ceece3b6257c9f75001147ed0 --- /dev/null +++ b/utils/json/json_visitor.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + +#include + +#include "json_node.h" +#include "log/log.h" + +namespace updater { +enum Action { SETVAL, PRINTVAL }; + +template +struct Traits; + +namespace detail { +template +using memberType = std::remove_reference_t::template Get(std::declval()))>; + +template +struct MemberVisitor; + +template +struct StructVisitor { + template + static bool VisitStruct(const JsonNode &node, const JsonNode &defaultNode, T &t, std::index_sequence) + { + constexpr auto key = Traits::MEMBER_KEY[F]; + if (!MemberVisitor::template VisitMember(node[key], defaultNode[key], t)) { + return false; + } + + if constexpr (sizeof...(R) == 0) { + return true; + } else { // don't remove else, otherwise can't compile + return VisitStruct(node, defaultNode, t, std::index_sequence {}); + } + } +}; + +template<> +struct MemberVisitor { + // visit string, int, bool + template + static auto VisitMember(const JsonNode &node, const JsonNode &defaultNode, T &obj) + -> detail::isMatch>, bool> + { + auto r = node.As>(); + auto defaultR = defaultNode.As>(); + if (!r.has_value() && !defaultR.has_value()) { + LOG(ERROR) << Traits::MEMBER_KEY[i] << " has not both default and non-default value!!!"; + return false; + } + if (r) { + Traits::template Get(obj) = *r; + return true; + } + if (defaultR) { + Traits::template Get(obj) = *defaultR; + return true; + } + return false; + } + // visit struct + template + static auto VisitMember(const JsonNode &node, const JsonNode &defaultNode, T &obj) + -> detail::isMatch>::COUNT)>, bool> + { + return StructVisitor::VisitStruct(node, defaultNode, Traits::template Get(obj), + std::make_index_sequence>::COUNT> {}); + } +}; +} // namespace detail + +template +auto Visit(const JsonNode &node, const JsonNode &defaultNode, T &obj) + -> detail::isMatch::COUNT)>, bool> +{ + static_assert(act == SETVAL, + "Only for setting member of struct with default node!"); + return detail::StructVisitor::VisitStruct(node, defaultNode, obj, + std::make_index_sequence::COUNT> {}); +} + +template +auto Visit(const JsonNode &node, T &obj) -> detail::isMatch::COUNT)>, bool> +{ + static_assert(act == SETVAL, + "Only for setting member of struct without default node!"); + static JsonNode dummyNode {}; + return detail::StructVisitor::VisitStruct(node, dummyNode, obj, + std::make_index_sequence::COUNT> {}); +} +} // namespace updater + +#endif diff --git a/utils/json/traits_util.h b/utils/json/traits_util.h new file mode 100644 index 0000000000000000000000000000000000000000..d606f46e210477e366f38dc376a7322740a0de3b --- /dev/null +++ b/utils/json/traits_util.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef TRAITS_UTIL_H +#define TRAITS_UTIL_H + +namespace updater::detail { +template +inline constexpr bool G_IS_NUM = std::is_integral_v && !std::is_same_v; + +template +inline constexpr bool G_IS_BOOL = std::is_same_v; + +template +inline constexpr bool G_IS_STR = (std::is_same_v || std::is_same_v || + std::is_same_v); + +template +inline constexpr bool G_IS_PRINTABLE = (G_IS_NUM || G_IS_BOOL || G_IS_STR); + +template +inline constexpr bool G_IS_BASE_TYPE = (G_IS_NUM || G_IS_BOOL || G_IS_STR); + +template +using isMatch = typename std::enable_if_t; + +template +struct StandardTypeHelper { + static_assert(G_IS_BASE_TYPE); + using type = std::conditional_t, int, std::conditional_t, std::string, bool>>; +}; + +template +using StandardType = typename StandardTypeHelper::type; +} + +#endif diff --git a/utils/utils.cpp b/utils/utils.cpp index 3da6a9a1b0d257080c8287bf23a6639085b1ece1..a4f484b75e4b54a70df221a7e39e14bdc76ed640 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -39,6 +39,10 @@ using namespace hpackage; namespace utils { constexpr uint32_t MAX_PATH_LEN = 256; constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4; +constexpr int USER_ROOT_AUTHORITY = 0; +constexpr int GROUP_SYS_AUTHORITY = 1000; +constexpr int USECONDS_PER_SECONDS = 1000000; // 1s = 1000000us +constexpr int NANOSECS_PER_USECONDS = 1000; // 1us = 1000ns int32_t DeleteFile(const std::string& filename) { UPDATER_ERROR_CHECK (!filename.empty(), "Invalid filename", return -1); @@ -162,18 +166,17 @@ void DoReboot(const std::string& rebootTarget, const std::string &extData) LOG(INFO) << ", rebootTarget: " << rebootTarget; static const int32_t maxCommandSize = 16; LoadFstab(); - auto miscBlockDevice = GetBlockDeviceByMountPoint("/misc"); struct UpdateMessage msg; if (rebootTarget.empty()) { UPDATER_ERROR_CHECK(!memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE), "Memset_s failed", return); - if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { + if (WriteUpdaterMiscMsg(msg) != true) { LOG(INFO) << "DoReboot: WriteUpdaterMessage empty error"; return; } sync(); } else { int result = 0; - bool ret = ReadUpdaterMessage(miscBlockDevice, msg); + bool ret = ReadUpdaterMiscMsg(msg); UPDATER_ERROR_CHECK(ret == true, "DoReboot read misc failed", return); if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) { result = strcpy_s(msg.command, maxCommandSize, "boot_updater"); @@ -193,8 +196,9 @@ void DoReboot(const std::string& rebootTarget, const std::string &extData) } else { UPDATER_ERROR_CHECK(!memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE), "Memset_s failed", return); } - if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { - LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error"; + ret = WriteUpdaterMiscMsg(msg); + if (!ret) { + LOG(INFO) << "DoReboot: WriteUpdaterMiscMsg empty error"; return; } sync(); @@ -234,7 +238,7 @@ bool WriteFully(int fd, const void *data, size_t size) return false; } p += written; - rest -= written; + rest -= static_cast(written); } return true; } @@ -247,7 +251,7 @@ bool ReadFully(int fd, void *data, size_t size) ssize_t sread = read(fd, p, remaining); UPDATER_ERROR_CHECK (sread > 0, "Utils::ReadFully run error", return false); p += sread; - remaining -= sread; + remaining -= static_cast(sread); } return true; } @@ -256,16 +260,16 @@ bool ReadFileToString(int fd, std::string &content) { struct stat sb {}; if (fstat(fd, &sb) != -1 && sb.st_size > 0) { - content.resize(sb.st_size); + content.resize(static_cast(sb.st_size)); } ssize_t n; - size_t remaining = sb.st_size; + auto remaining = static_cast(sb.st_size); auto p = reinterpret_cast(content.data()); while (remaining > 0) { n = read(fd, p, remaining); UPDATER_CHECK_ONLY_RETURN (n > 0, return false); p += n; - remaining -= n; + remaining -= static_cast(n); } return true; } @@ -278,7 +282,7 @@ bool WriteStringToFile(int fd, const std::string& content) ssize_t n = write(fd, p, remaining); UPDATER_CHECK_ONLY_RETURN (n != -1, return false); p += n; - remaining -= n; + remaining -= static_cast(n); } return true; } @@ -287,5 +291,117 @@ std::string GetLocalBoardId() { return "HI3516"; } + +void CompressLogs(const std::string &name) +{ + PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); + UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return); + std::vector> files; + // Build the zip file to be packaged + std::vector testFileNames; + std::string realName = name.substr(name.find_last_of("/") + 1); + testFileNames.push_back(realName); + for (auto name : testFileNames) { + ZipFileInfo file; + file.fileInfo.identity = name; + file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; + file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; + std::string fileName = "/data/updater/log/" + name; + files.push_back(std::pair(fileName, file)); + } + + PkgInfo pkgInfo; + pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; + pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; + pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; + + char realTime[MAX_TIME_SIZE] = {0}; + auto sysTime = std::chrono::system_clock::now(); + auto currentTime = std::chrono::system_clock::to_time_t(sysTime); + struct tm *localTime = std::localtime(¤tTime); + if (localTime != nullptr) { + std::strftime(realTime, sizeof(realTime), "%H_%M_%S", localTime); + } + char pkgName[MAX_LOG_NAME_SIZE]; + UPDATER_CHECK_ONLY_RETURN(snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1, + "/data/updater/log/%s_%s.zip", realName.c_str(), realTime) != -1, return); + int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files); + UPDATER_CHECK_ONLY_RETURN(ret != 0, return); + UPDATER_CHECK_ONLY_RETURN(DeleteFile(name) == 0, return); +} + +bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog) +{ + UPDATER_WARING_CHECK(MountForPath(UPDATER_LOG_DIR) == 0, "MountForPath /data/log failed!", return false); + if (access(UPDATER_LOG_DIR.c_str(), 0) != 0) { + UPDATER_ERROR_CHECK(!MkdirRecursive(UPDATER_LOG_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), + "MkdirRecursive error!", return false); + UPDATER_ERROR_CHECK(chown(UPDATER_PATH.c_str(), USER_ROOT_AUTHORITY, GROUP_SYS_AUTHORITY) == 0, + "Chown failed!", return false); + UPDATER_ERROR_CHECK(chmod(UPDATER_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0, + "Chmod failed!", return false); + } + + FILE* dFp = fopen(dLog.c_str(), "ab+"); + UPDATER_ERROR_CHECK(dFp != nullptr, "open log failed", return false); + + FILE* sFp = fopen(sLog.c_str(), "r"); + UPDATER_ERROR_CHECK(sFp != nullptr, "open log failed", fclose(dFp); return false); + + char buf[MAX_LOG_BUF_SIZE]; + size_t bytes; + while ((bytes = fread(buf, 1, sizeof(buf), sFp)) != 0) { + if (fwrite(buf, 1, bytes, dFp) <= 0) { + LOG(WARNING) << "CopyUpdaterLogs write failed, err:" << errno; + } + } + fseek(dFp, 0, SEEK_END); + UPDATER_INFO_CHECK(ftell(dFp) < MAX_LOG_SIZE, "log size greater than 5M!", CompressLogs(dLog)); + sync(); + fclose(sFp); + fclose(dFp); + return true; +} + +void WriteOtaResult(const int status) +{ + if (access(UPDATER_PATH.c_str(), 0) != 0) { + UPDATER_ERROR_CHECK(!MkdirRecursive(UPDATER_PATH, 0644), + "MkdirRecursive error!", return); + } + + const std::string resultPath = UPDATER_PATH + "/" + UPDATER_RESULT_FILE; + FILE *fp = fopen(resultPath.c_str(), "w+"); + if (fp == nullptr) { + LOG(ERROR) << "open result file failed"; + return; + } + char buf[MAX_RESULT_SIZE] = "pass\n"; + if (status != 0) { + if (sprintf_s(buf, MAX_RESULT_SIZE - 1, "fail:%d\n", status) < 0) { + LOG(WARNING) << "sprintf status fialed"; + } + } + + if (fwrite(buf, 1, strlen(buf) + 1, fp) <= 0) { + LOG(WARNING) << "write result file failed, err:" << errno; + } + + if (fclose(fp) != 0) { + LOG(WARNING) << "close result file failed"; + } + + (void)chown(resultPath.c_str(), USER_ROOT_AUTHORITY, GROUP_SYS_AUTHORITY); + (void)chmod(resultPath.c_str(), 0640); // 0640: -rw-r----- +} + +void UsSleep(int usec) +{ + auto seconds = usec / USECONDS_PER_SECONDS; + long nanoSeconds = static_cast(usec) % USECONDS_PER_SECONDS * NANOSECS_PER_USECONDS; + struct timespec ts = { static_cast(seconds), nanoSeconds }; + while (nanosleep(&ts, &ts) < 0 && errno == EINTR) { + } +} } // utils } // namespace updater diff --git a/utils/write_updater.cpp b/utils/write_updater.cpp index 019cd4e4d0c828c058f79ead42439e16b12dd270..a710265c1730c96145963d214b952fe1964083e4 100644 --- a/utils/write_updater.cpp +++ b/utils/write_updater.cpp @@ -31,8 +31,13 @@ int main(int argc, char **argv) return -1; } + const std::string miscFile = "/dev/block/by-name/misc"; if (strcmp(argv[1], "updater") == 0) { struct UpdateMessage boot {}; + if (argc < BINARY_MAX_ARGS) { + cout << "Please input correct updater command!" << endl; + return -1; + } if (argv[WRITE_SECOND_CMD] != nullptr) { if (snprintf_s(boot.update, sizeof(boot.update), sizeof(boot.update) - 1, "--update_package=%s", argv[WRITE_SECOND_CMD]) == -1) { @@ -40,7 +45,7 @@ int main(int argc, char **argv) return -1; } } - bool ret = WriteUpdaterMessage(MISC_FILE, boot); + bool ret = WriteUpdaterMessage(miscFile, boot); if (!ret) { cout << "WriteUpdaterMessage failed!" << endl; return -1; @@ -51,14 +56,14 @@ int main(int argc, char **argv) cout << "strncpy_s failed!" << endl; return -1; } - bool ret = WriteUpdaterMessage(MISC_FILE, boot); + bool ret = WriteUpdaterMessage(miscFile, boot); if (!ret) { cout << "WriteUpdaterMessage failed!" << endl; return -1; } } else if (strcmp(argv[1], "clear") == 0) { struct UpdateMessage boot {}; - bool ret = WriteUpdaterMessage(MISC_FILE, boot); + bool ret = WriteUpdaterMessage(miscFile, boot); if (!ret) { cout << "WriteUpdaterMessage failed!" << endl; return -1;