From 9cf5e305bf9c9f4aac52a151d18b53a94c6912b7 Mon Sep 17 00:00:00 2001 From: sun_fan Date: Mon, 18 Oct 2021 15:38:42 +0800 Subject: [PATCH 1/5] updater: fix code style Signed-off-by: sun_fan --- services/fs_manager/mount.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/services/fs_manager/mount.cpp b/services/fs_manager/mount.cpp index 20f99e76..2b33668d 100644 --- a/services/fs_manager/mount.cpp +++ b/services/fs_manager/mount.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "fs_manager/mount.h" + #include #include #include -- Gitee From 1fd392d1a06a17ca333fde4f9d943e0d4aa83c59 Mon Sep 17 00:00:00 2001 From: "411148299@qq.com" <411148299@qq.com> Date: Mon, 18 Oct 2021 15:55:59 +0800 Subject: [PATCH 2/5] fix code style Signed-off-by: 411148299@qq.com <411148299@qq.com> --- interfaces/kits/misc_info/BUILD.gn | 1 + ohos.build | 6 +- services/BUILD.gn | 19 +- services/applypatch/BUILD.gn | 1 + services/applypatch/transfer_manager.cpp | 14 +- services/etc/init.cfg | 37 +- services/etc/init.usb.cfg | 15 + services/etc/init.usb.configfs.cfg | 25 + services/flashd/BUILD.gn | 80 +++ services/flashd/blockdevice.cpp | 55 ++ .../fstab.h => flashd/blockdevice.h} | 93 +-- services/flashd/daemon/daemon_updater.cpp | 207 ++++++ services/flashd/daemon/daemon_updater.h | 58 ++ .../daemon/flashd_main.cpp} | 53 +- services/flashd/flash_service.cpp | 612 ++++++++++++++++++ services/flashd/flash_service.h | 77 +++ services/flashd/flash_utils.h | 49 ++ services/flashd/host/host_updater.cpp | 260 ++++++++ services/flashd/host/host_updater.h | 62 ++ services/flashd/partition.cpp | 419 ++++++++++++ services/flashd/partition.h | 82 +++ services/fs_manager/BUILD.gn | 3 +- services/fs_manager/fstab.cpp | 216 ------- services/fs_manager/mount.cpp | 293 ++------- .../include/applypatch/partition_record.h | 2 +- .../include/applypatch/transfer_manager.h | 1 + services/include/applypatch/updater_env.h | 7 +- services/include/flashd/flashd.h | 73 +++ services/include/fs_manager/fstab_api.h | 28 - services/include/fs_manager/mount.h | 12 +- services/include/package/pkg_manager.h | 13 + services/include/updater/updater.h | 17 + services/include/updater/updater_const.h | 2 + services/main.cpp | 34 +- .../package/pkg_manager/pkg_managerImpl.cpp | 37 +- .../package/pkg_manager/pkg_manager_impl.h | 8 + services/package/pkg_manager/pkg_stream.cpp | 10 + services/package/pkg_manager/pkg_stream.h | 22 +- services/package/pkg_package/pkg_gzipfile.h | 3 +- services/package/pkg_package/pkg_lz4file.h | 3 +- services/package/pkg_package/pkg_pkgfile.cpp | 2 + services/package/pkg_package/pkg_pkgfile.h | 4 +- .../package/pkg_package/pkg_upgradefile.cpp | 1 + .../package/pkg_package/pkg_upgradefile.h | 6 +- services/package/pkg_package/pkg_zipfile.h | 3 +- services/ui/surface_dev.cpp | 2 +- services/ui/surface_dev.h | 4 +- services/ui/updater_ui.cpp | 15 + services/ui/updater_ui.h | 7 + services/updater.cpp | 127 ++-- services/updater_binary/BUILD.gn | 1 + services/updater_binary/main.cpp | 2 + services/updater_binary/update_partitions.cpp | 2 +- services/updater_binary/update_processor.cpp | 56 +- services/updater_main.cpp | 152 +---- services/updater_main.h | 4 - services/updater_utils.cpp | 290 +++++++++ .../ReadFstabFromFile_fuzzer.cpp | 8 +- test/unittest/BUILD.gn | 26 +- .../flashd_test/flash_host_unittest.cpp | 104 +++ .../flashd_test/flash_service_unittest.cpp | 411 ++++++++++++ .../unittest/mount_test/fstabapi_unittest.cpp | 83 +-- test/unittest/mount_test/mount_unittest.cpp | 26 +- .../unittest/package/pkg_manager_unittest.cpp | 7 +- .../unittest/package/pkg_package_unittest.cpp | 16 +- .../updater_main_unittest.cpp | 7 +- .../updater_test/updater_unittest.cpp | 7 + utils/BUILD.gn | 2 + utils/include/utils.h | 4 +- utils/updater_reboot.cpp | 6 +- utils/utils.cpp | 116 +--- 71 files changed, 3495 insertions(+), 1015 deletions(-) create mode 100755 services/etc/init.usb.cfg create mode 100755 services/etc/init.usb.configfs.cfg create mode 100755 services/flashd/BUILD.gn create mode 100755 services/flashd/blockdevice.cpp rename services/{include/fs_manager/fstab.h => flashd/blockdevice.h} (40%) mode change 100644 => 100755 create mode 100755 services/flashd/daemon/daemon_updater.cpp create mode 100755 services/flashd/daemon/daemon_updater.h rename services/{include/sparse_image/sparse_image_api.h => flashd/daemon/flashd_main.cpp} (30%) mode change 100644 => 100755 create mode 100755 services/flashd/flash_service.cpp create mode 100755 services/flashd/flash_service.h create mode 100755 services/flashd/flash_utils.h create mode 100755 services/flashd/host/host_updater.cpp create mode 100755 services/flashd/host/host_updater.h create mode 100755 services/flashd/partition.cpp create mode 100755 services/flashd/partition.h delete mode 100644 services/fs_manager/fstab.cpp create mode 100755 services/include/flashd/flashd.h delete mode 100644 services/include/fs_manager/fstab_api.h create mode 100755 services/updater_utils.cpp create mode 100755 test/unittest/flashd_test/flash_host_unittest.cpp create mode 100755 test/unittest/flashd_test/flash_service_unittest.cpp diff --git a/interfaces/kits/misc_info/BUILD.gn b/interfaces/kits/misc_info/BUILD.gn index 51b347ca..7bcc7112 100755 --- a/interfaces/kits/misc_info/BUILD.gn +++ b/interfaces/kits/misc_info/BUILD.gn @@ -21,6 +21,7 @@ ohos_static_library("libmiscinfo") { "//base/update/updater/services/include", "//base/update/updater/utils/include", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ diff --git a/ohos.build b/ohos.build index 9ef224ed..341a12ee 100644 --- a/ohos.build +++ b/ohos.build @@ -27,10 +27,12 @@ "//base/update/updateservice/interfaces/innerkits/engine:updateservicekits", "//base/update/updater/services/ui:libui", "//third_party/libdrm:libdrm", - "//third_party/e2fsprogs:e2fsprogs" + "//third_party/e2fsprogs:e2fsprogs", + "//base/update/updater/services/flashd:updater_flashd" ], "test_list": [ - "//base/update/updater:unittest" + "//base/update/updater:unittest", + "//base/update/updateservice:unittest" ] } } diff --git a/services/BUILD.gn b/services/BUILD.gn index 1b6c5c0c..945f511d 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -21,6 +21,18 @@ ohos_prebuilt_etc("updater_init.cfg") { 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/hisilicon/hi3516dv300/build/updater_config/signing_cert.crt" @@ -40,6 +52,8 @@ group("updater_etc") { ":fstab.updater", ":signing_cert.crt", ":updater_init.cfg", + ":updater_init_usb_configfs.cfg", + ":updater_usb_init.cfg", ] } @@ -49,12 +63,13 @@ ohos_executable("updater") { "main.cpp", "updater.cpp", "updater_main.cpp", + "updater_utils.cpp", ] include_dirs = [ "include", "$SUBSYSTEM_DIR/utils/include", - "$SUBSYSTEM_DIR/interfaces/kits/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", @@ -72,6 +87,7 @@ ohos_executable("updater") { "//base/update/updater/services", "//base/update/updater/services/ui", "//base/update/updater/services/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ @@ -79,6 +95,7 @@ ohos_executable("updater") { "//base/update/updater/interfaces/kits/packages:libpackageExt", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/flashd:libflashd", "//base/update/updater/services/fs_manager:libfsmanager", "//base/update/updater/services/log:libupdaterlog", "//base/update/updater/services/package:libupdaterpackage", diff --git a/services/applypatch/BUILD.gn b/services/applypatch/BUILD.gn index 8d8d8725..43765bfd 100644 --- a/services/applypatch/BUILD.gn +++ b/services/applypatch/BUILD.gn @@ -39,6 +39,7 @@ ohos_static_library("libapplypatch") { "//base/update/updater/services/include/package", "//base/update/updater/services/include/log", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ diff --git a/services/applypatch/transfer_manager.cpp b/services/applypatch/transfer_manager.cpp index 00d88b48..6ba2e13d 100644 --- a/services/applypatch/transfer_manager.cpp +++ b/services/applypatch/transfer_manager.cpp @@ -91,11 +91,7 @@ bool TransferManager::CommandsParser(int fd, const std::vector &con if (initBlock == 0) { initBlock = globalParams->written; } - bool typeResult = cmd->GetCommandType() == CommandType::NEW || - cmd->GetCommandType() == CommandType::IMGDIFF || - cmd->GetCommandType() == CommandType::BSDIFF || - cmd->GetCommandType() == CommandType::ZERO; - if (totalSize != 0 && globalParams->env != nullptr && typeResult) { + if (totalSize != 0 && globalParams->env != nullptr && NeedSetProgress(cmd->GetCommandType())) { globalParams->env->PostMessage("set_progress", std::to_string((float)(globalParams->written - initBlock) / totalSize)); } @@ -140,6 +136,14 @@ std::string TransferManager::ReloadForRetry() const return cmd; } +bool TransferManager::NeedSetProgress(const CommandType &type) +{ + return type == CommandType::NEW || + type == CommandType::IMGDIFF || + type == CommandType::BSDIFF || + type == CommandType::ZERO; +} + bool TransferManager::CheckResult(const CommandResult result, const std::string &cmd, const CommandType &type) { switch (result) { diff --git a/services/etc/init.cfg b/services/etc/init.cfg index 5615a7d6..cefe21d4 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -13,18 +13,42 @@ "cmds" : [ "mkdir /system", "mkdir /vendor", - "mkdir /odm", - "mkdir /hos", "mkdir /tmp", "mount tmpfs tmpfs /tmp", "chown 0 2000 /tmp", - "chmod 0755 /tmp" + "chmod 0755 /tmp", + "mkdir /dev/usb-ffs 0770 shell shell", + "mkdir /dev/usb-ffs/hdc 0770 shell shell", + "mkdir /dev/usb-ffs/hdc 0770 shell shell", + "mkdir /config 0770 shell shell", + "mount configfs none /config", + "mkdir /config/usb_gadget/g1 0770 shell shell", + "write /config/usb_gadget/g1/idVendor 0x12D1", + "write /config/usb_gadget/g1/idProduct 0x5000", + "write /config/usb_gadget/g1/os_desc/use 1", + "write /config/usb_gadget/g1/bcdDevice 0x0223", + "write /config/usb_gadget/g1/bcdUSB 0x0200", + "mkdir /config/usb_gadget/g1/strings/0x409 0770", + "copy /sys/block/mmcblk0/device/cid /config/usb_gadget/g1/strings/0x409/serialnumber", + "write /config/usb_gadget/g1/strings/0x409/manufacturer HISILICON", + "write /config/usb_gadget/g1/strings/0x409/product \"HDC Device\"", + "mkdir /config/usb_gadget/g1/functions/ffs.hdc", + "mkdir /config/usb_gadget/g1/configs/b.1 0770 shell shell", + "mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770 shell shell", + "write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1", + "write /config/usb_gadget/g1/os_desc/qw_sign MSFT100", + "write /config/usb_gadget/g1/configs/b.1/MaxPower 500", + "symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1", + "mount functionfs hdc /dev/usb-ffs/hdc uid=2000,gid=2000", + "setparam sys.usb.controller 100e0000.hidwc3_0", + "setparam sys.usb.config hdc", + "setparam sys.usb.configfs 1" ] }, { "name" : "post-init", "cmds" : [ - "start updater", - "start shell" + "start shell", + "start updater" ] } ], @@ -35,8 +59,7 @@ "gid" : 2000, "once" : 0, "importance" : 0, - "console" : 1, - "caps" : [4294967295] + "console" : 1 }, { "name" : "updater", "path" : ["/bin/updater"], diff --git a/services/etc/init.usb.cfg b/services/etc/init.usb.cfg new file mode 100755 index 00000000..1a307221 --- /dev/null +++ b/services/etc/init.usb.cfg @@ -0,0 +1,15 @@ +{ + "jobs" : [{ + "name" : "boot", + "cmds" : [ + "setparam sys.usb.configfs 0" + ] + }, { + "name" : "boot && param:persist.sys.usb.config=*", + "condition" : "boot && persist.sys.usb.config=*", + "cmds" : [ + "setparam sys.usb.config ${persist.sys.usb.config}" + ] + } + ] +} diff --git a/services/etc/init.usb.configfs.cfg b/services/etc/init.usb.configfs.cfg new file mode 100755 index 00000000..4474b098 --- /dev/null +++ b/services/etc/init.usb.configfs.cfg @@ -0,0 +1,25 @@ +{ + "jobs" : [{ + "name" : "param:sys.usb.config=none && param:sys.usb.configfs=1", + "condition" : "sys.usb.config=none && sys.usb.configfs=1", + "cmds" : [ + "write /config/usb_gadget/g1/UDC none", + "setparam sys.usb.ffs.ready 0", + "write /config/usb_gadget/g1/bDeviceClass 0", + "write /config/usb_gadget/g1/bDeviceSubClass 0", + "write /config/usb_gadget/g1/bDeviceProtocol 0", + "rm /config/usb_gadget/g1/configs/b.1/f1", + "setparam sys.usb.state ${sys.usb.config}" + ] + }, { + "name" : "param:sys.usb.ffs.ready=1 && param:sys.usb.config=hdc && param:sys.usb.configfs=1", + "condition" : "sys.usb.ffs.ready=1 && sys.usb.config=hdc && sys.usb.configfs=1", + "cmds" : [ + "write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration hdc", + "symlink /config/usb_gadget/g1/functions/ffs.hdc /config/usb_gadget/g1/configs/b.1/f1", + "write /config/usb_gadget/g1/UDC ${sys.usb.controller}", + "setparam sys.usb.state ${sys.usb.config}" + ] + } + ] +} diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn new file mode 100755 index 00000000..d484a64c --- /dev/null +++ b/services/flashd/BUILD.gn @@ -0,0 +1,80 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_static_library("libflashd") { + sources = [ + "//base/update/updater/services/flashd/blockdevice.cpp", + "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", + "//base/update/updater/services/flashd/daemon/flashd_main.cpp", + "//base/update/updater/services/flashd/flash_service.cpp", + "//base/update/updater/services/flashd/partition.cpp", + "//base/update/updater/services/updater_binary/update_image_block.cpp", + "//base/update/updater/services/updater_binary/update_partitions.cpp", + "//base/update/updater/services/updater_binary/update_processor.cpp", + ] + + defines = [ + "HDC_DEBUG", + "HDC_SUPPORT_FLASHD", + "HARMONY_PROJECT", + ] + + deps = [ + "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", + "//base/update/updater/services/applypatch:libapplypatch", + "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/fs_manager:libfsmanager", + "//base/update/updater/services/log:libupdaterlog", + "//base/update/updater/services/package:libupdaterpackage", + "//base/update/updater/services/script:libupdaterscript", + "//base/update/updater/utils:libutils", + "//developtools/hdc_standard:hdc_deamon_flashd", + "//third_party/bzip2:libbz2", + "//third_party/cJSON:cjson_static", + "//third_party/libuv:uv_static", + "//third_party/lz4:liblz4_static", + "//third_party/openssl:libcrypto_static", + "//third_party/openssl:ssl_source", + "//third_party/zlib:libz", + "//utils/native/base:utils", + ] + + include_dirs = [ + "//developtools/hdc_standard/src/daemon", + "//developtools/hdc_standard/src/common", + "//base/update/updater/services", + "//base/update/updater/services/flashd", + "//base/update/updater/services/flashd/daemon", + "//base/update/updater/interfaces/kits/include", + "//base/update/updater/services/include/package", + "//base/update/updater/services/include/script", + "//base/update/updater/services/include/log", + "//base/update/updater/services/include", + "//base/update/updater/utils/include", + "//third_party/bounds_checking_function/include", + "//third_party/cJSON", + "//third_party/openssl/include", + "//utils/native/base/include", + "//third_party/lz4/lib", + "//third_party/libuv", + "//base/startup/init_lite/interfaces/innerkits/include", + ] + + part_name = "updater" +} + +group("updater_flashd") { + deps = [ ":libflashd" ] +} diff --git a/services/flashd/blockdevice.cpp b/services/flashd/blockdevice.cpp new file mode 100755 index 00000000..02d2d239 --- /dev/null +++ b/services/flashd/blockdevice.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "blockdevice.h" +#include +#include +#include +#include +#include +#include +#include "flash_service.h" + +namespace flashd { +int BlockDevice::Load() +{ + struct stat devStat {}; + int ret = stat(devPath_.c_str(), &devStat); + FLASHING_CHECK(ret != -1, return -1, "Failed to state %s", devPath_.c_str()); + + const std::string devName = GetDeviceName(); + std::string size = ReadDeviceSysInfo("size"); + FLASHING_CHECK(!size.empty(), return 0, "Failed to read dev size"); + devSize_ = atol(size.c_str()); + sectorSize_ = SECTOR_SIZE_DEFAULT; + physSectorSize_ = SECTOR_SIZE_DEFAULT; + return 0; +} + +const std::string BlockDevice::GetDeviceName() +{ + std::string::size_type pos = devPath_.find_last_of('/') + 1; + return devPath_.substr(pos, devPath_.size() - pos); +} + +std::string BlockDevice::ReadDeviceSysInfo(const std::string &type) +{ + std::vector buffer(DEVICE_PATH_SIZE, 0); + int ret = snprintf_s(buffer.data(), DEVICE_PATH_SIZE, DEVICE_PATH_SIZE - 1, + "/sys/block/%s/%s", GetDeviceName().c_str(), type.c_str()); + FLASHING_CHECK(ret != -1, return "", "Failed to snprintf_s %s", devPath_.c_str()); + std::vector table; + return FlashService::ReadSysInfo(buffer.data(), type, table); +} +} // namespace flashd \ No newline at end of file diff --git a/services/include/fs_manager/fstab.h b/services/flashd/blockdevice.h old mode 100644 new mode 100755 similarity index 40% rename from services/include/fs_manager/fstab.h rename to services/flashd/blockdevice.h index 4cf3b750..3533a586 --- a/services/include/fs_manager/fstab.h +++ b/services/flashd/blockdevice.h @@ -1,42 +1,51 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef __UPDATER_FS_MANAGER_FSTAB_H -#define __UPDATER_FS_MANAGER_FSTAB_H -#include -#include -#include - -namespace updater { -/* Fs manager flags definition */ -#define FS_MANAGER_CHECK 0x00000001 -#define FS_MANAGER_WAIT 0x00000002 - -#define VALID_FS_MANAGER_FLAGS (FS_MANAGER_CHECK | FS_MANAGER_WAIT) -#define FS_MANAGER_FLAGS_ENABLED(item, flag) ((item.fsManagerFlags & FS_MANAGER_##flag) != 0) - -#define FM_MANAGER_CHECK_ENABLED(item, flag) FS_MANAGER_FLAGS_ENABLED(item, check) -#define FM_MANAGER_WAIT_ENABLED(item, flag) FS_MANAGER_FLAGS_ENABLED(item, wait) - -struct FstabItem { - std::string deviceName; // Block device name - std::string mountPoint; // Mount point - std::string fsType; // File system type - std::string mountOptions; // File system mount options. readonly, rw, remount etc. - unsigned int fsManagerFlags; // flags defined by fs manager. -}; - -using Fstab = std::vector; -} // updater -#endif // __UPDATER_FS_MANAGER_H +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLASHING_BLOCKDEVICE_H +#define FLASHING_BLOCKDEVICE_H +#include +#include +#include "flash_utils.h" + +namespace flashd { +enum class DeviceType { + DEVICE_UNKNOWN = 0, + DEVICE_SCSI = 1, + DEVICE_EMMC = 2, +}; + +class BlockDevice { +public: + BlockDevice(DeviceType type, const std::string &devPath) : devPath_(devPath), type_(type) {} + ~BlockDevice() {}; + + int Load(); + const std::string GetDeviceName(); + DeviceType GetDeviceType() + { + return type_; + } +private: + std::string ReadDeviceSysInfo(const std::string &type); + + std::string devPath_; + size_t devSize_ = 0; + size_t sectorSize_ = 0; // logical sector size + size_t physSectorSize_ = 0; // physical sector size + DeviceType type_ = DeviceType::DEVICE_UNKNOWN; +}; +using BlockDevicePtr = BlockDevice *; +} +#endif // FLASHING_BLOCKDEVICE_H \ No newline at end of file diff --git a/services/flashd/daemon/daemon_updater.cpp b/services/flashd/daemon/daemon_updater.cpp new file mode 100755 index 00000000..37dae05c --- /dev/null +++ b/services/flashd/daemon/daemon_updater.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_updater.h" +#include "daemon_common.h" +#include "flashd/flashd.h" +#include "flash_utils.h" + +namespace Hdc { +DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_UPDATER_BEGIN; + commandData = CMD_UPDATER_DATA; +} + +DaemonUpdater::~DaemonUpdater() +{ + WRITE_LOG(LOG_DEBUG, "~DaemonUpdater refCount %d", refCount); +} + +bool DaemonUpdater::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease()) { + return false; + } + return true; +} + +bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ +#ifndef UPDATER_UT + if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { + return false; + } +#endif + if (flashHandle_ == nullptr) { + int ret = flashd::CreateFlashInstance(&flashHandle_, errorMsg_, + [&](uint32_t type, size_t dataLen, const void *context) { + SendProgress(dataLen); + }); + if (ret != 0) { + return false; + } + } + switch (command) { + case CMD_UPDATER_DATA: { + string serialStrring((char *)payload, payloadPrefixReserve); + TransferPayload pld; + SerialStruct::ParseFromString(pld, serialStrring); + SendProgress(pld.uncompressSize); + break; + } + case CMD_UPDATER_CHECK: { + ProcessUpdateCheck(payload, payloadSize); + break; + } + case CMD_UPDATER_ERASE: { + std::string param(reinterpret_cast(payload), payloadSize); + RunUpdateShell(flashd::UPDATEMOD_ERASE, param, ""); + TaskFinish(); + break; + } + case CMD_UPDATER_FORMAT: { + std::string param(reinterpret_cast(payload), payloadSize); + RunUpdateShell(flashd::UPDATEMOD_FORMAT, param, ""); + TaskFinish(); + break; + } + default: + WRITE_LOG(LOG_FATAL, "CommandDispatch command %d", command); + return false; + } + return true; +}; + +void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payloadSize) +{ + uint64_t realSize = 0; + int ret = memcpy_s(&realSize, sizeof(realSize), payload, sizeof(realSize)); + if (ret != 0) { + return; + } + string bufString((char *)payload + sizeof(realSize), payloadSize - sizeof(realSize)); + SerialStruct::ParseFromString(ctxNow.transferConfig, bufString); + ctxNow.master = false; + ctxNow.fsOpenReq.data = &ctxNow; + ctxNow.transferBegin = Base::GetRuntimeMSec(); + ctxNow.fileSize = ctxNow.transferConfig.fileSize; + percentage_ = -1; + + WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck local function %s size %llu realSize %llu", + ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize); + uint8_t type = flashd::UPDATEMOD_FLASH; + if (ctxNow.transferConfig.functionName == CMDSTR_UPDATE_SYSTEM) { + type = flashd::UPDATEMOD_UPDATE; + totalSize_ = static_cast(ctxNow.fileSize); + if (!MatchPackageExtendName(ctxNow.transferConfig.optionalName, ".bin")) { + totalSize_ += static_cast(realSize); // for decode from zip + } + totalSize_ += static_cast(realSize); // for verify + totalSize_ += static_cast(realSize); // for read to partition + totalSize_ += static_cast(realSize); // for write partition + } else if (ctxNow.transferConfig.functionName == CMDSTR_FLASH_PARTITION) { + totalSize_ = static_cast(ctxNow.fileSize); + type = flashd::UPDATEMOD_FLASH; + } else { + WRITE_LOG(LOG_FATAL, "ProcessUpdateCheck local function %s size %lu realSize %lu", + ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize); + return; + } + ctxNow.localPath = ctxNow.transferConfig.optionalName; + ret = flashd::DoUpdaterPrepare(flashHandle_, type, ctxNow.transferConfig.options, ctxNow.localPath); + if (ret == 0) { + refCount++; + WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck localPath %s", ctxNow.localPath.c_str()); + uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), + UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen); + } else { + AsyncUpdateFinish(type, ret, errorMsg_); + } +} + +void DaemonUpdater::RunUpdateShell(uint8_t type, const std::string &options, const std::string &package) +{ + int ret = flashd::DoUpdaterFlash(flashHandle_, type, options, package); + if (ret != 0) { + WRITE_LOG(LOG_FATAL, errorMsg_.c_str()); + } + AsyncUpdateFinish(type, ret, errorMsg_); +} + +void DaemonUpdater::SendProgress(size_t dataLen) +{ + currSize_ += dataLen; + int32_t percentage = (int32_t)(currSize_ * (flashd::PERCENT_FINISH - 1) / totalSize_); + if (percentage >= flashd::PERCENT_FINISH) { + WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage %d", currSize_, percentage); + return; + } + if (percentage_ < percentage) { + percentage_ = percentage; + WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage_ %d", currSize_, percentage_); + FLASHING_LOGI("SendProgress %lf percentage_ %d", currSize_, percentage_); + SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); + } +} + +void DaemonUpdater::WhenTransferFinish(CtxFile *context) +{ + uint64_t nMSec = Base::GetRuntimeMSec() - context->transferBegin; + double fRate = static_cast(context->indexIO) / nMSec; // / /1000 * 1000 = 0 + WRITE_LOG(LOG_DEBUG, "File for %s transfer finish Size:%lld time:%lldms rate:%.2lfkB/s", + ctxNow.transferConfig.functionName.c_str(), context->indexIO, nMSec, fRate); + + int ret = 0; + uint8_t type = flashd::UPDATEMOD_UPDATE; + if (ctxNow.transferConfig.functionName == CMDSTR_UPDATE_SYSTEM) { + type = flashd::UPDATEMOD_UPDATE; + ret = flashd::DoUpdaterFlash(flashHandle_, type, ctxNow.transferConfig.options, ctxNow.localPath); + } else if (ctxNow.transferConfig.functionName == CMDSTR_FLASH_PARTITION) { + type = flashd::UPDATEMOD_FLASH; + } + AsyncUpdateFinish(type, ret, errorMsg_); + ret = flashd::DoUpdaterFinish(flashHandle_, type, ctxNow.localPath); + if (ret != 0) { + WRITE_LOG(LOG_FATAL, errorMsg_.c_str()); + } + TaskFinish(); +} + +void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t ret, const string &result) +{ + WRITE_LOG(LOG_DEBUG, "AsyncUpdateFinish ret %d result %s", ret, result.c_str()); + uint32_t percentage = (ret != 0) ? flashd::PERCENT_CLEAR : flashd::PERCENT_FINISH; + SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); + + string echo = result; + echo = Base::ReplaceAll(echo, "\n", " "); + vector vecBuf; + vecBuf.push_back(type); + if (ret != 0) { + vecBuf.push_back(MSG_FAIL); + } else { + vecBuf.push_back(MSG_OK); + } + vecBuf.insert(vecBuf.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size()); + SendToAnother(CMD_UPDATER_FINISH, vecBuf.data(), vecBuf.size()); +} + +#ifdef UPDATER_UT +void DaemonUpdater::DoTransferFinish() +{ + WhenTransferFinish(&ctxNow); +} +#endif +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/daemon_updater.h b/services/flashd/daemon/daemon_updater.h new file mode 100755 index 00000000..a7e35b67 --- /dev/null +++ b/services/flashd/daemon/daemon_updater.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_UPDATER_H +#define HDC_DAEMON_UPDATER_H +#include + +#include "securec.h" +#include "transfer.h" + +namespace Hdc { +class DaemonUpdater : public HdcTransferBase { +public: + explicit DaemonUpdater(HTaskInfo hTaskInfo); + virtual ~DaemonUpdater(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; + bool ReadyForRelease(); +#ifdef UPDATER_UT + void DoTransferFinish(); +#endif +private: + virtual void WhenTransferFinish(CtxFile *context) override; + void ProcessUpdateCheck(const uint8_t *payload, const int payloadSize); + void RunUpdateShell(uint8_t type, const std::string &options, const std::string &package); + void AsyncUpdateFinish(uint8_t type, int32_t ret, const string &result); + void SendProgress(size_t dataLen); +#ifdef UPDATER_UT + bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) + { + WRITE_LOG(LOG_DEBUG, "SendToAnother %d size %d", command, size); + return true; + } + void TaskFinish() + { + WRITE_LOG(LOG_DEBUG, "TaskFinish "); + return; + } +#endif +private: + double currSize_ = 0; + double totalSize_ = 0; + int32_t percentage_ = 0; + void* flashHandle_ = nullptr; + std::string errorMsg_ {}; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/include/sparse_image/sparse_image_api.h b/services/flashd/daemon/flashd_main.cpp old mode 100644 new mode 100755 similarity index 30% rename from services/include/sparse_image/sparse_image_api.h rename to services/flashd/daemon/flashd_main.cpp index 210541e4..5d73fd8f --- a/services/include/sparse_image/sparse_image_api.h +++ b/services/flashd/daemon/flashd_main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -12,15 +12,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "daemon_common.h" +#include "flashd/flashd.h" +#include "updater/updater.h" -#ifndef UPDATER_SPARSE_IMAGE_API_H -#define UPDATER_SPARSE_IMAGE_API_H -namespace updater { -// SparseImage structure is an internal structure of libsparseimage -// Just declare it here. -struct SparseImage; -struct SparseImage *CreateSparseImageFromBuffer(char *buff); -void DeallocateSparseImage(struct SparseImage *si); -int SparseImageRestore(int fd, struct SparseImage *si); -} // namespace updater -#endif // UPDATER_SPARSE_IMAGE_API_H +using namespace Hdc; +namespace flashd { +int flashd_main(int argc, char **argv) +{ + Base::SetLogLevel(LOG_LAST); // debug log print + std::vector args = updater::ParseParams(argc, argv); + bool enableUsb = false; + bool enableTcp = false; + for (std::string arg : args) { + if (arg.find("-l") != std::string::npos) { + int logLevel = atoi(arg.c_str() + strlen("-l")); + if (logLevel < 0 || logLevel > LOG_LAST) { + WRITE_LOG(LOG_DEBUG, "Loglevel error!\n"); + return -1; + } + Base::SetLogLevel(logLevel); + } else if (arg.find("-t") != std::string::npos) { + enableTcp = true; + } else if (arg.find("-u") != std::string::npos) { + enableUsb = true; + } + } + + if (!enableTcp && !enableUsb) { + Base::PrintMessage("Both TCP and USB are disable, default enable usb"); + enableUsb = true; + } + + WRITE_LOG(LOG_DEBUG, "flashd main run"); + HdcDaemon daemon(false); + daemon.InitMod(enableTcp, enableUsb); +#ifndef UPDATER_UT + daemon.WorkerPendding(); +#endif + return 0; +} +} diff --git a/services/flashd/flash_service.cpp b/services/flashd/flash_service.cpp new file mode 100755 index 00000000..1cd136b5 --- /dev/null +++ b/services/flashd/flash_service.cpp @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "flash_service.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blockdevice.h" +#include "fs_manager/mount.h" +#include "package/pkg_manager.h" +#include "securec.h" +#include "updater/updater.h" +#include "updater/updater_const.h" +#include "utils.h" + +using namespace hpackage; +using namespace updater; + +namespace flashd { +FlashService::~FlashService() +{ + for (auto part : partitions_) { + printf("LoadBlockDevice %s \n", part->GetPartitionName().c_str()); + delete part; + } + partitions_.clear(); + for (auto dev : blockDevices_) { + delete dev; + } + blockDevices_.clear(); +} + +int FlashService::LoadSysDevice() +{ + if (loadSysDevice_) { + return 0; + } + return LoadBlockDevice("/dev/block"); +} + +int FlashService::DoUpdate(const std::string &packageName) +{ + int ret = 0; + FLASHING_LOGI("DoUpdate packageName %s", packageName.c_str()); + FLASHING_CHECK(access(packageName.c_str(), 0) == 0, + return FLASHING_IMAGE_INVALID, "Invalid package %s for update", packageName.c_str()); + ret = updater::IsSpaceCapacitySufficient(packageName); + if (ret == UPDATE_SPACE_NOTENOUGH) { + RecordMsg(updater::ERROR, "Free space is not enough"); + return FLASHING_SPACE_NOTENOUGH; + } + FLASHING_LOGI("Check space for packageName %s success", packageName.c_str()); + + uint64_t pkgLen = 0; + PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); + FLASHING_CHECK(pkgManager != nullptr, return FLASHING_PACKAGE_INVALID, "Failed to GetPackageInstance"); + pkgManager->SetPkgDecodeProgress([&](int type, size_t writeDataLen, const void *context) { + pkgLen += writeDataLen; + PostProgress(UPDATEMOD_UPDATE, writeDataLen, context); + }); + std::vector components; + ret = pkgManager->LoadPackage(packageName, utils::GetCertName(), components); + FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); + RecordMsg(updater::ERROR, "Can not load package %s", packageName.c_str()); + return FLASHING_PACKAGE_INVALID, "Failed to load package %s", packageName.c_str()); +#ifndef LOCAL_SUPPORT + ret = updater::ExecUpdate(pkgManager, 0, + [&](const char *cmd, const char *content) { + if (strncmp(cmd, "data", strlen(cmd)) == 0) { + size_t dataLen = std::stoll(content); + PostProgress(UPDATEMOD_UPDATE, dataLen, nullptr); + } + }); +#endif + FLASHING_LOGI("Load packageName %s success %llu", packageName.c_str(), pkgLen); + PkgManager::ReleasePackageInstance(pkgManager); + return ret; +} + +int FlashService::DoFlashPartition(const std::string &fileName, const std::string &partition) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_FLASH, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to flash partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to flash partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + FLASHING_LOGI("DoFlashPartition partition %s image:%s", partition.c_str(), fileName.c_str()); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + return part->DoFlash(fileName); +} + +int FlashService::GetPartitionPath(const std::string &partition, std::string ¶titionPath) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_FLASH, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to flash partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to flash partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + FLASHING_LOGI("DoFlashPartition partition %s", partition.c_str()); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + paratitionPath = part->GetPartitionPath(); + return 0; +} + +int FlashService::DoErasePartition(const std::string &partition) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_ERASE, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to erase partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to erase partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + FLASHING_LOGI("DoErasePartition partition %s ", partition.c_str()); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + return part->DoErase(); +} + +int FlashService::DoFormatPartition(const std::string &partition, const std::string &fsType) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_FORMAT, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to format partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to format partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + if (part->IsOnlyErase()) { + FLASHING_LOGI("DoFormatPartition format partition %s", partition.c_str()); + return part->DoErase(); + } + FLASHING_LOGI("DoFormatPartition partition %s fsType:%s", partition.c_str(), fsType.c_str()); + return part->DoFormat(fsType); +} + +int FlashService::DoResizeParatiton(const std::string &partition, uint32_t blocks) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_UPDATE, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to resize partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to resize partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + return part->DoResize(blocks); +} + +PartitionPtr FlashService::GetPartition(const std::string &partition) const +{ + const std::string partName = GetPartNameByAlias(partition); + for (auto part : partitions_) { + if (partName.compare(part->GetPartitionName()) == 0) { + return part; + } + } + return nullptr; +} + +int FlashService::LoadBlockDevice(const std::string &fileDir) +{ + std::vector partitionsName {}; + struct stat dirStat = {}; + int ret = stat(fileDir.c_str(), &dirStat); + FLASHING_CHECK(ret != -1 && S_ISDIR(dirStat.st_mode), return -1, "Invlid dir %s", fileDir.c_str()); + + std::vector buffer(DEVICE_PATH_SIZE, 0); + struct dirent *entry = nullptr; + DIR *dir = opendir(fileDir.c_str()); + while ((entry = readdir(dir)) != nullptr) { + if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { + continue; + } + std::string devPath = fileDir + "/" + entry->d_name; + if (entry->d_type == 10) { // 10 link 文件 + readlink(devPath.c_str(), buffer.data(), DEVICE_PATH_SIZE); + devPath = fileDir + "/" + buffer.data(); + memset_s(buffer.data(), DEVICE_PATH_SIZE, 0, DEVICE_PATH_SIZE); + } + ret = stat(devPath.c_str(), &dirStat); + FLASHING_CHECK(ret != -1, break, "Invlid dir %s %s", devPath.c_str(), strerror(errno)); + uint32_t devMajor = major(dirStat.st_rdev); + uint32_t devMinor = minor(dirStat.st_rdev); + if (devMajor == LOOP_MAJOR) { + continue; + } + ret = 0; + if (SCSI_BLK_MAJOR(devMajor)) { + if ((devMinor % 0x10) == 0) { + ret = AddNewBlockDevice(DeviceType::DEVICE_SCSI, devPath); + } else { + partitionsName.push_back(devPath); + } + } else if (devMajor == SDMMC_MAJOR) { + if (devMinor % 0x08 == 0) { + ret = AddNewBlockDevice(DeviceType::DEVICE_EMMC, devPath); + } else { + partitionsName.push_back(devPath); + } + } + FLASHING_CHECK(ret == 0, break, "Failed to add device %s", devPath.c_str()); + } + closedir(dir); + FLASHING_CHECK(ret == 0, return -1, "Failed to add device %s", fileDir.c_str()); + ret = LoadPartition(partitionsName); + loadSysDevice_ = true; + return ret; +} + +int FlashService::LoadPartition(std::vector &partitionsNames) +{ + std::sort(std::begin(partitionsNames), std::end(partitionsNames), std::less()); + for (auto device : blockDevices_) { + for (std::string path : partitionsNames) { + std::string name = GetBaseName(path); + if (strncmp(name.c_str(), device->GetDeviceName().c_str(), device->GetDeviceName().size()) != 0) { + continue; + } + AddNewPartition(path, device); + } + } + return 0; +} + +int FlashService::AddNewPartition(const std::string &path, BlockDevicePtr device) +{ + std::string name = GetBaseName(path); + PartitionPtr part = new Partition(name, GetRealPath(path), device, this); + FLASHING_CHECK(part != nullptr, return -1, "Failed to create partition %s", path.c_str()); + int ret = part->Load(); + FLASHING_CHECK(ret == 0, delete part; + return -1, "Failed to create partition %s", path.c_str()); + partitions_.push_back(part); + return 0; +} + +int FlashService::AddNewBlockDevice(DeviceType type, const std::string &devPath) +{ + BlockDevicePtr device = new BlockDevice(type, GetRealPath(devPath)); + FLASHING_CHECK(device != nullptr, return -1, "Failed to create device %s", devPath.c_str()); + int ret = device->Load(); + FLASHING_CHECK(ret == 0, delete device; + return 0, "Failed to create device %s", devPath.c_str()); + blockDevices_.push_back(device); + return 0; +} + +std::string FlashService::ReadSysInfo(const std::string &path, const std::string &type, std::vector &table) +{ + std::string returnStr; + auto file = std::unique_ptr(fopen(path.c_str(), "r"), fclose); + FLASHING_CHECK(file != nullptr, return "", "Failed to open %s", path.c_str()); + std::vector buffer(LINE_BUFFER_SIZE, 0); + while (fgets(buffer.data(), LINE_BUFFER_SIZE, file.get()) != nullptr) { + if (type == "uevent") { + table.push_back(buffer.data()); + } else if (type == "start") { + returnStr = std::string(buffer.data()); + break; + } else if (type == "size") { + returnStr = std::string(buffer.data()); + break; + } else if (type == "partition") { + returnStr = std::string(buffer.data()); + break; + } + memset_s(buffer.data(), LINE_BUFFER_SIZE, 0, LINE_BUFFER_SIZE); + } + return returnStr; +} + +std::string FlashService::GetParamFromTable(const std::vector &table, const std::string ¶m) +{ + for (std::string line : table) { + std::string::size_type pos = line.find(param); + if (pos != std::string::npos) { + return line.substr(param.size(), line.size() - 1 - param.size()); + } + } + return ""; +} + +int FlashService::ExecCommand(const std::vector &cmds) +{ + std::vector extractedCmds; + for (const auto &cmd : cmds) { + extractedCmds.push_back(const_cast(cmd.c_str())); + } + extractedCmds.push_back(nullptr); + pid_t pid = fork(); + if (pid < 0) { + FLASHING_CHECK(0, return -1, "Failed to fork %d error:%d", pid, errno); + return errno; + } + if (pid == 0) { + execv(extractedCmds[0], extractedCmds.data()); + exit(0x7f); // 0x7f exit code + } + int status; + waitpid(pid, &status, 0); + if (WEXITSTATUS(status) != 0 || !WIFEXITED(status)) { + return WEXITSTATUS(status); + } + return 0; +} + +void FlashService::RecordMsg(uint8_t level, const char *msg, ...) +{ + errorLevel_ = level; + va_list vaArgs; + va_start(vaArgs, msg); + std::vector zc(MAX_SIZE_BUF); + const int retSize = vsnprintf_s(zc.data(), MAX_SIZE_BUF, zc.size() - 1, msg, vaArgs); + if (retSize >= 0) { + errorMsg_ = std::string(zc.data(), retSize); + } + va_end(vaArgs); +} + +void FlashService::PostProgress(uint32_t type, size_t dataLen, const void *context) const +{ + if (progressor_ != nullptr) { + progressor_(type, dataLen, context); + } +} + +int FlashService::CheckOperationPermission(int type, const std::string &partition) const +{ + if (type >= UPDATEMOD_MAX) { + return 1; + } + std::vector forbitPartName[] = { + {}, // updater + {"updater"}, // flash + {"updater", "boot", "kernel"}, // erase + {"updater", "boot", "kernel"} // format + }; + if (forbitPartName[type].size() == 0) { + return 0; + } + const std::string partName = GetPartNameByAlias(partition); + auto it = std::find (forbitPartName[type].begin(), forbitPartName[type].end(), partName); + return it != forbitPartName[type].end(); +} + +const std::string FlashService::GetBaseName(const std::string &path) +{ + std::string::size_type pos = path.find_last_of('/') + 1; + return path.substr(pos, path.size() - pos); +} + +const std::string FlashService::GetPathRoot(const std::string &path) +{ + std::string::size_type pos = path.find_first_of('/', 1); + return path.substr(0, pos); +} + +const std::string FlashService::GetPartNameByAlias(const std::string &alias) +{ + std::map> partNameMap = { + { "userdata", { "data", "/data", "userdata" } }, + { "system", { "system", "/system" } }, + { "vendor", { "vendor", "/vendor" } }, + { "misc", { "misc", "/misc" } }, + { "updater", { "updater", "/updater" } }, + { "kernel", { "boot" } }, // image + { "boot", { "fastboot" } }, // fastboot + }; + for (auto iter = partNameMap.begin(); iter != partNameMap.end(); iter++) { + for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); iter2++) { + if (*iter2 == alias) { + return iter->first; + } + } + } + return alias; +} + +const std::string FlashService::GetRealPath(const std::string &path) +{ + std::vector realPath(DEVICE_PATH_SIZE, 0); + return realpath(path.c_str(), realPath.data()); +} + +bool FlashService::CheckFreeSpace(const std::string &root, uint32_t blocks) +{ + struct statvfs64 vfs {}; + int ret = statvfs64(root.c_str(), &vfs); + FLASHING_CHECK(ret >= 0, return false, "Failed to statvfs %s", root.c_str()); + if (static_cast(vfs.f_bsize) == DEFAULT_BLOCK_SIZE) { + return static_cast(vfs.f_bfree) < static_cast(blocks); + } + return static_cast(vfs.f_bfree) < (blocks / static_cast(vfs.f_bsize)) * DEFAULT_BLOCK_SIZE; +} + +static std::string GetValueFromParam(const std::vector ¶ms, + const std::string ¶mType, const std::string &defValue) +{ + std::string ret = defValue; + for (size_t i = 0; i < params.size(); i++) { + if (paramType.compare(params[i]) == 0) { + if (i < (params.size() - 1)) { + ret = params[i + 1]; + } else { + ret = "true"; + } + } + } + return ret; +} + +static bool FilterParam(const std::string ¶m, const std::vector &filter) +{ + auto iter = filter.begin(); + while (iter != filter.end()) { + if (param.compare(*iter) == 0) { + return true; + } + iter++; + } + return false; +} + +static int GetCmdParam(uint8_t type, const std::string &origString, + const std::vector &filter, std::vector &resultStrings) +{ + static uint32_t paramMinNumber[flashd::UPDATEMOD_MAX + 1] = { 1, 2, 2, 2, 0 }; + std::string::size_type p1 = 0; + std::string::size_type p2 = origString.find(" "); + + while (p2 != std::string::npos) { + if (p2 == p1) { + ++p1; + p2 = origString.find(" ", p1); + continue; + } + + std::string param = origString.substr(p1, p2 - p1); + if (!FilterParam(param, filter)) { + resultStrings.push_back(param); + } + p1 = p2 + 1; + p2 = origString.find(" ", p1); + } + + if (p1 != origString.size()) { + std::string param = origString.substr(p1); + if (!FilterParam(param, filter)) { + resultStrings.push_back(param); + } + } + FLASHING_CHECK((resultStrings.size() >= paramMinNumber[type]) && (type <= flashd::UPDATEMOD_MAX), + return FLASHING_ARG_INVALID, "Invalid param for %d cmd %s", type, origString.c_str()); + return 0; +} + +int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunction progressor) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle"); + flashd::FlashService *flash = new flashd::FlashService(errorMsg, progressor); + if (flash == nullptr) { + FLASHING_LOGE("Failed to create flash service"); + errorMsg = "Create instance fail"; + return FLASHING_SYSTEM_ERROR; + } + *handle = static_cast(flash); + return 0; +} + +int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdParam, std::string &filePath) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); + flashd::FlashService *flash = static_cast(handle); + + std::vector params {}; + int ret = GetCmdParam(type, cmdParam, { "-f" }, params); + FLASHING_CHECK(ret == 0, flash->RecordMsg(updater::ERROR, "Invalid param for %d", type); + return FLASHING_ARG_INVALID, "Invalid param for %d", type); + FLASHING_DEBUG("DoUpdaterPrepare type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str()); + switch (type) { + case flashd::UPDATEMOD_UPDATE: { + filePath = FLASHD_FILE_PATH + filePath; + // 检查剩余分区大小,扩展分区 + const std::string root = flashd::FlashService::GetPathRoot(FLASHD_FILE_PATH); + ret = MountForPath(root); + FLASHING_CHECK(ret == 0, + flash->RecordMsg(updater::ERROR, "Failed to mount data paratition for %s", filePath.c_str()); + return FLASHING_INVALID_SPACE, "Failed to mount data paratition for %s", filePath.c_str()); + + ret = flash->DoResizeParatiton(root, MIN_BLOCKS_FOR_UPDATE); + FLASHING_CHECK(ret == 0, return ret, "Failed to resize partition"); + if (access(FLASHD_FILE_PATH.c_str(), F_OK) == -1) { + mkdir(FLASHD_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + } + break; + } + case flashd::UPDATEMOD_FLASH: { + ret = flash->GetPartitionPath(params[0], filePath); + break; + } + default: + ret = flashd::FLASHING_SYSTEM_ERROR; + break; + } + return ret; +} + +int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam, const std::string &filePath) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); + flashd::FlashService *flash = static_cast(handle); + + std::vector params {}; + int ret = GetCmdParam(type, cmdParam, {"-f"}, params); + FLASHING_CHECK(ret == 0, + flash->RecordMsg(updater::ERROR, "Invalid param for %d", type); + return FLASHING_ARG_INVALID, "Invalid param for %d", type); + FLASHING_DEBUG("DoUpdaterFlash type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str()); + switch (type) { + case flashd::UPDATEMOD_UPDATE: { + ret = flash->DoUpdate(filePath); + unlink(filePath.c_str()); + break; + } + case flashd::UPDATEMOD_ERASE: + FLASHING_CHECK(params.size() > 1, return FLASHING_ARG_INVALID, "Invalid param size for erase"); + ret = flash->DoErasePartition(params[1]); + break; + case flashd::UPDATEMOD_FORMAT: { + std::string fsType = GetValueFromParam(params, "-t", "ext4"); + FLASHING_CHECK(params.size() > 1, return FLASHING_ARG_INVALID, "Invalid param size for format"); + ret = flash->DoFormatPartition(params[1], fsType); + break; + } + default: + ret = flashd::FLASHING_SYSTEM_ERROR; + break; + } + return ret; +} + +int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partition) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); + FLASHING_DEBUG("DoUpdaterFinish type: %d %s", type, partition.c_str()); + updater::PostUpdater(); + switch (type) { + case flashd::UPDATEMOD_UPDATE: { + utils::DoReboot(""); + break; + } + default: + break; + } + return 0; +} +} // namespace flashd diff --git a/services/flashd/flash_service.h b/services/flashd/flash_service.h new file mode 100755 index 00000000..e9420784 --- /dev/null +++ b/services/flashd/flash_service.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLASHING_H +#define FLASHING_H +#include +#include +#include +#include +#include "blockdevice.h" +#include "partition.h" +#include "updater/updater.h" + +// Just update-mode use +namespace flashd { +class FlashService { +public: + FlashService(std::string &errorMsg, ProgressFunction progressor) + : errorMsg_(errorMsg), progressor_(progressor) {} + explicit FlashService(std::string &errorMsg) : errorMsg_(errorMsg), progressor_(nullptr) {} + ~FlashService(); + + int DoUpdate(const std::string &packageName); + int DoFlashPartition(const std::string &fileName, const std::string &partition); + int DoErasePartition(const std::string &partition); + int DoFormatPartition(const std::string &partition, const std::string &fsType); + int GetPartitionPath(const std::string &partition, std::string ¶titionPath); + int DoResizeParatiton(const std::string &partition, uint32_t blocks); + + int LoadSysDevice(); + PartitionPtr GetPartition(const std::string &partition) const; + + void PostProgress(uint32_t type, size_t dataLen, const void *context) const; + void RecordMsg(uint8_t level, const char *msg, ...); + uint8_t GetErrorLevel() const + { + return errorLevel_; + } + + static std::string ReadSysInfo(const std::string &path, const std::string &type, std::vector &table); + static std::string GetParamFromTable(const std::vector &table, const std::string ¶m); + static int ExecCommand(const std::vector &cmds); + + static const std::string GetBaseName(const std::string &path); + static const std::string GetPathRoot(const std::string &path); + static const std::string GetRealPath(const std::string &path); + static const std::string GetPartNameByAlias(const std::string &alias); + static bool CheckFreeSpace(const std::string &root, uint32_t blocks); +private: + int LoadBlockDevice(const std::string &fileDir); + int LoadPartition(std::vector &partitionsNames); + + int AddNewBlockDevice(DeviceType type, const std::string &devPath); + int AddNewPartition(const std::string &path, BlockDevicePtr device); + + int CheckOperationPermission(int type, const std::string &partition) const; + std::string &errorMsg_; + ProgressFunction progressor_; + uint8_t errorLevel_ = 0; + bool loadSysDevice_ = false; + std::vector blockDevices_; + std::vector partitions_; +}; +} +#endif // FLASHING_H \ No newline at end of file diff --git a/services/flashd/flash_utils.h b/services/flashd/flash_utils.h new file mode 100755 index 00000000..0f6a415d --- /dev/null +++ b/services/flashd/flash_utils.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLASHING_UTILS_H +#define FLASHING_UTILS_H +#include + +#include "flashd/flashd.h" +#include "log/log.h" +#include "securec.h" + +namespace flashd { +#define FLASHING_LOGE(format, ...) Logger(updater::ERROR, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) +#define FLASHING_DEBUG(format, ...) Logger(updater::DEBUG, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) +#define FLASHING_LOGI(format, ...) Logger(updater::INFO, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) +#define FLASHING_LOGW(format, ...) Logger(updater::WARNING, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) + +#define FLASHING_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + FLASHING_LOGE(__VA_ARGS__); \ + exper; \ + } + +static constexpr size_t BUFFER_SIZE = 64 * 1024; +static constexpr uint32_t LOOP_MAJOR = 7; +static constexpr uint32_t SCSI_CDROM_MAJOR = 11; +static constexpr uint32_t SCSI_DISK0_MAJOR = 8; +static constexpr uint32_t SDMMC_MAJOR = 179; +static constexpr uint32_t DEVICE_PATH_SIZE = 256; +static constexpr uint32_t LINE_BUFFER_SIZE = 256; +static constexpr size_t SECTOR_SIZE_DEFAULT = 512; +#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR) + +class FlashService; +using FlashingPtr = FlashService *; +} // namespace flashd +#endif // FLASHING_UTILS_H diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp new file mode 100755 index 00000000..4de625d3 --- /dev/null +++ b/services/flashd/host/host_updater.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "host_updater.h" +#include "common.h" +#include "transfer.h" +#include "serial_struct.h" + +namespace Hdc { +static const int PERCENT_FINISH = 100; +static const uint32_t PERCENT_CLEAR = ((uint32_t)-1); +HostUpdater::HostUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_UPDATER_BEGIN; + commandData = CMD_UPDATER_DATA; +} + +HostUpdater::~HostUpdater() {} + +void HostUpdater::RunQueue(CtxFile &context) +{ + refCount++; + context.localPath = context.taskQueue.back(); + uv_fs_open(loopTask, &context.fsOpenReq, context.localPath.c_str(), O_RDONLY, 0, OnFileOpen); + context.master = true; +} + +bool HostUpdater::BeginTransfer(CtxFile &context, + const std::string &function, const char *payload, int minParam, int fileIndex) +{ + int argc = 0; + char **argv = Base::SplitCommandToArgs(payload, &argc); + if (argv == nullptr || argc < minParam || fileIndex >= argc) { + LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); + delete[]((char *)argv); + return false; + } + int maxParam = minParam; + if (strstr(payload, "-f") != nullptr) { + maxParam += 1; + } + if (argc != maxParam) { + LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); + delete[]((char *)argv); + return false; + } + + context.transferConfig.functionName = function; + context.transferConfig.options = payload; + if (strcmp(argv[fileIndex], "-f") == 0) { + context.localPath = argv[fileIndex + 1]; + } else { + context.localPath = argv[fileIndex]; + } + + if (MatchPackageExtendName(context.localPath, ".img")) { + context.transferConfig.compressType = COMPRESS_NONE; + } else if (function == CMDSTR_FLASH_PARTITION) { + context.transferConfig.compressType = COMPRESS_NONE; + } else if (MatchPackageExtendName(context.localPath, ".bin")) { + context.transferConfig.compressType = COMPRESS_NONE; + } else if (!(MatchPackageExtendName(context.localPath, ".zip") || + MatchPackageExtendName(context.localPath, ".lz4") || + MatchPackageExtendName(context.localPath, ".gz2"))) { + LogMsg(MSG_FAIL, "Invaid file \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); + delete[]((char *)argv); + return false; + } + + WRITE_LOG(LOG_DEBUG, "BeginTransfer function: %s localPath: %s command: %s ", + context.transferConfig.functionName.c_str(), context.localPath.c_str(), payload); + // check path + bool ret = Base::CheckDirectoryOrPath(context.localPath.c_str(), true, true); + if (!ret) { + LogMsg(MSG_FAIL, "Invaid file \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); + delete[]((char *)argv); + return false; + } + context.taskQueue.push_back(context.localPath); + RunQueue(context); + return true; +} + +std::string HostUpdater::GetFileName(const std::string &fileName) const +{ + int32_t pos = fileName.find_last_of('/'); + if (pos < 0) { + pos = fileName.find_last_of('\\'); + } + return fileName.substr(pos + 1, fileName.size()); +} + +void HostUpdater::CheckMaster(CtxFile *context) +{ + uv_fs_t fs; + Base::ZeroStruct(fs.statbuf); + uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr); + context->transferConfig.fileSize = fs.statbuf.st_size; + uv_fs_req_cleanup(&fs); + + WRITE_LOG(LOG_DEBUG, "CheckMaster %s %llu", context->transferConfig.functionName.c_str(), fs.statbuf.st_size); + context->transferConfig.optionalName = GetFileName(context->localPath); + std::string bufString = SerialStruct::SerializeToString(context->transferConfig); + + const uint64_t verdorSize = static_cast(1024 * 1024) * 256; + const uint64_t systemSize = static_cast(1024 * 1024) * 1500; + const uint64_t minSize = static_cast(1024 * 1024) * 10; + uint64_t realSize = verdorSize; + if (fs.statbuf.st_size > minSize) { + realSize += systemSize; + } + std::vector buffer(sizeof(realSize) + bufString.size()); + int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); + int ret2 = memcpy_s(buffer.data() + sizeof(realSize), buffer.size(), bufString.c_str(), bufString.size()); + if ((ret == 0) && (ret2 == 0)) { + SendToAnother(CMD_UPDATER_CHECK, (uint8_t *)buffer.data(), buffer.size()); + } +} + +bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int param) +{ + int argc = 0; + char **argv = Base::SplitCommandToArgs(payload, &argc); + if (argv == nullptr) { + LogMsg(MSG_FAIL, "Can not parser cmd \"%s\"", function.c_str()); + return false; + } + delete[]((char *)argv); + if (argc < param) { + LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); + return false; + } + + int maxParam = param; + if (strstr(payload, "-f") != nullptr) { + maxParam += 1; + } + if (strstr(payload, "-t") != nullptr) { + maxParam += 1; + maxParam += 1; + } + if (argc != maxParam) { + LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); + return false; + } + return true; +} + +bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + const int cmdFroErase = 2; + const int cmdFroFormat = 2; + if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { + return false; + } + bool ret = true; + switch (command) { + case CMD_UPDATER_BEGIN: { + std::string s(" Processing: 0%%"); + bSendProgress = true; + SendRawData(reinterpret_cast(s.data()), s.size()); + break; + } + case CMD_UPDATER_UPDATE_INIT: + ret = BeginTransfer(ctxNow, CMDSTR_UPDATE_SYSTEM, reinterpret_cast(payload), 1, 0); + break; + case CMD_UPDATER_FLASH_INIT: + ret = BeginTransfer(ctxNow, CMDSTR_FLASH_PARTITION, + reinterpret_cast(payload), 2, 1); // 2 cmd min param for flash + break; + case CMD_UPDATER_FINISH: + ret = CheckUpdateContinue(command, payload, payloadSize); + break; + case CMD_UPDATER_ERASE: { + if (!CheckCmd(CMDSTR_ERASE_PARTITION, reinterpret_cast(payload), cmdFroErase)) { + return false; + } + SendToAnother(CMD_UPDATER_ERASE, payload, payloadSize); + ctxNow.taskQueue.push_back(reinterpret_cast(payload)); + break; + } + case CMD_UPDATER_FORMAT: { + if (!CheckCmd(CMDSTR_FORMAT_PARTITION, reinterpret_cast(payload), cmdFroFormat)) { + return false; + } + SendToAnother(CMD_UPDATER_FORMAT, payload, payloadSize); + ctxNow.taskQueue.push_back(reinterpret_cast(payload)); + break; + } + case CMD_UPDATER_PROGRESS: + if (payloadSize >= (int)sizeof(uint32_t)) { + ProcessProgress(*(uint32_t *)payload); + } + break; + default: + break; + } + return ret; +} + +void HostUpdater::ProcessProgress(uint32_t percentage) +{ + if (!bSendProgress) { + return; + } + std::string backStr = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; + std::string breakStr = "\n"; + WRITE_LOG(LOG_INFO, "ProcessProgress %d", percentage); + const int bufferSize = 128; + std::vector buffer(bufferSize); + if (percentage == PERCENT_CLEAR) { // clear + SendRawData(reinterpret_cast(backStr.data()), backStr.size()); + SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); + bSendProgress = false; + return; + } + int len = sprintf_s(buffer.data(), buffer.size() - 1, "%s Processing: %3d%%", backStr.c_str(), percentage); + if (len <= 0) { + return; + } + SendRawData(reinterpret_cast(buffer.data()), len); + if (percentage == PERCENT_FINISH) { + SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); + bSendProgress = false; + } +} + +bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize) +{ + if (static_cast(payloadSize) < sizeof(uint16_t)) { + return false; + } + MessageLevel level = (MessageLevel)payload[1]; + if ((level == MSG_OK) && bSendProgress) { + ProcessProgress(PERCENT_FINISH); + } + std::string info((char*)(payload + sizeof(uint16_t)), payloadSize - sizeof(uint16_t)); + if (!info.empty()) { + LogMsg(level, "%s", info.c_str()); + } + WRITE_LOG(LOG_DEBUG, "CheckUpdateContinue %d %s", level, info.c_str()); + ctxNow.taskQueue.pop_back(); + if (singalStop || !ctxNow.taskQueue.size()) { + return false; + } + RunQueue(ctxNow); + return true; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_updater.h b/services/flashd/host/host_updater.h new file mode 100755 index 00000000..08e5ec78 --- /dev/null +++ b/services/flashd/host/host_updater.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_UPDATER_H +#define HDC_HOST_UPDATER_H +#include "common.h" +#include "transfer.h" + +namespace Hdc { +class HostUpdater : public HdcTransferBase { +public: + explicit HostUpdater(HTaskInfo hTaskInfo); + virtual ~HostUpdater(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; + +private: + void CheckMaster(CtxFile *context) override; + + bool BeginTransfer(CtxFile &context, + const std::string &function, const char *payload, int minParam, int fileIndex); + bool CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize); + void RunQueue(CtxFile &context); + std::string GetFileName(const std::string &fileName) const; + void ProcessProgress(uint32_t percentage); +#ifdef UPDATER_UT + void LogMsg(MessageLevel level, const char *msg, ...) + { + va_list vaArgs; + va_start(vaArgs, msg); + string log = Base::StringFormat(msg, vaArgs); + va_end(vaArgs); + WRITE_LOG(LOG_DEBUG, "LogMsg %d %s", level, log.c_str()); + return; + } + void SendRawData(uint8_t *bufPtr, const int size) + { + WRITE_LOG(LOG_DEBUG, "SendRawData %d", size); + } + bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) + { + WRITE_LOG(LOG_DEBUG, "SendToAnother command %d size %d", command, size); + return true; + } +#endif +private: + bool CheckCmd(const std::string &function, const char *payload, int param); + + bool bSendProgress = false; +}; +} +#endif \ No newline at end of file diff --git a/services/flashd/partition.cpp b/services/flashd/partition.cpp new file mode 100755 index 00000000..75d0f1d8 --- /dev/null +++ b/services/flashd/partition.cpp @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "partition.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "flash_service.h" +#include "utils.h" + +namespace flashd { +Partition::~Partition() +{ + if (fd_ != -1) { + close(fd_); + } +} + +int Partition::Load() +{ + std::vector table; + std::string info = ReadPartitionSysInfo(devName_, "partition", table); + FLASHING_CHECK(!info.empty(), return -1, "Can not get partition for %s", devName_.c_str()); + partNumber_ = atoi(info.c_str()); + + ReadPartitionSysInfo(devName_, "uevent", table); + info = FlashService::GetParamFromTable(table, "DEVNAME="); + FLASHING_CHECK(info == devName_, return -1, "Failed to check dev name %s %s", info.c_str(), devName_.c_str()); + + partName_ = FlashService::GetParamFromTable(table, "PARTNAME="); + if (partName_.empty()) { + partName_ = devName_; + } + int ret = Partition::GetMountInfo(); + FLASHING_LOGI("Partition info devName \"%s\" partPath_ \"%s\" partName_ \"%s\"", + devName_.c_str(), partPath_.c_str(), partName_.c_str()); + if (!mountPoint_.empty()) { + FLASHING_LOGI("Partition mount info mount \"%s\" fs %s flags: %s", + mountPoint_.c_str(), fsType_.c_str(), mountFlags_.c_str()); + } + return ret; +} + +int Partition::DoFlash(const std::string &fileName) +{ + int ret = Open(); + FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for flash", partName_.c_str()); + + auto inputFd = open(fileName.c_str(), O_RDONLY); + FLASHING_CHECK(inputFd > 0, + flash_->RecordMsg(updater::ERROR, "Can not open image \"%s\" error: %s", fileName.c_str(), strerror(errno)); + return FLASHING_NOPERMISSION, "Can not open image \"%s\" error: %s", fileName.c_str(), strerror(errno)); + + struct stat st {}; + size_t fileSize = 1; + if (fstat(inputFd, &st) >= 0) { + fileSize = st.st_size; + } + + std::vector content(BUFFER_SIZE); + ssize_t readLen = read(inputFd, content.data(), content.size()); + FLASHING_CHECK(readLen >= 0, close(inputFd); + return FLASHING_PART_WRITE_ERROR, "Failed to flash data of len %d", readLen); + ret = WriteRowData(inputFd, fileSize, content, readLen); + close(inputFd); + FLASHING_CHECK(ret == 0, return ret, "Failed to write %s", fileName.c_str()); + FLASHING_LOGI("DoFlash partition %s image:%s success", partPath_.c_str(), fileName.c_str()); + return ret; +} + +int Partition::DoErase() +{ + int ret = Open(); + FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for erase", partName_.c_str()); + + if (!IsBlockDevice(fd_)) { + return 0; + } + + uint64_t size = GetBlockDeviceSize(fd_); + FLASHING_LOGI("DoErase partition %s size %luM", partPath_.c_str(), size); + uint64_t range[2] = {0}; + range[1] = size; + ret = ioctl(fd_, BLKSECDISCARD, &range); + FLASHING_LOGI("DoErase partition %s ret %d", partPath_.c_str(), ret); + if (ret < 0) { + range[0] = 0; + range[1] = size; + ret = ioctl(fd_, BLKDISCARD, &range); + FLASHING_CHECK(ret >= 0, + flash_->RecordMsg(updater::ERROR, "Failed to erase \"%s\" error: %s", partName_.c_str(), strerror(errno)); + return ret, "Failed to erase %s error: %s", partName_.c_str(), strerror(errno)); + std::vector buffer(BLOCK_SIZE, 0); + ret = updater::utils::WriteFully(fd_, buffer.data(), buffer.size()); + FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to flash data errno %d", errno); + fsync(fd_); + } + FLASHING_LOGI("DoErase partition %s erase success", partPath_.c_str()); + return 0; +} + +int Partition::DoFormat(const std::string &fsType) +{ + if (mountPoint_ == "/") { /* Can not format root */ + return 0; + } + int ret = DoUmount(); + FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to umount partition"); + + std::vector formatCmds {}; + ret = BuildCommandParam(fsType, formatCmds); + FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to get param"); + ret = FlashService::ExecCommand(formatCmds); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to format \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to format \"%s\" error: %s", partPath_.c_str(), strerror(ret)); + + fsType_ = fsType; + ret = DoMount(); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to mount \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to mount \"%s\"", partPath_.c_str()); + FLASHING_LOGI("DoFormat partition %s format %s success", partName_.c_str(), fsType_.c_str()); + return ret; +} + +int Partition::DoResize(uint32_t blocks) +{ + int ret = 0; + bool needResize = false; + if (!mountPoint_.empty()) { + needResize = FlashService::CheckFreeSpace(mountPoint_, blocks); + } else { + ret = Open(); + FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for erase", partName_.c_str()); + uint64_t size = GetBlockDeviceSize(fd_); + FLASHING_LOGI("DoResise partition %s size %lu", partName_.c_str(), size); + close(fd_); + fd_ = -1; + uint64_t min = static_cast(DEFAULT_BLOCK_SIZE) * static_cast(blocks); + needResize = size < min; + } + if (!needResize) { + FLASHING_LOGI("No need to resize partition %s", partName_.c_str()); + return 0; + } + ret = DoUmount(); + FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to umount partition"); + + std::vector formatCmds; + formatCmds.push_back(RESIZE_TOOL); + formatCmds.push_back(partPath_); + ret = FlashService::ExecCommand(formatCmds); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to resize \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to resize \"%s\" error: %s", partName_.c_str(), strerror(ret)); + ret = DoMount(); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to mount \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to mount \"%s\"", partPath_.c_str()); + FLASHING_LOGI("Resize partition %s success", partName_.c_str()); + return 0; +} + +int Partition::Open() +{ + if (fd_ != -1) { + return 0; + } + fd_ = open(partPath_.c_str(), O_RDWR); + FLASHING_CHECK(fd_ > 0, + flash_->RecordMsg(updater::ERROR, + "Can not open partiton \"%s\" error: %s", partName_.c_str(), strerror(errno)); + return FLASHING_NOPERMISSION, + "Can open partition %s error %s", partPath_.c_str(), strerror(errno)); + return 0; +} + +int Partition::WriteRowData(int inputFd, size_t fileSize, std::vector &buffer, size_t dataSize) +{ + size_t dataLen = dataSize; + size_t totalWrite = 0; + do { +#ifndef UPDATER_UT + ssize_t writeLen = write(fd_, buffer.data(), dataLen); +#else + ssize_t writeLen = dataLen; +#endif + FLASHING_CHECK(writeLen >= 0, + return FLASHING_PART_WRITE_ERROR, "Failed to write data of len %d", dataLen); + totalWrite += writeLen; + + // continue read and write + ssize_t ret = read(inputFd, buffer.data(), buffer.size()); + if (ret <= 0) { + break; + } + + flash_->PostProgress(UPDATEMOD_FLASH, dataSize, nullptr); + dataLen = ret; + } while (1); + fsync(fd_); + return 0; +} + +int Partition::IsBlockDevice(int fd) const +{ + struct stat st {}; + int ret = fstat(fd, &st); + if (ret < 0) { + return 0; + } + return S_ISBLK(st.st_mode); +} + +uint64_t Partition::GetBlockDeviceSize(int fd) const +{ + uint64_t size = 0; + int ret = ioctl(fd, BLKGETSIZE64, &size); + return (ret == 0) ? size : 0; +} + +std::string Partition::ReadPartitionSysInfo(const std::string &partition, + const std::string &type, std::vector &table) +{ + std::vector buffer(DEVICE_PATH_SIZE, 0); + int ret = snprintf_s(buffer.data(), DEVICE_PATH_SIZE, DEVICE_PATH_SIZE - 1, + "/sys/block/%s/%s/%s", device_->GetDeviceName().c_str(), partition.c_str(), type.c_str()); + FLASHING_CHECK(ret != -1, return "", "Failed to snprintf_s %s", device_->GetDeviceName().c_str()); + return FlashService::ReadSysInfo(buffer.data(), type, table); +} + +const std::string Partition::GetPartitionName() const +{ + return partName_; +} + +int Partition::GetMountInfo() +{ + auto file = std::unique_ptr(fopen("/proc/mounts", "r"), fclose); + FLASHING_CHECK(file != nullptr, return -1, "Failed to open mounts "); + std::vector buffer(LINE_BUFFER_SIZE, 0); + std::vector mount(DEVICE_PATH_SIZE, 0); + std::vector fsType(DEVICE_PATH_SIZE, 0); + std::vector dev(DEVICE_PATH_SIZE, 0); + std::vector flags(DEVICE_PATH_SIZE, 0); + while (fgets(buffer.data(), LINE_BUFFER_SIZE, file.get()) != nullptr) { + // clang-format off + int ret = sscanf_s(buffer.data(), "%255s %255s %255s %255s %*d %*d\n", + dev.data(), DEVICE_PATH_SIZE - 1, + mount.data(), DEVICE_PATH_SIZE - 1, + fsType.data(), DEVICE_PATH_SIZE - 1, + flags.data(), DEVICE_PATH_SIZE - 1); + // clang-format on + if (ret <= 0) { + break; + } + struct stat st {}; + if (lstat(dev.data(), &st) < 0) { + continue; + } + if (S_ISLNK(st.st_mode)) { + readlink(dev.data(), dev.data(), DEVICE_PATH_SIZE); + } + if (strncmp(dev.data(), partPath_.c_str(), partPath_.size()) == 0 || + (partName_ == "system" && strncmp(mount.data(), "/", strlen("/")) == 0)) { + mountPoint_.assign(mount.data()); + fsType_.assign(fsType.data()); + mountFlags_.assign(flags.data()); + break; + } + memset_s(buffer.data(), LINE_BUFFER_SIZE, 0, LINE_BUFFER_SIZE); + } + return 0; +} + +int Partition::DoUmount() +{ + if (mountPoint_.empty()) { + return 0; + } + int ret = umount2(mountPoint_.c_str(), MNT_FORCE); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to umount \"%s\" error: %s", partName_.c_str(), strerror(errno)); + return FLASHING_PART_WRITE_ERROR, "Failed to umount \"%s\" error: %s", partName_.c_str(), strerror(errno)); + return ret; +} + +int Partition::DoMount() +{ + if (mountPoint_.empty()) { + return 0; + } + struct stat st {}; + int ret = lstat(mountPoint_.c_str(), &st); + FLASHING_CHECK(ret >= 0, return ret, "Failed to fstat %s error %s", mountPoint_.c_str(), strerror(errno)); + + if (S_ISLNK(st.st_mode)) { + unlink(mountPoint_.c_str()); + } + mkdir(mountPoint_.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + // get mount flags + std::string data; + uint32_t flags = GetMountFlags(mountFlags_, data); + errno = 0; + while ((ret = mount(partPath_.c_str(), mountPoint_.c_str(), fsType_.c_str(), flags, data.c_str()) != 0)) { + if (errno == EAGAIN) { + continue; + } else { + break; + } + } + return ret; +} + +int Partition::BuildCommandParam(const std::string &fsType, std::vector &formatCmds) const +{ + std::map fsToolsMap = { + { "ext4", FORMAT_TOOL_FOR_EXT4 }, + { "f2fs", FORMAT_TOOL_FOR_F2FS }, + }; + auto it = fsToolsMap.find(fsType); + FLASHING_CHECK(it != fsToolsMap.end(), + flash_->RecordMsg(updater::ERROR, "Not support fs type %s", fsType.c_str()); + return FLASHING_FSTYPE_NOT_SUPPORT, "Not support fs type %s", fsType.c_str()); + + if (fsType == "ext4") { + formatCmds.push_back(it->second); + formatCmds.push_back("-F"); + formatCmds.push_back("-t"); + formatCmds.push_back(fsType); + formatCmds.push_back("-b"); + formatCmds.push_back(std::to_string(DEFAULT_BLOCK_SIZE)); + formatCmds.push_back(partPath_); + } else if (fsType == "f2fs") { + formatCmds.push_back(it->second); + formatCmds.push_back(partPath_); + } + return 0; +} + +bool Partition::IsOnlyErase() const +{ + std::vector rawPartName = { + "boot", "fastboot", "kernel", "misc", "system" + }; + auto it = std::find (rawPartName.begin(), rawPartName.end(), partName_); + return it != rawPartName.end(); +} + +uint32_t Partition::GetMountFlags(const std::string &mountFlagsStr, std::string &data) const +{ + static std::map mntInfo = { + { "ro", MS_RDONLY }, + { "rw", 0 }, + { ",sync", MS_SYNCHRONOUS }, + { ",dirsync", MS_DIRSYNC }, + { ",mand", MS_MANDLOCK }, + { ",lazytime", MS_LAZYTIME }, + { ",nosuid", MS_NOSUID }, + { ",nodev", MS_NODEV }, + { ",noexec", MS_NOEXEC }, + { ",noatime", MS_NOATIME }, + { ",nodiratime", MS_NODIRATIME }, + { ",relatime", MS_RELATIME }, + { ",remount", MS_REMOUNT }, + { ",bind", MS_BIND }, + { ",rec", MS_REC }, + { ",unbindable", MS_UNBINDABLE }, + { ",private", MS_PRIVATE }, + { ",slave", MS_SLAVE }, + { ",shared", MS_SHARED }, + { ",defaults", 0 }, + }; + + // get rw flags + uint32_t flags = 0; + std::string::size_type found = std::string::npos; + std::string::size_type start = 0; + while (true) { + found = mountFlagsStr.find_first_of(",", start + 1); + std::string option = mountFlagsStr.substr(start, found - start); + auto iter = mntInfo.find(option); + if (iter != mntInfo.end()) { + flags |= iter->second; + } else { + data.append(option); + data.append(","); + } + if (found == std::string::npos) { + break; + } + start = found; + } + data.pop_back(); // Remove last ',' + return flags; +} +} diff --git a/services/flashd/partition.h b/services/flashd/partition.h new file mode 100755 index 00000000..411568f0 --- /dev/null +++ b/services/flashd/partition.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLASHING_PARTITION_H +#define FLASHING_PARTITION_H +#include +#include +#include +#include +#include +#include "blockdevice.h" +#include "flash_utils.h" + +namespace flashd { +enum class PartitionType { + NORMAL, + LOGICAL, + EXTENDED, +}; + +class Partition { +public: + Partition(const std::string &name, const std::string &path, BlockDevicePtr device, FlashingPtr flash) + : partPath_(path), devName_(name), device_(device), flash_(flash) {} + ~Partition(); + + int Load(); + int DoFlash(const std::string &fileName); + int DoFormat(const std::string &fsType); + int DoErase(); + int DoResize(uint32_t blocks); + + bool IsOnlyErase() const; + const std::string GetPartitionName() const; + PartitionType GetPartitionType() const + { + return type_; + } + const std::string GetPartitionPath() const + { + return partPath_; + } +private: + std::string ReadPartitionSysInfo(const std::string &partition, + const std::string &type, std::vector &table); + int Open(); + int WriteRowData(int inputFd, size_t fileSize, std::vector &buffer, size_t dataSize); + int IsBlockDevice(int fd) const; + int GetMountInfo(); + int DoUmount(); + int DoMount(); + int BuildCommandParam(const std::string &fsType, std::vector &formatCmds) const; + uint64_t GetBlockDeviceSize(int fd) const; + uint32_t GetMountFlags(const std::string &mountFlagsStr, std::string &data) const; + + int fd_ = -1; + int partNumber_ { 0 }; // Partition number. + std::string partPath_ {}; + std::string devName_ {}; // partition DEVNAME + std::string partName_ {}; // partition PARTN + PartitionType type_ { PartitionType::NORMAL }; + std::string fsType_ {}; // File system type, ext4, f2fs etc. + std::string mountFlags_ {}; // flags:rw,relatime,fmask=0077,dmask=0077 + std::string mountPoint_ {}; + BlockDevicePtr device_ = nullptr; + FlashingPtr flash_ = nullptr; +}; +using PartitionPtr = Partition *; +} +#endif // FLASHING_PARTITION_H \ No newline at end of file diff --git a/services/fs_manager/BUILD.gn b/services/fs_manager/BUILD.gn index 3ce65a7c..93aad545 100644 --- a/services/fs_manager/BUILD.gn +++ b/services/fs_manager/BUILD.gn @@ -17,7 +17,6 @@ ohos_static_library("libfsmanager") { sources = [ "cmp_partition.cpp", "do_partition.cpp", - "fstab.cpp", "mount.cpp", "partitions.cpp", ] @@ -27,9 +26,11 @@ ohos_static_library("libfsmanager") { "//base/update/updater/interfaces/kits/include", "//base/update/updater/utils/include", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ + "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static", "//base/update/updater/utils:libutils", "//third_party/bounds_checking_function:libsec_static", ] diff --git a/services/fs_manager/fstab.cpp b/services/fs_manager/fstab.cpp deleted file mode 100644 index 2851568b..00000000 --- a/services/fs_manager/fstab.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "fs_manager/fstab.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "fs_manager/fstab_api.h" -#include "log/log.h" -#include "utils.h" - -namespace updater { -using utils::SplitString; - -static std::map g_fsManagerMap = { - {"check", FS_MANAGER_CHECK}, - {"wait", FS_MANAGER_WAIT}, -}; - -void ParseFstabPerLine(std::string &line, Fstab &fstab, bool &parseError) -{ - const std::string separator = " \t"; - char *restPtr = nullptr; - struct FstabItem item; - char *p = nullptr; - do { - if ((p = strtok_r(const_cast(line.c_str()), separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse block device.\n"); - break; - } - - item.deviceName = p; - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse mount point.\n"); - break; - } - - item.mountPoint = p; - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse fs type.\n"); - break; - } - item.fsType = p; - - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse mount options.\n"); - break; - } - item.mountOptions = p; - - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse fs manager flags.\n"); - break; - } - item.fsManagerFlags = 0; - std::string fsFlags = p; - for (const auto& flag : g_fsManagerMap) { - if (fsFlags.find(flag.first) != std::string::npos) { - item.fsManagerFlags |= flag.second; - } - } - - fstab.emplace_back(std::move(item)); - parseError = false; - } while (0); - - return; -} - -bool ReadFstabFromFile(const std::string &fstabFile, Fstab &fstab) -{ - char *line = nullptr; - size_t allocLen = 0; - ssize_t readLen = 0; - std::string tmpStr = ""; - Fstab tmpTab; - char *realPath = realpath(fstabFile.c_str(), NULL); - if (realPath == nullptr) { - return false; - } - auto fp = std::unique_ptr(fopen(realPath, "r"), fclose); - if (fp.get() == nullptr) { - LOG(ERROR) << "fp is nullptr"; - free(realPath); - return false; - } - free(realPath); - while ((readLen = getline(&line, &allocLen, fp.get())) != -1) { - char *p = nullptr; - if (line[readLen - 1] == '\n') { - line[readLen - 1] = '\0'; - } - p = line; - while (isspace(*p)) { - p++; - } - - if (*p == '\0' || *p == '#') { - continue; - } - - bool parseError = true; - tmpStr = p; - ParseFstabPerLine(tmpStr, tmpTab, parseError); - tmpStr.clear(); - if (parseError) { - free(line); - return false; - } - } - - free(line); - fstab = std::move(tmpTab); - return true; -} - -struct FstabItem* FindFstabItemForMountPoint(Fstab &fstab, const std::string& mp) -{ - for (auto &item : fstab) { - if (item.mountPoint == mp) { - return &item; - } - } - return nullptr; -} - -struct FstabItem* FindFstabItemForPath(Fstab &fstab, const std::string &path) -{ - struct FstabItem *item = nullptr; - std::string tmp(path); - if (path.empty()) { - return nullptr; - } - while (true) { - item = FindFstabItemForMountPoint(fstab, tmp); - if (item != nullptr) { - return item; - } - auto sep = tmp.find_last_of('/'); - if (sep == std::string::npos) { - return nullptr; - } - if (sep == 0) { - tmp = "/"; - break; - } - tmp = tmp.substr(0, sep); - } - return nullptr; -} - -static bool ParseDefaultMountFlags(const std::string &mountFlag, unsigned long &flags) -{ - std::map mountFlags = { - { "noatime", MS_NOATIME }, - { "noexec", MS_NOEXEC }, - { "nosuid", MS_NOSUID }, - { "nodev", MS_NODEV }, - { "nodiratime", MS_NODIRATIME }, - { "ro", MS_RDONLY }, - { "rw", 0 }, - { "sync", MS_SYNCHRONOUS }, - { "remount", MS_REMOUNT }, - { "bind", MS_BIND }, - { "rec", MS_REC }, - { "unbindable", MS_UNBINDABLE }, - { "private", MS_PRIVATE }, - { "slave", MS_SLAVE }, - { "shared", MS_SHARED }, - { "defaults", 0 }, - }; - for (const auto &flag : mountFlags) { - if (mountFlag == flag.first) { - flags = flag.second; - return true; - } - } - return false; -} - -unsigned long GetMountFlags(const std::string &mountOptions, std::string &fsSpecificOptions) -{ - unsigned long flags = 0; - unsigned long tmpFlag = 0; - - auto options = SplitString(mountOptions, ","); - fsSpecificOptions.clear(); - for (const auto &option : options) { - if (ParseDefaultMountFlags(option, tmpFlag)) { - flags |= tmpFlag; - } else { // not default mount flags, maybe File system specific. - fsSpecificOptions.append(option); - fsSpecificOptions.append(","); - } - } - fsSpecificOptions.pop_back(); // Remove last ',' - LOG(DEBUG) << "File system specific mount options is " << fsSpecificOptions; - return flags; -} -} // updater diff --git a/services/fs_manager/mount.cpp b/services/fs_manager/mount.cpp index 2b33668d..0a71611f 100644 --- a/services/fs_manager/mount.cpp +++ b/services/fs_manager/mount.cpp @@ -12,8 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "fs_manager/mount.h" +#include "fs_manager/mount.h" #include #include #include @@ -22,166 +22,34 @@ #include #include #include -#include "fs_manager/fstab.h" -#include "fs_manager/fstab_api.h" #include "log/log.h" #include "utils.h" namespace updater { using updater::utils::SplitString; static std::string g_defaultUpdaterFstab = ""; -static Fstab g_fstab; - -static bool IsSupportedFilesystem(const std::string &fsType) -{ - std::vector supportedFilesystems = {"ext4", "f2fs", "vfat"}; - - bool supported = false; - for (const auto &fs : supportedFilesystems) { - if (fsType == fs) { - supported = true; - break; - } - } - return supported; -} - -static int ExecCommand(std::vector cmds) -{ - std::vector extractedCmds; - - for (const auto &cmd : cmds) { - extractedCmds.push_back(const_cast(cmd.c_str())); - } - extractedCmds.push_back(nullptr); - pid_t pid = fork(); - if (pid < 0) { - LOG(ERROR) << "Fork new process to format failed: " << errno; - ERROR_CODE(CODE_FORK_FAIL); - return -1; - } - if (pid == 0) { - execv(extractedCmds[0], extractedCmds.data()); - exit(-1); - } - int status; - waitpid(pid, &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOG(ERROR) << "Command " << extractedCmds[0] << " failed with status " << WEXITSTATUS(status); - } - return WEXITSTATUS(status); -} - -static int DoFormat(const std::string &devPath, const std::string &fsType) -{ - std::map fsToolsMap = { - { "ext4", "/bin/mke2fs" }, - { "f2fs", "/bin/make_f2fs" }, - }; - int ret = 0; - auto it = fsToolsMap.find(fsType); - if (it == fsToolsMap.end()) { - LOG(ERROR) << "Can not find fs tools for " << fsType; - return -1; - } - auto fsTool = it->second; - if (fsType == "ext4") { - constexpr int blockSize = 4096; - std::vector formatCmds; - formatCmds.push_back(fsTool); - formatCmds.push_back("-F"); - formatCmds.push_back("-t"); - formatCmds.push_back(fsType); - formatCmds.push_back("-b"); - formatCmds.push_back(std::to_string(blockSize)); - formatCmds.push_back(devPath); - ret = ExecCommand(formatCmds); - } else if (fsType == "f2fs") { - std::vector formatCmds; - formatCmds.push_back(fsTool); - formatCmds.push_back(devPath); - ret = ExecCommand(formatCmds); - } - return ret; -} - -int FormatPartition(const std::string &path) -{ - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); - if (item == nullptr) { - LOG(ERROR) << "Cannot find fstab item for " << path << " to format."; - return -1; - } - - if (item->mountPoint == "/") { - /* Can not format root */ - return 0; - } - - if (!IsSupportedFilesystem(item->fsType)) { - LOG(ERROR) << "Try to format " << item->mountPoint << " with unsupported file system type: " << item->fsType; - return -1; - } - - // Umount first - if (UmountForPath(path) != 0) { - return -1; - } - int ret = DoFormat(item->deviceName, item->fsType); - if (ret != 0) { - LOG(ERROR) << "Format " << path << " failed"; - } - return ((ret != 0) ? -1 : 0); -} - -static MountStatus GetMountStatusForMountPoint(const std::string &mountPoint) +static Fstab *g_fstab; +static std::string GetFstabFile() { - char buffer[512]; - size_t n; - constexpr size_t numMountItems = 6; - const std::string mountFile = "/proc/mounts"; - auto fp = std::unique_ptr(fopen(mountFile.c_str(), "r"), fclose); - - while (fgets(buffer, sizeof(buffer) - 1, fp.get()) != nullptr) { - n = strlen(buffer); - if (n > 0 && buffer[n - 1] == '\n') { - buffer[n - 1] = '\0'; - } - std::string line(buffer); - std::vector mountItems = SplitString(line); - if (mountItems.size() == numMountItems) { - // Second item in /proc/mounts is mount point - if (mountItems[1] == mountPoint) { - return MountStatus::MOUNT_MOUNTED; - } + /* check vendor fstab files from specific directory */ + std::vector specificFstabFiles = {"/vendor/etc/fstab.updater"}; + for (auto& fstabFile : specificFstabFiles) { + if (access(fstabFile.c_str(), F_OK) == 0) { + return fstabFile; } } - - // Cannot find it from system. - return MountStatus::MOUNT_UMOUNTED; + return ""; } MountStatus GetMountStatusForPath(const std::string &path) { - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); if (item == nullptr) { return MountStatus::MOUNT_ERROR; } return GetMountStatusForMountPoint(item->mountPoint); } -static std::string GetFstabFile() -{ - /* check vendor fstab files from specific directory */ - std::vector specificFstabFiles = {"/vendor/etc/fstab.updater", "/odm/etc/fstab.updater"}; - for (auto& fstabFile : specificFstabFiles) { - if (access(fstabFile.c_str(), F_OK) == 0) { - return fstabFile; - } - } - return ""; -} - void LoadFstab() { std::string fstabFile = g_defaultUpdaterFstab; @@ -192,22 +60,20 @@ void LoadFstab() } } // Clear fstab before read fstab file. - g_fstab.clear(); - if (ReadFstabFromFile(fstabFile, g_fstab) == false) { + if ((g_fstab = ReadFstabFromFile(fstabFile.c_str(), false)) == nullptr) { LOG(WARNING) << "Read " << fstabFile << " failed"; return; } LOG(DEBUG) << "Updater filesystem config info:"; - for (const auto &item : g_fstab) { - LOG(DEBUG) << "\tDevice: " << item.deviceName; - LOG(DEBUG) << "\tMount point : " << item.mountPoint; - LOG(DEBUG) << "\tFs type : " << item.fsType; - LOG(DEBUG) << "\tMount options: " << item.mountOptions; + for (FstabItem *item = g_fstab->head; item != nullptr; item = item->next) { + LOG(DEBUG) << "\tDevice: " << item->deviceName; + LOG(DEBUG) << "\tMount point : " << item->mountPoint; + LOG(DEBUG) << "\tFs type : " << item->fsType; + LOG(DEBUG) << "\tMount options: " << item->mountOptions; } } - void LoadSpecificFstab(const std::string &fstabName) { g_defaultUpdaterFstab = fstabName; @@ -217,21 +83,20 @@ void LoadSpecificFstab(const std::string &fstabName) int UmountForPath(const std::string& path) { - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); - MountStatus rc; + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); if (item == nullptr) { LOG(ERROR) << "Cannot find fstab item for " << path << " to umount."; return -1; } LOG(DEBUG) << "Umount for path " << path; - rc = GetMountStatusForMountPoint(item->mountPoint); - if (rc == MountStatus::MOUNT_ERROR) { + MountStatus rc = GetMountStatusForMountPoint(item->mountPoint); + if (rc == MOUNT_ERROR) { return -1; - } else if (rc == MountStatus::MOUNT_UMOUNTED) { + } else if (rc == MOUNT_UMOUNTED) { return 0; } else { - int ret = umount(item->mountPoint.c_str()); + int ret = umount(item->mountPoint); if (ret == -1) { LOG(ERROR) << "Umount " << item->mountPoint << "failed: " << errno; return -1; @@ -240,54 +105,10 @@ int UmountForPath(const std::string& path) return 0; } -static int Mount(const std::string &source, const std::string &target, const std::string &fsType, - unsigned long flags, const std::string &data) -{ - struct stat st {}; - int rc; - if (stat(target.c_str(), &st) != 0 && errno != ENOENT) { - LOG(ERROR) << "Cannot get " << target << " status: " << errno; - return -1; - } - if ((st.st_mode & S_IFMT) == S_IFLNK) { // link, delete it. - unlink(target.c_str()); - } - mkdir(target.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - errno = 0; - while ((rc = mount(source.c_str(), target.c_str(), fsType.c_str(), flags, data.c_str()) != 0)) { - if (errno == EAGAIN) { - LOG(INFO) << "Mount " << source << " to " << target << " failed. try again"; - continue; - } else { - break; - } - } - return rc; -} - -static int DoMount(const struct FstabItem &item) -{ - unsigned long mountFlags; - std::string fsSpecificOptions; - - mountFlags = GetMountFlags(item.mountOptions, fsSpecificOptions); - if (!IsSupportedFilesystem(item.fsType)) { - LOG(ERROR) << "Unsupported file system \"" << item.fsType << "\""; - return -1; - } - int rc = Mount(item.deviceName, item.mountPoint, item.fsType, mountFlags, fsSpecificOptions); - if (rc != 0) { - LOG(ERROR) << "Mount " << item.deviceName << " to " << item.mountPoint << " failed: " << errno; - } else { - LOG(INFO) << "Mount " << item.deviceName << " to " << item.mountPoint << " successful"; - } - return rc; -} - int MountForPath(const std::string &path) { - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); - int ret; + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); + int ret = -1; if (item == nullptr) { LOG(ERROR) << "Cannot find fstab item for " << path << " to mount."; return -1; @@ -296,51 +117,68 @@ int MountForPath(const std::string &path) LOG(DEBUG) << "Mount for path " << path; MountStatus rc = GetMountStatusForMountPoint(item->mountPoint); if (rc == MountStatus::MOUNT_ERROR) { - return -1; + ret = -1; } else if (rc == MountStatus::MOUNT_MOUNTED) { - std::cout << path << " already mounted\n"; - return 0; + LOG(INFO) << path << " already mounted"; + ret = 0; } else { - ret = DoMount(*item); + ret = MountOneItem(item); } return ret; } -struct FstabItem *GetItemForMountPoint(const std::string &mountPoint) +int FormatPartition(const std::string &path) { - if (g_fstab.empty()) { - LOG(ERROR) << "Fstab is empty."; - return nullptr; + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); + if (item == nullptr) { + LOG(ERROR) << "Cannot find fstab item for " << path << " to format."; + return -1; } - for (auto& item : g_fstab) { - if (item.mountPoint == mountPoint) { - return &item; - } + + if (strcmp(item->mountPoint, "/") == 0) { + /* Can not format root */ + return 0; } - return nullptr; + + if (!IsSupportedFilesystem(item->fsType)) { + LOG(ERROR) << "Try to format " << item->mountPoint << " with unsupported file system type: " << item->fsType; + return -1; + } + + // Umount first + if (UmountForPath(path) != 0) { + return -1; + } + int ret = DoFormat(item->deviceName, item->fsType); + if (ret != 0) { + LOG(ERROR) << "Format " << path << " failed"; + } + return ((ret != 0) ? -1 : 0); } int SetupPartitions() { - if (g_fstab.empty()) { - LOG(ERROR) << "Fstab is empty."; + if (g_fstab == NULL || g_fstab->head == NULL) { + LOG(ERROR) << "Fstab is invalid"; return -1; } - for (const auto &item : g_fstab) { - if (item.mountPoint == "/" || item.mountPoint == "/tmp" || item.fsType == "none" || - item.mountPoint == "/sdcard") { + for (const FstabItem *item = g_fstab->head; item != nullptr; item = item->next) { + std::string mountPoint(item->mountPoint); + std::string fsType(item->fsType); + if (mountPoint == "/" || mountPoint == "/tmp" || fsType == "none" || + mountPoint == "/sdcard") { continue; } - if (item.mountPoint == "/data") { - if (MountForPath(item.mountPoint) != 0) { - LOG(ERROR) << "Expected partition " << item.mountPoint << " is not mounted."; + if (mountPoint == "/data") { + if (MountForPath(mountPoint) != 0) { + LOG(ERROR) << "Expected partition " << mountPoint << " is not mounted."; return -1; } continue; } - if (UmountForPath(item.mountPoint) != 0) { - LOG(ERROR) << "Umount " << item.mountPoint << " failed"; + if (UmountForPath(mountPoint) != 0) { + LOG(ERROR) << "Umount " << mountPoint << " failed"; return -1; } } @@ -351,12 +189,11 @@ const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint) { std::string blockDevice = ""; if (!mountPoint.empty()) { - auto item = FindFstabItemForMountPoint(g_fstab, mountPoint); - if (item) { + FstabItem *item = FindFstabItemForMountPoint(*g_fstab, mountPoint.c_str()); + if (item != NULL) { blockDevice = item->deviceName; } } return blockDevice; } } // updater - diff --git a/services/include/applypatch/partition_record.h b/services/include/applypatch/partition_record.h index d3418992..962d43f4 100644 --- a/services/include/applypatch/partition_record.h +++ b/services/include/applypatch/partition_record.h @@ -68,7 +68,7 @@ private: private: std::string GetMiscPartitionPath(const std::string &mountPoint = "/misc"); - PartitionRecordInfo info_; + PartitionRecordInfo info_ {}; // offset of partition record in misc. // offset is not start from zero, but // start from the global offset of misc partition. diff --git a/services/include/applypatch/transfer_manager.h b/services/include/applypatch/transfer_manager.h index 3231917f..b2e06bdb 100644 --- a/services/include/applypatch/transfer_manager.h +++ b/services/include/applypatch/transfer_manager.h @@ -73,6 +73,7 @@ public: } std::string ReloadForRetry() const; bool CheckResult(const CommandResult result, const std::string &cmd, const CommandType &type); + bool NeedSetProgress(const CommandType &type); private: bool RegisterForRetry(const std::string &cmd); diff --git a/services/include/applypatch/updater_env.h b/services/include/applypatch/updater_env.h index 4ce1b8f7..121e1a4d 100644 --- a/services/include/applypatch/updater_env.h +++ b/services/include/applypatch/updater_env.h @@ -22,6 +22,7 @@ #include "package/pkg_manager.h" #include "script_instruction.h" #include "script_manager.h" +#include "updater/updater.h" using uscript::UScriptEnv; using uscript::UScriptInstructionFactory; @@ -30,8 +31,8 @@ using uscript::UScriptInstructionFactoryPtr; namespace updater { class UpdaterEnv : public UScriptEnv { public: - UpdaterEnv(hpackage::PkgManager::PkgManagerPtr pkgManager, FILE* pipeWrite, bool retry) : - UScriptEnv(pkgManager), pipeWrite_(pipeWrite), isRetry_(retry) {} + UpdaterEnv(hpackage::PkgManager::PkgManagerPtr pkgManager, PostMessageFunction postMessage, bool retry) + : UScriptEnv(pkgManager), postMessage_(postMessage), isRetry_(retry) {} virtual ~UpdaterEnv(); virtual void PostMessage(const std::string &cmd, std::string content); @@ -43,7 +44,7 @@ public: } private: UScriptInstructionFactoryPtr factory_ = nullptr; - FILE* pipeWrite_ = nullptr; + PostMessageFunction postMessage_ = nullptr; bool isRetry_ = false; }; } diff --git a/services/include/flashd/flashd.h b/services/include/flashd/flashd.h new file mode 100755 index 00000000..8eae9598 --- /dev/null +++ b/services/include/flashd/flashd.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UPDATER_FLASHING_H +#define UPDATER_FLASHING_H +#include +#include + +namespace flashd { +enum { + FLASHING_SYSTEM_ERROR = 100, + FLASHING_ARG_INVALID, + FLASHING_IMAGE_INVALID, + FLASHING_PART_NOEXIST, + FLASHING_NOPERMISSION, + FLASHING_PART_WRITE_ERROR, + FLASHING_PACKAGE_INVALID, + FLASHING_SPACE_NOTENOUGH, + FLASHING_INVALID_SPACE, + FLASHING_FSTYPE_NOT_SUPPORT, +}; + +enum UpdateModType { + UPDATEMOD_UPDATE, + UPDATEMOD_FLASH, + UPDATEMOD_ERASE, + UPDATEMOD_FORMAT, + UPDATEMOD_MAX +}; + +static constexpr uint16_t MAX_SIZE_BUF = 1024; +static constexpr uint32_t PERCENT_FINISH = 100; +static constexpr uint32_t PERCENT_CLEAR = (uint32_t)-1; + +#ifndef LOCAL_SUPPORT +const std::string FORMAT_TOOL_FOR_EXT4 = "/bin/mke2fs"; +const std::string FORMAT_TOOL_FOR_F2FS = "/bin/make_f2fs"; +const std::string RESIZE_TOOL = "/bin/resize2fs"; +const std::string FLASHD_FILE_PATH = "/data/updater/"; +const std::string FLASHD_HDC_LOG_PATH = "/tmp/flashd_hdc.log"; +#else +const std::string FORMAT_TOOL_FOR_EXT4 = "/usr/sbin/mke2fs"; +const std::string FORMAT_TOOL_FOR_F2FS = "/system/bin/make_f2fs"; +const std::string RESIZE_TOOL = "/bin/resize2fs"; +const std::string FLASHD_FILE_PATH = "/home/axw/develop/build/"; +const std::string FLASHD_HDC_LOG_PATH = "/home/axw/develop/build/hdc.log"; +#endif +static constexpr uint32_t MIN_BLOCKS_FOR_UPDATE = 1024 * 1024; +static constexpr uint32_t DEFAULT_BLOCK_SIZE = 4096; +static constexpr uint32_t DEFAULT_SIZE_UNIT = 1024 * 1024; + +using FlashHandle = void *; +int flashd_main(int argc, char **argv); +using ProgressFunction = std::function; + +int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunction progressor); +int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdParam, std::string &filePath); +int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam, const std::string &filePath); +int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partition); +} // namespace flashd +#endif /* UPDATER_FLASHING_H */ diff --git a/services/include/fs_manager/fstab_api.h b/services/include/fs_manager/fstab_api.h deleted file mode 100644 index a8e36a25..00000000 --- a/services/include/fs_manager/fstab_api.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __UPDATER_FS_MANAGER_FSTAB_API_H -#define __UPDATER_FS_MANAGER_FSTAB_API_H -#include -#include "fs_manager/fstab.h" - -namespace updater { -bool ReadFstabFromFile(const std::string &fstabFile, Fstab &fstabs); -struct FstabItem* FindFstabItemForPath(Fstab &fstab, const std::string &path); -struct FstabItem* FindFstabItemForMountPoint(Fstab &fstab, const std::string &mp); -unsigned long GetMountFlags(const std::string &mountOptions, std::string &fsSpecificOptions); -} // updater -#endif // __UPDATER_FS_MANAGER_FSTAB_API_ - diff --git a/services/include/fs_manager/mount.h b/services/include/fs_manager/mount.h index 7d70ccbb..744a8d13 100644 --- a/services/include/fs_manager/mount.h +++ b/services/include/fs_manager/mount.h @@ -16,24 +16,16 @@ #define UPDATER_FS_MANAGER_MOUNT_H #include -#include "fs_manager/fstab_api.h" -#include "fs_manager/fstab.h" +#include "fs_manager/fs_manager.h" namespace updater { -enum MountStatus : int { - MOUNT_ERROR = -1, - MOUNT_UMOUNTED = 0, - MOUNT_MOUNTED = 1, -}; - void LoadFstab(); /* Load fstab */ void LoadSpecificFstab(const std::string &fstabName); int FormatPartition(const std::string &path); int UmountForPath(const std::string &path); int MountForPath(const std::string &path); -MountStatus GetMountStatusForPath(const std::string &path); -struct FstabItem *GetItemForMountPoint(const std::string &mountPoint); int SetupPartitions(); const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint); +MountStatus GetMountStatusForPath(const std::string &path); } // updater #endif // UPDATER_FS_MANAGER_MOUNT_H \ No newline at end of file diff --git a/services/include/package/pkg_manager.h b/services/include/package/pkg_manager.h index 9cf37201..e70c9d8d 100644 --- a/services/include/package/pkg_manager.h +++ b/services/include/package/pkg_manager.h @@ -47,6 +47,13 @@ enum { PKG_VERIFY_FAIL, }; +enum { + POST_TYPE_UPLOAD_PKG = 0, + POST_TYPE_DECODE_PKG, + POST_TYPE_VERIFY_PKG, + POST_TYPE_WRITE_PARTITION +}; + /** * Package information */ @@ -203,6 +210,8 @@ public: } }; +using PkgDecodeProgress = std::function; + /** * Get a singleton PkgManager instance. */ @@ -334,6 +343,10 @@ public: std::vector &fileIds) = 0; virtual int32_t ParsePackage(StreamPtr stream, std::vector &fileIds, int32_t type) = 0; + + virtual void SetPkgDecodeProgress(PkgDecodeProgress decodeProgress) = 0; + + virtual void PostDecodeProgress(int type, size_t writeDataLen, const void *context) = 0; }; } // namespace hpackage #endif // PKG_MANAGER_H diff --git a/services/include/updater/updater.h b/services/include/updater/updater.h index e71b1b9c..0d94c5ab 100644 --- a/services/include/updater/updater.h +++ b/services/include/updater/updater.h @@ -26,9 +26,12 @@ enum UpdaterStatus { UPDATE_CORRUPT, /* package or verify failed, something is broken. */ UPDATE_SKIP, /* skip update because of condition is not satisfied, e.g, battery is low */ UPDATE_RETRY, + UPDATE_SPACE_NOTENOUGH, UPDATE_UNKNOWN }; +using PostMessageFunction = std::function; + UpdaterStatus DoInstallUpdaterPackage(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath, int retryCount); @@ -38,5 +41,19 @@ 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); + +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); + +bool IsSDCardExist(const std::string &sdcard_path); + +void PostUpdater(); + +std::vector ParseParams(int argc, char **argv); } // updater #endif /* UPDATER_UPDATER_H */ diff --git a/services/include/updater/updater_const.h b/services/include/updater/updater_const.h index 7dad0359..88775927 100644 --- a/services/include/updater/updater_const.h +++ b/services/include/updater/updater_const.h @@ -27,6 +27,8 @@ const std::string UPDATER_PATH = "/data/updater"; const std::string MISC_FILE = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/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"; + #ifndef UPDATER_UT const std::string SDCARD_CARD_PATH = "/sdcard/updater"; const std::string SDCARD_CARD_PKG_PATH = "/sdcard/updater/updater.zip"; diff --git a/services/main.cpp b/services/main.cpp index 322f128c..e0173eef 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -12,10 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "flashd/flashd.h" +#include "fs_manager/mount.h" +#include "log/log.h" +#include "misc_info/misc_info.h" +#include "updater/updater_const.h" #include "updater_main.h" +using namespace updater; + int main(int argc, char **argv) { + struct UpdateMessage boot {}; + // read from misc + bool ret = ReadUpdaterMessage(MISC_FILE, boot); + if (!ret) { + printf("ReadUpdaterMessage MISC_FILE failed!\n"); + } + // 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. + if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { + ret = ReadUpdaterMessage(COMMAND_FILE, boot); + if (!ret) { + printf("ReadUpdaterMessage COMMAND_FILE failed!\n"); + } + } + + const int flashBootLength = 10; + bool useFlash = memcmp(boot.command, "boot_flash", flashBootLength) == 0; + InitUpdaterLogger(useFlash ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); + SetLogLevel(VERBOSE); + LoadFstab(); + STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; + LOG(INFO) << "boot.command " << boot.command; + LOG(INFO) << "boot.update " << boot.update; + if (useFlash) { + return flashd::flashd_main(argc, argv); + } return updater::UpdaterMain(argc, argv); } diff --git a/services/package/pkg_manager/pkg_managerImpl.cpp b/services/package/pkg_manager/pkg_managerImpl.cpp index 8dbff31c..684536c0 100644 --- a/services/package/pkg_manager/pkg_managerImpl.cpp +++ b/services/package/pkg_manager/pkg_managerImpl.cpp @@ -52,7 +52,9 @@ PkgManager::PkgManagerPtr PkgManager::GetPackageInstance() PkgManager::PkgManagerPtr PkgManager::CreatePackageInstance() { - return new PkgManagerImpl(); + PkgManager::PkgManagerPtr impl = new PkgManagerImpl(); + PKG_LOGI("CreatePackageInstance %p", impl); + return impl; } void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager) @@ -60,6 +62,7 @@ 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; @@ -205,16 +208,16 @@ PkgFilePtr PkgManagerImpl::CreatePackage(PkgStreamPtr stream, PkgFile::PkgType t PkgFilePtr pkgFile = nullptr; switch (type) { case PkgFile::PKG_TYPE_UPGRADE: - pkgFile = new UpgradePkgFile(stream, header); + pkgFile = new UpgradePkgFile(this, stream, header); break; case PkgFile::PKG_TYPE_ZIP: - pkgFile = new ZipPkgFile(stream); + pkgFile = new ZipPkgFile(this, stream); break; case PkgFile::PKG_TYPE_LZ4: - pkgFile = new Lz4PkgFile(stream); + pkgFile = new Lz4PkgFile(this, stream); break; case PkgFile::PKG_TYPE_GZIP: - pkgFile = new GZipPkgFile(stream); + pkgFile = new GZipPkgFile(this, stream); break; default: return nullptr; @@ -396,7 +399,7 @@ int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fi int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) { - PkgStreamPtr pkgStream = new MemoryMapStream(fileName, buffer, PkgStream::PkgStreamType_Buffer); + PkgStreamPtr pkgStream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer); PKG_CHECK(pkgStream != nullptr, return -1, "Failed to create stream"); stream = pkgStream; return PKG_SUCCESS; @@ -438,7 +441,7 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string FILE *file = nullptr; 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(fileName, file, type); + stream = new FileStream(this, fileName, file, type); } else if (type == PkgStream::PkgStreamType_MemoryMap) { size_t fileSize = size; if (fileSize == 0) { @@ -451,7 +454,7 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string uint8_t *memoryMap = MapMemory(fileName, fileSize); PKG_CHECK(memoryMap != nullptr, return PKG_INVALID_FILE, "Fail to map memory %s ", fileName.c_str()); PkgBuffer buffer(memoryMap, fileSize); - stream = new MemoryMapStream(fileName, buffer); + stream = new MemoryMapStream(this, fileName, buffer); } else { return -1; } @@ -462,7 +465,7 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName, PkgStream::ExtractFileProcessor processor, const void *context) { - stream = new ProcessorStream(fileName, processor, context); + stream = new ProcessorStream(this, fileName, processor, context); PKG_CHECK(stream != nullptr, return -1, "Failed to create stream"); return PKG_SUCCESS; } @@ -588,6 +591,7 @@ int32_t PkgManagerImpl::GenerateFileDigest(PkgStreamPtr stream, PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN, algorithm->Update(buff, readLen)); PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN, algorithmInner->Update(buff, readLen)); offset += readLen; + PostDecodeProgress(POST_TYPE_VERIFY_PKG, readLen, nullptr); readLen = 0; } @@ -677,8 +681,8 @@ int32_t PkgManagerImpl::DecompressBuffer(FileInfoPtr info, const PkgBuffer &data PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info); PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "Can not get algorithm for %s", info->identity.c_str()); - std::shared_ptr inStream = std::make_shared(info->identity, - data, PkgStream::PkgStreamType_Buffer); + std::shared_ptr inStream = std::make_shared( + (PkgManager::PkgManagerPtr)this, info->identity, data, PkgStream::PkgStreamType_Buffer); PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "Can not create stream for %s", info->identity.c_str()); PkgAlgorithmContext context = {{0, 0}, {data.length, 0}, 0, info->digestMethod}; int32_t ret = algorithm->Unpack(inStream.get(), PkgStreamImpl::ConvertPkgStream(output), context); @@ -698,8 +702,8 @@ int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &data, PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info); PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "Can not get algorithm for %s", info->identity.c_str()); - std::shared_ptr inStream = std::make_shared(info->identity, - data, PkgStream::PkgStreamType_Buffer); + std::shared_ptr inStream = std::make_shared( + (PkgManager::PkgManagerPtr)this, info->identity, data, PkgStream::PkgStreamType_Buffer); PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "Can not create stream for %s", info->identity.c_str()); PkgAlgorithmContext context = {{0, 0}, {0, data.length}, 0, info->digestMethod}; int32_t ret = algorithm->Pack(inStream.get(), PkgStreamImpl::ConvertPkgStream(output), context); @@ -710,4 +714,11 @@ int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &data, info->unpackedSize = context.unpackedSize; return PKG_SUCCESS; } + +void PkgManagerImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context) +{ + if (decodeProgress_ != nullptr) { + decodeProgress_(type, writeDataLen, context); + } +} } // namespace hpackage diff --git a/services/package/pkg_manager/pkg_manager_impl.h b/services/package/pkg_manager/pkg_manager_impl.h index 1233bb43..04dd1039 100644 --- a/services/package/pkg_manager/pkg_manager_impl.h +++ b/services/package/pkg_manager/pkg_manager_impl.h @@ -73,6 +73,13 @@ public: int32_t ParsePackage(StreamPtr stream, std::vector &fileIds, int32_t type) override; int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) 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); @@ -111,6 +118,7 @@ private: std::vector pkgFiles_ {}; std::map pkgStreams_ {}; std::string signVerifyKeyName_ {}; + PkgDecodeProgress decodeProgress_ { nullptr }; }; } // namespace hpackage #endif // PKG_MANAGER_IMPL_H diff --git a/services/package/pkg_manager/pkg_stream.cpp b/services/package/pkg_manager/pkg_stream.cpp index 2974d4eb..7f28de2f 100644 --- a/services/package/pkg_manager/pkg_stream.cpp +++ b/services/package/pkg_manager/pkg_stream.cpp @@ -18,6 +18,7 @@ #include #include #include "pkg_manager.h" +#include "pkg_manager_impl.h" #include "pkg_utils.h" #include "securec.h" @@ -47,6 +48,13 @@ bool PkgStreamImpl::IsRef() const return refCount_ == 0; } +void PkgStreamImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context) +{ + if (pkgManager_ != nullptr) { + pkgManager_->PostDecodeProgress(type, writeDataLen, context); + } +} + FileStream::~FileStream() { if (stream_ != nullptr) { @@ -76,6 +84,7 @@ int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t offset) fseek(stream_, offset, SEEK_SET); size_t len = fwrite(data.buffer, size, 1, stream_); PKG_CHECK(len == 1, return PKG_INVALID_STREAM, "Write buffer fail"); + PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); return PKG_SUCCESS; } @@ -143,6 +152,7 @@ int32_t MemoryMapStream::Write(const PkgBuffer &data, size_t size, size_t start) PKG_CHECK(copyLen >= size, return PKG_INVALID_STREAM, "Write fail copyLen %zu, %zu", copyLen, size); int32_t ret = memcpy_s(memMap_ + currOffset_, memSize_ - currOffset_, data.buffer, size); PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_STREAM, "Write fail"); + PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); return PKG_SUCCESS; } diff --git a/services/package/pkg_manager/pkg_stream.h b/services/package/pkg_manager/pkg_stream.h index 18f06ae7..02d21feb 100644 --- a/services/package/pkg_manager/pkg_stream.h +++ b/services/package/pkg_manager/pkg_stream.h @@ -27,7 +27,8 @@ class PkgStreamImpl; using PkgStreamPtr = PkgStreamImpl *; class PkgStreamImpl : public PkgStream { public: - explicit PkgStreamImpl(std::string fileName) : fileName_(fileName), refCount_(0) {} + explicit PkgStreamImpl(PkgManager::PkgManagerPtr pkgManager, std::string fileName) + : fileName_(fileName), refCount_(0), pkgManager_(pkgManager) {} virtual ~PkgStreamImpl() {} @@ -68,16 +69,18 @@ public: static PkgStreamPtr ConvertPkgStream(PkgManager::StreamPtr stream); protected: + void PostDecodeProgress(int type, size_t writeDataLen, const void *context); std::string fileName_; private: std::atomic_int refCount_; + PkgManager::PkgManagerPtr pkgManager_ = nullptr; }; class FileStream : public PkgStreamImpl { public: - FileStream(std::string fileName, FILE *stream, int32_t streamType) : PkgStreamImpl(fileName), - stream_(stream), fileLength_(0), streamType_(streamType) {} + FileStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName, FILE *stream, int32_t streamType) + : PkgStreamImpl(pkgManager, fileName), stream_(stream), fileLength_(0), streamType_(streamType) {} ~FileStream() override; @@ -103,8 +106,8 @@ private: class MemoryMapStream : public PkgStreamImpl { public: - MemoryMapStream(std::string fileName, const PkgBuffer &buffer, - int32_t streamType = PkgStreamType_MemoryMap) : PkgStreamImpl(fileName), memMap_(buffer.buffer), + MemoryMapStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName, const PkgBuffer &buffer, + int32_t streamType = PkgStreamType_MemoryMap) : PkgStreamImpl(pkgManager, fileName), memMap_(buffer.buffer), memSize_(buffer.length), currOffset_(0), streamType_(streamType) {} ~MemoryMapStream() override; @@ -151,8 +154,9 @@ private: class ProcessorStream : public PkgStreamImpl { public: - ProcessorStream(std::string fileName, ExtractFileProcessor processor, const void *context) - : PkgStreamImpl(fileName), processor_(processor), context_(context) {} + ProcessorStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName, + ExtractFileProcessor processor, const void *context) + : PkgStreamImpl(pkgManager, fileName), processor_(processor), context_(context) {} ~ProcessorStream() override {} @@ -168,7 +172,9 @@ public: int32_t Write(const PkgBuffer &data, size_t size, size_t start) override { PKG_CHECK(processor_ != nullptr, return PKG_INVALID_STREAM, "processor not exist"); - return processor_(data, size, start, false, context_); + int ret = processor_(data, size, start, false, context_); + PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); + return ret; } int32_t Seek(long int size, int whence) override diff --git a/services/package/pkg_package/pkg_gzipfile.h b/services/package/pkg_package/pkg_gzipfile.h index 8d14f3ac..a06dd7e5 100644 --- a/services/package/pkg_package/pkg_gzipfile.h +++ b/services/package/pkg_package/pkg_gzipfile.h @@ -56,7 +56,8 @@ private: class GZipPkgFile : public PkgFile { public: - explicit GZipPkgFile(PkgStreamPtr stream) : PkgFile(stream, PkgFile::PKG_TYPE_GZIP) + explicit GZipPkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_GZIP) { pkgInfo_.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo_.digestMethod = PKG_DIGEST_TYPE_SHA256; diff --git a/services/package/pkg_package/pkg_lz4file.h b/services/package/pkg_package/pkg_lz4file.h index 24425529..95b0658a 100644 --- a/services/package/pkg_package/pkg_lz4file.h +++ b/services/package/pkg_package/pkg_lz4file.h @@ -52,7 +52,8 @@ private: class Lz4PkgFile : public PkgFile { public: - explicit Lz4PkgFile(PkgStreamPtr stream) : PkgFile(stream, PkgFile::PKG_TYPE_LZ4) + explicit Lz4PkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_LZ4) { pkgInfo_.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo_.digestMethod = PKG_DIGEST_TYPE_SHA256; diff --git a/services/package/pkg_package/pkg_pkgfile.cpp b/services/package/pkg_package/pkg_pkgfile.cpp index 5deac71e..c02e9d8c 100644 --- a/services/package/pkg_package/pkg_pkgfile.cpp +++ b/services/package/pkg_package/pkg_pkgfile.cpp @@ -34,6 +34,8 @@ PkgFile::~PkgFile() } pkgEntryMapId_.clear(); pkgEntryMapFileName_.clear(); + PkgManager::StreamPtr tmpStream = pkgStream_; + pkgManager_->ClosePkgStream(tmpStream); } PkgEntryPtr PkgFile::AddPkgEntry(const std::string &fileName) diff --git a/services/package/pkg_package/pkg_pkgfile.h b/services/package/pkg_package/pkg_pkgfile.h index e48b2369..7a7a908d 100644 --- a/services/package/pkg_package/pkg_pkgfile.h +++ b/services/package/pkg_package/pkg_pkgfile.h @@ -85,7 +85,8 @@ public: const std::vector &digest, const std::vector &signature)>; public: - PkgFile(PkgStreamPtr stream, PkgType type) : type_(type), pkgStream_(stream) {} + PkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream, PkgType type) + : type_(type), pkgStream_(stream), pkgManager_(manager) {} virtual ~PkgFile(); @@ -136,6 +137,7 @@ protected: PkgType type_ {}; PkgStreamPtr pkgStream_ = nullptr; + PkgManager::PkgManagerPtr pkgManager_ = nullptr; uint32_t nodeId_ = 0; std::map pkgEntryMapId_ {}; std::multimap> pkgEntryMapFileName_ {}; diff --git a/services/package/pkg_package/pkg_upgradefile.cpp b/services/package/pkg_package/pkg_upgradefile.cpp index 8ca02378..85d4e1e0 100644 --- a/services/package/pkg_package/pkg_upgradefile.cpp +++ b/services/package/pkg_package/pkg_upgradefile.cpp @@ -233,6 +233,7 @@ int32_t UpgradePkgFile::Verify(size_t start, DigestAlgorithm::DigestAlgorithmPtr ret = pkgStream_->Read(buffer, offset, remainBytes, readBytes); PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to read data "); algorithm->Update(buffer, readBytes); + pkgManager_->PostDecodeProgress(POST_TYPE_VERIFY_PKG, remainBytes, nullptr); } PkgBuffer digest(GetDigestLen()); diff --git a/services/package/pkg_package/pkg_upgradefile.h b/services/package/pkg_package/pkg_upgradefile.h index 93a8ec61..e2fdbb27 100644 --- a/services/package/pkg_package/pkg_upgradefile.h +++ b/services/package/pkg_package/pkg_upgradefile.h @@ -78,8 +78,8 @@ private: class UpgradePkgFile : public PkgFile { public: - UpgradePkgFile(PkgStreamPtr stream, PkgManager::PkgInfoPtr header) : - PkgFile(stream, PkgFile::PKG_TYPE_UPGRADE) + UpgradePkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream, PkgManager::PkgInfoPtr header) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_UPGRADE) { if (header == nullptr || header->entryCount == 0) { return; @@ -92,7 +92,7 @@ public: int32_t AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr input) override; - int32_t SavePackage(size_t &offset) override; + int32_t SavePackage(size_t &signOffset) override; int32_t LoadPackage(std::vector &fileNames, VerifyFunction verify = nullptr) override; diff --git a/services/package/pkg_package/pkg_zipfile.h b/services/package/pkg_package/pkg_zipfile.h index 01ef177e..706e5715 100644 --- a/services/package/pkg_package/pkg_zipfile.h +++ b/services/package/pkg_package/pkg_zipfile.h @@ -168,7 +168,8 @@ private: class ZipPkgFile : public PkgFile { public: - explicit ZipPkgFile(PkgStreamPtr stream) : PkgFile(stream, PkgFile::PKG_TYPE_ZIP) + explicit ZipPkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_ZIP) { pkgInfo_.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo_.digestMethod = PKG_DIGEST_TYPE_SHA256; diff --git a/services/ui/surface_dev.cpp b/services/ui/surface_dev.cpp index 73de0f69..fbfb53c0 100644 --- a/services/ui/surface_dev.cpp +++ b/services/ui/surface_dev.cpp @@ -17,7 +17,7 @@ #include "updater_ui_const.h" namespace updater { -void SurfaceDev::Flip(void *buf) +void SurfaceDev::Flip(const void *buf) { if (!buf) { LOG(ERROR) << "buf is null"; diff --git a/services/ui/surface_dev.h b/services/ui/surface_dev.h index cc7c47ac..d65d1a65 100644 --- a/services/ui/surface_dev.h +++ b/services/ui/surface_dev.h @@ -25,9 +25,9 @@ public: DRM_DEVICE, }; - explicit SurfaceDev(SurfaceDev::DevType deviceType); + explicit SurfaceDev(SurfaceDev::DevType devType); ~SurfaceDev() override; - void Flip(void* buf); + void Flip(const void* buf); void GetScreenSize(int &w, int &h); private: int screenSizeW_ = 0; diff --git a/services/ui/updater_ui.cpp b/services/ui/updater_ui.cpp index 15957511..bf15c482 100644 --- a/services/ui/updater_ui.cpp +++ b/services/ui/updater_ui.cpp @@ -518,4 +518,19 @@ void DeleteView() g_sfDev = nullptr; } } + +TextLabel *GetUpdateInfoLabel() +{ + return g_updateInfoLabel; +} + +ProgressBar *GetProgressBar() +{ + return g_progressBar; +} + +void SetUpdateFlag(int updateFlag) +{ + g_updateFlag = updateFlag; +} } // namespace updater diff --git a/services/ui/updater_ui.h b/services/ui/updater_ui.h index d495aa16..621df1c3 100644 --- a/services/ui/updater_ui.h +++ b/services/ui/updater_ui.h @@ -17,6 +17,7 @@ #include #include "text_label.h" +#include "progress_bar.h" namespace updater { void DoProgress(); @@ -28,5 +29,11 @@ void UpdaterUiInit(); void ShowText(TextLabel *label, std::string text); void DeleteView(); + +TextLabel *GetUpdateInfoLabel(); + +ProgressBar *GetProgressBar(); + +void SetUpdateFlag(int updateFlag); } // namespace updater #endif /* UPDATE_UI_HOS_UPDATER_H */ diff --git a/services/updater.cpp b/services/updater.cpp index 44531918..caccbbfe 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -42,9 +42,6 @@ using updater::utils::SplitString; using updater::utils::Trim; using namespace hpackage; -extern TextLabel *g_updateInfoLabel; -extern ProgressBar *g_progressBar; - int g_percentage; int g_tmpProgressValue; int g_tmpValue; @@ -116,39 +113,7 @@ int UpdatePreProcess(PkgManager::PkgManagerPtr pkgManager, const std::string &pa return ret; } -static 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); - auto freeSpaceSize = static_cast(updaterVfs.f_bfree); - auto blockSize = static_cast(updaterVfs.f_bsize); - uint64_t totalFreeSize = freeSpaceSize * blockSize; - UPDATER_ERROR_CHECK(totalFreeSize > static_cast(info->unpackedSize), - "Can not update, free space is not enough", - ShowText(g_updateInfoLabel, "Free space is not enough"); return UPDATE_ERROR); - } else { - UPDATER_ERROR_CHECK(statvfs64("/data", &updaterVfs) >= 0, "Statvfs read /data error!", return UPDATE_ERROR); - UPDATER_ERROR_CHECK(updaterVfs.f_bfree * updaterVfs.f_bsize > (info->unpackedSize + MAX_LOG_SPACE), - "Can not update, free space is not enough", - ShowText(g_updateInfoLabel, "Free space is not enough"); return UPDATE_ERROR); - } - return UPDATE_SUCCESS; -} - -static inline void ProgressSmoothHandler() +static void ProgressSmoothHandler() { while (g_tmpProgressValue < FULL_PERCENT_PROGRESS) { int gap = FULL_PERCENT_PROGRESS - g_tmpProgressValue; @@ -157,7 +122,9 @@ static inline void ProgressSmoothHandler() if (g_tmpProgressValue >= FULL_PERCENT_PROGRESS || increase == 0) { break; } else { - g_progressBar->SetProgressValue(g_tmpProgressValue); + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(g_tmpProgressValue); + } std::this_thread::sleep_for(std::chrono::milliseconds(SHOW_FULL_PROGRESS_TIME)); } } @@ -166,23 +133,29 @@ static inline void ProgressSmoothHandler() UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath, int retryCount) { - g_progressBar->Hide(); + if (GetProgressBar() != nullptr) { + GetProgressBar()->Hide(); + } ShowUpdateFrame(true); 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); LOG(INFO) << "Verify package..."; - g_updateInfoLabel->SetText("Verify package..."); + updateInfoLabel->SetText("Verify package..."); UPDATER_ERROR_CHECK(access(packagePath.c_str(), 0) == 0, "package is not exist", - ShowText(g_updateInfoLabel, "package is not exist"); return UPDATE_CORRUPT); + ShowText(GetUpdateInfoLabel(), "package is not exist"); return UPDATE_CORRUPT); if (retryCount > 0) { LOG(INFO) << "Retry for " << retryCount << " time(s)"; } else { - UpdaterStatus ret = IsSpaceCapacitySufficient(packagePath); + UpdaterStatus ret = static_cast(IsSpaceCapacitySufficient(packagePath)); // Only handle UPATE_ERROR and UPDATE_SUCCESS here. // If it returns UPDATE_CORRUPT, which means something wrong with package manager. // Let package verify handle this. - if (ret == UPDATE_ERROR) { + if (ret == UPDATE_SPACE_NOTENOUGH) { + ShowText(GetUpdateInfoLabel(), "Free space is not enough"); + } else if (ret == UPDATE_ERROR) { return ret; } else if (ret == UPDATE_SUCCESS) { pkgManager = PkgManager::GetPackageInstance(); @@ -191,7 +164,7 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons int32_t verifyret = GetUpdatePackageInfo(pkgManager, packagePath); UPDATER_ERROR_CHECK(verifyret == PKG_SUCCESS, "Verify package Fail...", - ShowText(g_updateInfoLabel, "Verify package Fail..."); return UPDATE_CORRUPT); + 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); @@ -200,21 +173,49 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons UpdaterStatus updateRet = StartUpdaterProc(pkgManager, packagePath, retryCount, maxTemperature); if (updateRet == UPDATE_SUCCESS) { ProgressSmoothHandler(); - g_progressBar->SetProgressValue(FULL_PERCENT_PROGRESS); - g_updateInfoLabel->SetText("Update success, reboot now"); + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(FULL_PERCENT_PROGRESS); + } + updateInfoLabel->SetText("Update success, reboot now"); std::this_thread::sleep_for(std::chrono::milliseconds(SHOW_FULL_PROGRESS_TIME)); LOG(INFO)<< "update success , do reboot now"; } else { - g_updateInfoLabel->SetText("Install failed."); + updateInfoLabel->SetText("Install failed."); LOG(ERROR) << "Install package failed."; } return updateRet; } +static void HandleProgressSet(const std::vector &output) +{ + UPDATER_ERROR_CHECK(output.size() >= DEFAULT_PROCESS_NUM, "check output fail", return); + auto outputInfo = Trim(output[1]); + float frac = 0.0; + frac = std::stof(output[1]); + if (frac >= -EPSINON && frac <= EPSINON) { + return; + } else { + g_tmpProgressValue = static_cast(frac * g_percentage); + } + if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) { + g_tmpValue += g_percentage; + return; + } + g_tmpProgressValue = g_tmpProgressValue + g_tmpValue; + if (g_tmpProgressValue == 0) { + return; + } + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(g_tmpProgressValue); + } +} static void HandleChildOutput(const std::string &buffer, int32_t bufferLen, bool &retryUpdate) { UPDATER_CHECK_ONLY_RETURN(bufferLen != 0, return); + TextLabel *updateInfoLabel = GetUpdateInfoLabel(); + UPDATER_ERROR_CHECK(updateInfoLabel != nullptr, "Fail to updateInfoLabel", return); + std::string str = buffer; std::vector output = SplitString(str, ":"); UPDATER_ERROR_CHECK(output.size() >= 1, "check output fail", return); @@ -236,32 +237,17 @@ static void HandleChildOutput(const std::string &buffer, int32_t bufferLen, if (progress.size() != DEFAULT_PROCESS_NUM) { LOG(ERROR) << "show progress with wrong arguments"; } else { - g_progressBar->Show(); - g_updateInfoLabel->SetText("Start to install package."); + if (GetProgressBar() != nullptr) { + GetProgressBar()->Show(); + } + updateInfoLabel->SetText("Start to install package."); frac = std::stof(progress[0]); g_percentage = static_cast(frac * FULL_PERCENT_PROGRESS); } } else if (outputHeader == "set_progress") { - UPDATER_ERROR_CHECK(output.size() >= DEFAULT_PROCESS_NUM, "check output fail", return); - auto outputInfo = Trim(output[1]); - float frac = 0.0; - frac = std::stof(output[1]); - if (frac >= -EPSINON && frac <= EPSINON) { - return; - } else { - g_tmpProgressValue = static_cast(frac * g_percentage); - } - if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) { - g_tmpValue += g_percentage; - return; - } - g_tmpProgressValue = g_tmpProgressValue + g_tmpValue; - if (g_tmpProgressValue == 0) { - return; - } - g_progressBar->SetProgressValue(g_tmpProgressValue); + HandleProgressSet(output); } else { - LOG(WARNING) << "Child process returns unexpected message."; + LOG(DEBUG) << "Child process returns unexpected message: " << outputHeader; } } @@ -273,12 +259,11 @@ UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, const std:: UPDATER_ERROR_CHECK(pkgManager != nullptr, "Fail to GetPackageInstance", return UPDATE_CORRUPT); int pipeRead = pfd[0]; int pipeWrite = pfd[1]; - UPDATER_ERROR_CHECK(ExtractUpdaterBinary(pkgManager, UPDATER_BINARY) == 0, "Updater: cannot extract updater binary from update package.", return UPDATE_CORRUPT); g_tmpProgressValue = 0; - if (g_progressBar != nullptr) { - g_progressBar->SetProgressValue(0); + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(0); } pid_t pid = fork(); UPDATER_CHECK_ONLY_RETURN(pid >= 0, ERROR_CODE(CODE_FORK_FAIL); return UPDATE_ERROR); @@ -319,7 +304,7 @@ UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, const std:: } close(pipeWrite); // close write endpoint - char buffer[MAX_BUFFER_SIZE]; + char buffer[MAX_BUFFER_SIZE] = {0}; bool retryUpdate = false; FILE* fromChild = fdopen(pipeRead, "r"); UPDATER_ERROR_CHECK(fromChild != nullptr, "fdopen pipeRead failed", return UPDATE_ERROR); diff --git a/services/updater_binary/BUILD.gn b/services/updater_binary/BUILD.gn index 1a242386..6c2a2237 100644 --- a/services/updater_binary/BUILD.gn +++ b/services/updater_binary/BUILD.gn @@ -27,6 +27,7 @@ config("updater_config") { "//third_party/openssl/include", "//third_party/bounds_checking_function/include", "//drivers/hdf/frameworks/include/utils", + "//base/startup/init_lite/interfaces/innerkits/include", ] } diff --git a/services/updater_binary/main.cpp b/services/updater_binary/main.cpp index 6f145ce3..775c17c1 100644 --- a/services/updater_binary/main.cpp +++ b/services/updater_binary/main.cpp @@ -24,6 +24,7 @@ #include "utils.h" using namespace updater; +#ifndef UPDATER_UT int main(int argc, char **argv) { InitUpdaterLogger("UPDATER_BINARY", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); @@ -42,3 +43,4 @@ int main(int argc, char **argv) std::string packagePath = argv[0]; return ProcessUpdater(retry, pipeFd, packagePath, utils::GetCertName()); } +#endif \ No newline at end of file diff --git a/services/updater_binary/update_partitions.cpp b/services/updater_binary/update_partitions.cpp index 0f431deb..edd7fcab 100644 --- a/services/updater_binary/update_partitions.cpp +++ b/services/updater_binary/update_partitions.cpp @@ -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 diff --git a/services/updater_binary/update_processor.cpp b/services/updater_binary/update_processor.cpp index 270c8c4f..34675148 100644 --- a/services/updater_binary/update_processor.cpp +++ b/services/updater_binary/update_processor.cpp @@ -43,8 +43,8 @@ UpdaterEnv::~UpdaterEnv() void UpdaterEnv::PostMessage(const std::string &cmd, std::string content) { - if (pipeWrite_ != nullptr) { - fprintf(pipeWrite_, "%s:%s\n", cmd.c_str(), content.c_str()); + if (postMessage_ != nullptr) { + postMessage_(cmd.c_str(), content.c_str()); } } @@ -108,6 +108,7 @@ 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; @@ -212,6 +213,25 @@ int32_t UScriptInstructionSparseImageWrite::Execute(uscript::UScriptEnv &env, us DataWriter::ReleaseDataWriter(writer); return ret; } + +int ExecUpdate(PkgManager::PkgManagerPtr pkgManager, int retry, PostMessageFunction postMessage) +{ + UpdaterEnv* env = new UpdaterEnv(pkgManager, postMessage, retry); + UPDATER_ERROR_CHECK(env != nullptr, "Fail to create env", return EXIT_PARSE_SCRIPT_ERROR); + int ret = 0; + ScriptManager* scriptManager = ScriptManager::GetScriptManager(env); + UPDATER_ERROR_CHECK(scriptManager != nullptr, "Fail to create scriptManager", + ScriptManager::ReleaseScriptManager(); + delete env; + return EXIT_PARSE_SCRIPT_ERROR); + for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) { + ret = scriptManager->ExecuteScript(i); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Fail to execute script", break); + } + ScriptManager::ReleaseScriptManager(); + delete env; + return ret; +} } // updater int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath) @@ -227,35 +247,15 @@ 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); - UpdaterEnv* env = new UpdaterEnv(pkgManager, pipeWrite, retry); - UPDATER_ERROR_CHECK(env != nullptr, "Fail to create env", - fclose(pipeWrite); - pipeWrite = nullptr; - PkgManager::ReleasePackageInstance(pkgManager); - env = nullptr; - return EXIT_PARSE_SCRIPT_ERROR); - ScriptManager* scriptManager = ScriptManager::GetScriptManager(env); - UPDATER_ERROR_CHECK(scriptManager != nullptr, "Fail to create scriptManager", - fclose(pipeWrite); - pipeWrite = nullptr; - delete env; - env = nullptr; - PkgManager::ReleasePackageInstance(pkgManager); - ScriptManager::ReleaseScriptManager(); - return EXIT_PARSE_SCRIPT_ERROR); - for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) { - ret = scriptManager->ExecuteScript(i); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Fail to execute script", break); - } - - delete env; - env = nullptr; - ScriptManager::ReleaseScriptManager(); + ret = updater::ExecUpdate(pkgManager, retry, + [&pipeWrite](const char *cmd, const char *content) { + if (pipeWrite != nullptr) { + fprintf(pipeWrite, "%s:%s\n", cmd, content); + } + }); PkgManager::ReleasePackageInstance(pkgManager); #ifndef UPDATER_UT fclose(pipeWrite); diff --git a/services/updater_main.cpp b/services/updater_main.cpp index f90b73e6..c4b40a2c 100644 --- a/services/updater_main.cpp +++ b/services/updater_main.cpp @@ -49,8 +49,7 @@ using namespace updater::utils; extern TextLabel *g_logLabel; extern TextLabel *g_logResultLabel; -extern TextLabel *g_updateInfoLabel; -extern int g_updateFlag; + constexpr int DISPLAY_TIME = 1000 * 1000; constexpr struct option OPTIONS[] = { { "update_package", required_argument, nullptr, 0 }, @@ -103,20 +102,6 @@ int FactoryReset(FactoryResetMode mode, const std::string &path) return DoFactoryReset(mode, path); } - -bool IsSDCardExist(const std::string &sdcardPath) -{ - // Record system error codes. - int save_errno = errno; - struct stat st {}; - if (stat(sdcardPath.c_str(), &st) < 0) { - return false; - } else { - errno = save_errno; - return true; - } -} - UpdaterStatus UpdaterFromSdcard() { #ifndef UPDATER_UT @@ -130,7 +115,6 @@ UpdaterStatus UpdaterFromSdcard() } return UPDATE_ERROR; } - if (MountForPath(SDCARD_PATH) != 0) { int ret = mount(sdcardStr.c_str(), SDCARD_PATH.c_str(), "vfat", 0, NULL); UPDATER_WARING_CHECK(ret == 0, "MountForPath /sdcard failed!", return UPDATE_ERROR); @@ -181,7 +165,7 @@ static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, const std::v "ClearRecordPartitionOffset failed", return UPDATE_ERROR); SetRetryCountToMisc(upParams.retryCount + 1, args); } - UPDATER_CHECK_ONLY_RETURN(SetupPartitions() == 0, ShowText(g_updateInfoLabel, "Setup partitions failed"); + UPDATER_CHECK_ONLY_RETURN(SetupPartitions() == 0, ShowText(GetUpdateInfoLabel(), "Setup partitions failed"); return UPDATE_ERROR); status = DoInstallUpdaterPackage(manager, upParams.updatePackage, upParams.retryCount); if (status != UPDATE_SUCCESS) { @@ -213,7 +197,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, } else if (upParams.factoryWipeData) { LOG(INFO) << "Factory level FactoryReset begin"; status = UPDATE_SUCCESS; - g_updateFlag = 1; + SetUpdateFlag(1); ShowUpdateFrame(true); DoProgress(); UPDATER_ERROR_CHECK(FactoryReset(FACTORY_WIPE_DATA, "/data") == 0, "FactoryReset factory level failed", @@ -228,7 +212,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, } else if (upParams.userWipeData) { LOG(INFO) << "User level FactoryReset begin"; status = UPDATE_SUCCESS; - g_updateFlag = 1; + SetUpdateFlag(1); ShowUpdateFrame(true); DoProgress(); UPDATER_ERROR_CHECK(FactoryReset(USER_WIPE_DATA, "/data") == 0, "FactoryReset user level failed", @@ -291,138 +275,10 @@ static UpdaterStatus StartUpdater(PkgManager::PkgManagerPtr manager, const std:: return StartUpdaterEntry(manager, args, upParams); } -static bool IsDir(const std::string &path) -{ - struct stat st{}; - if (stat(path.c_str(), &st) < 0) { - return false; - } - return S_ISDIR(st.st_mode); -} - -static bool DeleteUpdaterPath(const std::string &path) -{ - auto pDir = std::unique_ptr(opendir(path.c_str()), closedir); - UPDATER_INFO_CHECK_NOT_RETURN(pDir != nullptr, "Can not open dir"); - - struct dirent *dp = nullptr; - if (pDir != nullptr) { - while ((dp = readdir(pDir.get())) != nullptr) { - std::string currentName(dp->d_name); - if (currentName[0] != '.' && (currentName.compare("log") != 0)) { - std::string tmpName(path); - tmpName.append("/" + currentName); - if (IsDir(tmpName)) { - DeleteUpdaterPath(tmpName); - } -#ifndef UPDATER_UT - remove(tmpName.c_str()); -#endif - } - } - } - return true; -} - -static bool ClearMisc() -{ - struct UpdateMessage cleanBoot {}; - UPDATER_ERROR_CHECK(WriteUpdaterMessage(MISC_FILE, cleanBoot) == true, - "ClearMisc clear boot message to misc failed", return false); - auto fp = std::unique_ptr(fopen(MISC_FILE.c_str(), "rb+"), fclose); - UPDATER_FILE_CHECK(fp != nullptr, "WriteVersionCode fopen failed", return false); - fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET); - off_t clearOffset = 0; - UPDATER_FILE_CHECK(fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) == 1, - "ClearMisc write misc initOffset 0 failed", return false); - - struct PartitionRecordInfo cleanPartition {}; - for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset += - sizeof(PartitionRecordInfo)) { - fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET); - UPDATER_FILE_CHECK(fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) == 1, - "ClearMisc write misc cleanPartition failed", return false); - } - return true; -} - -void PostUpdaterForSdcard(std::string &updaterLogPath, std::string &stageLogPath, std::string &errorCodePath) -{ - if (SetupPartitions() != 0) { - ShowText(g_updateInfoLabel, "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() -{ - 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); - // clear update misc partition. - UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); - if (!access(COMMAND_FILE.c_str(), 0)) { - UPDATER_ERROR_CHECK_NOT_RETURN(unlink(COMMAND_FILE.c_str()) == 0, "Delete command failed"); - } - - // delete updater tmp files - if (access(UPDATER_PATH.c_str(), 0) == 0 && access(SDCARD_CARD_PATH.c_str(), 0) != 0) { - UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(UPDATER_PATH), "DeleteUpdaterPath failed"); - } - if (!access(SDCARD_CARD_PATH.c_str(), 0)) { - UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(SDCARD_CARD_PATH), "Delete sdcard path failed"); - } - // save logs - UPDATER_ERROR_CHECK_NOT_RETURN(CopyUpdaterLogs(TMP_LOG, updaterLogPath) == true, "Copy updater log failed!"); - UPDATER_ERROR_CHECK_NOT_RETURN(CopyUpdaterLogs(TMP_ERROR_CODE_PATH, errorCodePath) == true, - "Copy error code log failed!"); - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - chmod(updaterLogPath.c_str(), mode); - chmod(stageLogPath.c_str(), mode); - chmod(errorCodePath.c_str(), mode); - STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater"; - UPDATER_ERROR_CHECK_NOT_RETURN(CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath) == true, "Copy stage log failed!"); -} - -std::vector ParseParams(int argc, char **argv) -{ - struct UpdateMessage boot {}; - // read from misc - UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(MISC_FILE, 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. - if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { - UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(COMMAND_FILE, boot) == true, - "ReadUpdaterMessage COMMAND_FILE failed!"); - } - STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; - std::vector parseParams(argv, argv + argc); - boot.update[sizeof(boot.update) - 1] = '\0'; - parseParams = utils::SplitString(boot.update, "\n"); - return parseParams; -} - int UpdaterMain(int argc, char **argv) { UpdaterStatus status = UPDATE_UNKNOWN; PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance(); - InitUpdaterLogger("UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); - SetLogLevel(INFO); - LoadFstab(); std::vector args = ParseParams(argc, argv); LOG(INFO) << "Ready to start"; diff --git a/services/updater_main.h b/services/updater_main.h index c2862850..fef8b7a8 100644 --- a/services/updater_main.h +++ b/services/updater_main.h @@ -35,10 +35,6 @@ struct UpdaterParams { int UpdaterMain(int argc, char **argv); -std::vector ParseParams(int argc, char **argv); - -void PostUpdater(); - int FactoryReset(FactoryResetMode mode, const std::string &path); UpdaterStatus UpdaterFromSdcard(); diff --git a/services/updater_utils.cpp b/services/updater_utils.cpp new file mode 100755 index 00000000..0abd3ca1 --- /dev/null +++ b/services/updater_utils.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include + +#include "applypatch/partition_record.h" +#include "flashd/flashd.h" +#include "log/log.h" +#include "misc_info/misc_info.h" +#include "package/pkg_manager.h" +#include "securec.h" +#include "updater/updater.h" +#include "updater/updater_const.h" +#include "updater_ui.h" +#include "utils.h" + +namespace updater { +using namespace hpackage; +using namespace updater::utils; +static constexpr int USER_ROOT_AUTHORITY = 0; +static constexpr int GROUP_SYS_AUTHORITY = 1000; + +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 {}; + if (stat(path.c_str(), &st) < 0) { + return false; + } + return S_ISDIR(st.st_mode); +} + +static bool DeleteUpdaterPath(const std::string &path) +{ + auto pDir = std::unique_ptr(opendir(path.c_str()), closedir); + UPDATER_INFO_CHECK_NOT_RETURN(pDir != nullptr, "Can not open dir"); + if (pDir == nullptr) { + return true; + } + struct dirent *dp = nullptr; + while ((dp = readdir(pDir.get())) != nullptr) { + std::string currentName(dp->d_name); + if (currentName[0] != '.' && (currentName.compare("log") != 0)) { + std::string tmpName(path); + tmpName.append("/" + currentName); + if (IsDir(tmpName)) { + DeleteUpdaterPath(tmpName); + } +#ifndef UPDATER_UT + remove(tmpName.c_str()); +#endif + } + } + return true; +} + +static bool ClearMisc() +{ + struct UpdateMessage cleanBoot {}; + UPDATER_ERROR_CHECK(WriteUpdaterMessage(MISC_FILE, cleanBoot) == true, + "ClearMisc clear boot message to misc failed", return false); + auto fp = std::unique_ptr(fopen(MISC_FILE.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; + UPDATER_FILE_CHECK(fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) == 1, + "ClearMisc write misc initOffset 0 failed", return false); + + struct PartitionRecordInfo cleanPartition {}; + for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset += + sizeof(PartitionRecordInfo)) { + (void)fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET); + UPDATER_FILE_CHECK(fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) == 1, + "ClearMisc write misc cleanPartition failed", return false); + } + return true; +} + +bool IsSDCardExist(const std::string &sdcardPath) +{ + // Record system error codes. + int save_errno = errno; + struct stat st {}; + if (stat(sdcardPath.c_str(), &st) < 0) { + return false; + } else { + errno = save_errno; + return true; + } +} + +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() +{ + 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); + // clear update misc partition. + UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); + if (!access(COMMAND_FILE.c_str(), 0)) { + UPDATER_ERROR_CHECK_NOT_RETURN(unlink(COMMAND_FILE.c_str()) == 0, "Delete command failed"); + } + + // delete updater tmp files + if (access(UPDATER_PATH.c_str(), 0) == 0 && access(SDCARD_CARD_PATH.c_str(), 0) != 0) { + UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(UPDATER_PATH), "DeleteUpdaterPath failed"); + } + if (!access(SDCARD_CARD_PATH.c_str(), 0)) { + UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(SDCARD_CARD_PATH), "Delete sdcard path failed"); + } + if (access(flashd::FLASHD_FILE_PATH.c_str(), 0) == 0) { + UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(flashd::FLASHD_FILE_PATH), "DeleteUpdaterPath failed"); + } + + // save logs + bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath); + UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy updater log failed!"); + ret = CopyUpdaterLogs(TMP_ERROR_CODE_PATH, errorCodePath); + UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error code log failed!"); + 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; + chmod(updaterLogPath.c_str(), mode); + chmod(stageLogPath.c_str(), mode); + chmod(errorCodePath.c_str(), mode); + STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater"; + ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath); + 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, + "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. + if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { + UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(COMMAND_FILE, boot) == true, + "ReadUpdaterMessage COMMAND_FILE failed!"); + } + STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; + std::vector parseParams(argv, argv + argc); + boot.update[sizeof(boot.update) - 1] = '\0'; + std::vector parseParams1 = utils::SplitString(boot.update, "\n"); + parseParams.insert(parseParams.end(), parseParams1.begin(), parseParams1.end()); + return parseParams; +} +} // namespace updater diff --git a/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp b/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp index 99827d82..748a8131 100644 --- a/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp +++ b/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp @@ -20,7 +20,7 @@ #include #include #include -#include "fstab_api.h" +#include "fs_manager/fs_manager.h" #include "log/log.h" using namespace updater; @@ -29,7 +29,7 @@ namespace OHOS { bool FuzzReadFstabFromFile(const uint8_t* data, size_t size) { FILE *pFile; - Fstab fstab; + Fstab *fstab = NULL; const std::string fstabFile = "ReadFstabFromFile.txt"; pFile = fopen("ReadFstabFromFile.txt", "w+"); @@ -40,9 +40,9 @@ namespace OHOS { fwrite(data, 1, size, pFile); fclose(pFile); - ReadFstabFromFile(fstabFile, fstab); + fstab = ReadFstabFromFile(fstabFile.c_str(), false); remove("ReadFstabFromFile.txt"); - + ReleaseFstab(fstab); return 0; } } diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 0d5d617e..5a7a54c8 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,6 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", + "flashd_test/flash_host_unittest.cpp", + "flashd_test/flash_service_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -91,9 +93,14 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/diffpatch/patch/blocks_patch.cpp", "//base/update/updater/services/diffpatch/patch/image_patch.cpp", "//base/update/updater/services/diffpatch/patch/update_patch.cpp", + "//base/update/updater/services/flashd/blockdevice.cpp", + "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", + "//base/update/updater/services/flashd/daemon/flashd_main.cpp", + "//base/update/updater/services/flashd/flash_service.cpp", + "//base/update/updater/services/flashd/host/host_updater.cpp", + "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", - "//base/update/updater/services/fs_manager/fstab.cpp", "//base/update/updater/services/fs_manager/mount.cpp", "//base/update/updater/services/fs_manager/partitions.cpp", "//base/update/updater/services/log/log.cpp", @@ -132,9 +139,12 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/updater_binary/update_partitions.cpp", "//base/update/updater/services/updater_binary/update_processor.cpp", "//base/update/updater/services/updater_main.cpp", + "//base/update/updater/services/updater_utils.cpp", "//base/update/updater/utils/utils.cpp", ] + include_dirs = [ + "//base/startup/init_lite/interfaces/innerkits/include", "//base/update/updater/interfaces/kits/include/", "//base/update/updater/interfaces/kits/include/package", "//base/update/updater/services/include/", @@ -154,6 +164,9 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package/pkg_package", "//base/update/updater/services/updater_binary", "//base/update/updater/services/include/fs_manager", + "//base/update/updater/services/flashd", + "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/host", "//base/update/updater/services/fs_manager", "//base/update/updater/services/applypatch", "//base/update/updater/services/diffpatch", @@ -183,8 +196,14 @@ ohos_unittest("updater_unittest") { "//drivers/peripheral/input/hal/include", "//drivers/peripheral/input/interfaces/include", "//third_party/bounds_checking_function/include", + "//developtools/hdc_standard/src", + "//developtools/hdc_standard/src/daemon", + "//developtools/hdc_standard/src/common", + "//developtools/hdc_standard/src/host", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ + "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static", "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", "//base/update/updater/services/applypatch:libapplypatch", @@ -195,11 +214,13 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/ui:libui", "//base/update/updater/utils:libutils", + "//developtools/hdc_standard:hdc_deamon_flashd", "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", + "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", @@ -216,6 +237,9 @@ ohos_unittest("updater_unittest") { defines = [ "UPDATER_UT", "BUILD_OHOS", + "HDC_DEBUG", + "HDC_SUPPORT_FLASHD", + "HARMONY_PROJECT", ] public_configs = [ ":utest_config" ] diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp new file mode 100755 index 00000000..c4e6d023 --- /dev/null +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "common/common.h" +#include "common/transfer.h" +#include "host_updater.h" +#include "serial_struct.h" +#include "unittest_comm.h" + +using namespace std; +using namespace Hdc; +using namespace testing::ext; +namespace { +static std::string TEST_PARTITION_NAME = "data"; +static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/src/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/src/image/userdata.img"; + +class FLashHostUnitTest : public testing::Test { +public: + FLashHostUnitTest() {} + ~FLashHostUnitTest() {} + + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + void TestBody() {} + +public: + int TestFlashHost(uint16_t command, const std::string &cmd) + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + hTaskInfo = task.get(); + hTaskInfo->channelId = 1; + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 0; + std::shared_ptr flashHost = std::make_shared(hTaskInfo); + flashHost->CommandDispatch(command, + const_cast(reinterpret_cast(cmd.data())), cmd.size()); + return 0; + } +}; + +HWTEST_F(FLashHostUnitTest, TestFlashHost, TestSize.Level1) +{ + FLashHostUnitTest test; + + std::string cmdParam = "update "; + cmdParam += TEST_UPDATER_PACKAGE_PATH; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_UPDATE_INIT, cmdParam)); + + cmdParam = "flash "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FLASH_INIT, cmdParam)); + + cmdParam = ""; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_CHECK, cmdParam)); + + cmdParam = ""; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_BEGIN, cmdParam)); + + cmdParam = ""; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_DATA, cmdParam)); + + cmdParam = ""; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FINISH, cmdParam)); + + cmdParam = "erase -f "; + cmdParam += TEST_PARTITION_NAME; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_ERASE, cmdParam)); + + cmdParam = "format -f "; + cmdParam += TEST_PARTITION_NAME; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); + + uint32_t percentage = 30; // 30 progress + cmdParam.resize(sizeof(percentage)); + memcpy_s(cmdParam.data(), cmdParam.size(), &percentage, sizeof(percentage)); + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_PROGRESS, cmdParam)); +} +} // namespace \ No newline at end of file diff --git a/test/unittest/flashd_test/flash_service_unittest.cpp b/test/unittest/flashd_test/flash_service_unittest.cpp new file mode 100755 index 00000000..64b37920 --- /dev/null +++ b/test/unittest/flashd_test/flash_service_unittest.cpp @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "common/common.h" +#include "common/transfer.h" +#include "daemon_updater.h" +#include "flash_service.h" +#include "flashd/flashd.h" +#include "serial_struct.h" +#include "unittest_comm.h" + +using namespace std; +using namespace flashd; +using namespace Hdc; +using namespace testing::ext; +namespace { +static std::string TEST_PARTITION_NAME = "data"; +static std::string TEST_UPDATER_PACKAGE_PATH = "/home/axw/develop/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/home/axw/develop/image/userdata.img"; + +class FLashServiceUnitTest : public testing::Test { +public: + FLashServiceUnitTest() {} + ~FLashServiceUnitTest() {} + + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + void TestBody() {} + +public: + int TestFindAllDevice() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->LoadSysDevice(); + return 0; + } + + int TestDoFlashPartition() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoFlashPartition(TEST_FLASH_IMAGE_NAME, TEST_PARTITION_NAME); + return 0; + } + + int TestDoErasePartition() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoErasePartition(TEST_PARTITION_NAME); + return 0; + } + + int TestDoFormatPartition() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoFormatPartition(TEST_PARTITION_NAME, "ext4"); + return 0; + } + + int TestFlashServiceDoPrepare(uint8_t type, const std::string &cmdParam) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + (void)flashd::DoUpdaterPrepare(flash.get(), type, cmdParam, TEST_UPDATER_PACKAGE_PATH); + return 0; + } + + int TestFlashServiceDoFlash(uint8_t type, const std::string &cmdParam) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + (void)flashd::DoUpdaterPrepare(flash.get(), type, cmdParam, TEST_UPDATER_PACKAGE_PATH); + return 0; + } + + int TestFlashServiceDoFinish(uint8_t type) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + (void)flashd::DoUpdaterFinish(flash.get(), type, ""); + return 0; + } + + int TestDaemonUpdater() + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + hTaskInfo = task.get(); + hTaskInfo->channelId = 1; + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + + // cmd: hdc updater packagename + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "update"; + transferConfig.options = "update"; + std::string localPath = TEST_UPDATER_PACKAGE_PATH; + transferConfig.fileSize = 163884012; // 163884012 file size + WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); + transferConfig.optionalName = "updater.zip"; + std::string bufString = SerialStruct::SerializeToString(transferConfig); + // 当前升级包中总的文件的大小 + const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; + std::vector buffer(sizeof(realSize) + bufString.size()); + int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); + EXPECT_EQ(0, ret); + ret = memcpy_s(buffer.data() + sizeof(realSize), buffer.size(), bufString.c_str(), bufString.size()); + EXPECT_EQ(0, ret); + hdcDamon->CommandDispatch(CMD_UPDATER_CHECK, buffer.data(), buffer.size()); + + // begin + hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); + + // data 写数据部分 + const uint32_t dataSize = 1024; // 1024 data size + HdcTransferBase::TransferPayload payloadHead {}; + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = dataSize; + payloadHead.compressSize = dataSize; + payloadHead.index = 0; + std::string bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = dataSize; + payloadHead.compressSize = dataSize; + payloadHead.index = 1; + bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + // end + hdcDamon->DoTransferFinish(); + return 0; + } + + int TestHdcDaemonFlash() + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + hTaskInfo = task.get(); + hTaskInfo->channelId = 2; // 2 channel id + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + + // cmd: hdc flash partition packagename + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "flash"; + transferConfig.options = TEST_PARTITION_NAME; + transferConfig.options += " "; + transferConfig.options += TEST_FLASH_IMAGE_NAME; + std::string localPath = TEST_FLASH_IMAGE_NAME; + transferConfig.fileSize = 1468006400; // 1468006400 file size + WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); + transferConfig.optionalName = "userdata.img"; + std::string bufString = SerialStruct::SerializeToString(transferConfig); + // 当前升级包中总的文件的大小 + const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; + std::vector buffer(sizeof(realSize) + bufString.size()); + int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); + EXPECT_EQ(0, ret); + ret = memcpy_s(buffer.data() + sizeof(realSize), buffer.size(), bufString.c_str(), bufString.size()); + EXPECT_EQ(0, ret); + hdcDamon->CommandDispatch(CMD_UPDATER_CHECK, buffer.data(), buffer.size()); + + // begin + hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); + + // data 写数据部分 + const uint32_t dataSize = 1024; // 1024 data size + HdcTransferBase::TransferPayload payloadHead {}; + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = dataSize; + payloadHead.compressSize = dataSize; + payloadHead.index = 0; + std::string bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = dataSize; + payloadHead.compressSize = dataSize; + payloadHead.index = 1; + bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + // end + hdcDamon->DoTransferFinish(); + return 0; + } + + int TestHdcDaemonErase() + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + hTaskInfo = task.get(); + hTaskInfo->channelId = 2; // 2 channel id + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + + // cmd: hdc erase partition + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "erase"; + transferConfig.options = "erase -f "; + transferConfig.options += TEST_PARTITION_NAME; + std::string bufString = SerialStruct::SerializeToString(transferConfig); + hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); + return 0; + } + + int TestHdcDaemonFormat() + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + hTaskInfo = task.get(); + hTaskInfo->channelId = 2; // 2 channel id + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + + // cmd: hdc format partition + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "format"; + transferConfig.options = "format -f "; + transferConfig.options += TEST_PARTITION_NAME; + std::string bufString = SerialStruct::SerializeToString(transferConfig); + hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); + return 0; + } +}; + +HWTEST_F(FLashServiceUnitTest, FLashServiceUnitTest, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFindAllDevice()); +} + +HWTEST_F(FLashServiceUnitTest, TestDaemonUpdater, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDaemonUpdater()); +} + +HWTEST_F(FLashServiceUnitTest, TestHdcDaemonFlash, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestHdcDaemonFlash()); +} + +HWTEST_F(FLashServiceUnitTest, TestHdcDaemonErase, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestHdcDaemonErase()); +} + +HWTEST_F(FLashServiceUnitTest, TestHdcDaemonFormat, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestHdcDaemonFormat()); +} + +HWTEST_F(FLashServiceUnitTest, TestFindAllDevice, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFindAllDevice()); +} + +HWTEST_F(FLashServiceUnitTest, TestDoFlashPartition, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDoFlashPartition()); +} + +HWTEST_F(FLashServiceUnitTest, TestDoFormatPartition, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDoFormatPartition()); +} + +HWTEST_F(FLashServiceUnitTest, TestDoErasePartition, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDoErasePartition()); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoPrepare, TestSize.Level1) +{ + FLashServiceUnitTest test; + std::string cmdParam = "update "; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_UPDATE, cmdParam)); + + cmdParam = "flash "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_FLASH, cmdParam)); + + cmdParam = "erase -f"; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_ERASE, cmdParam)); + + cmdParam = "format -f "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_FORMAT, cmdParam)); + + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_MAX, cmdParam)); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoFlash, TestSize.Level1) +{ + FLashServiceUnitTest test; + std::string cmdParam = "update "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_UPDATE, cmdParam)); + + cmdParam = "flash "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FLASH, cmdParam)); + + cmdParam = "erase -f "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_ERASE, cmdParam)); + + cmdParam = "format -f ext4 "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); + + cmdParam = "format -f f2fs "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); + + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_MAX, cmdParam)); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoFinish, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFlashServiceDoFinish(flashd::UPDATEMOD_UPDATE)); + EXPECT_EQ(0, test.TestFlashServiceDoFinish(flashd::UPDATEMOD_FLASH)); + EXPECT_EQ(0, test.TestFlashServiceDoFinish(flashd::UPDATEMOD_MAX)); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashdMain, TestSize.Level1) +{ + const char* argv1[] = {"TestFlashdMain", "-t"}; + flashd_main(sizeof(argv1) / sizeof(char*), const_cast(argv1)); + const char *argv2[] = {"TestFlashdMain", "-u", " -l5"}; + flashd_main(sizeof(argv2)/sizeof(char*), const_cast(argv2)); +} +} // namespace \ No newline at end of file diff --git a/test/unittest/mount_test/fstabapi_unittest.cpp b/test/unittest/mount_test/fstabapi_unittest.cpp index 6605ccb8..e772ece4 100755 --- a/test/unittest/mount_test/fstabapi_unittest.cpp +++ b/test/unittest/mount_test/fstabapi_unittest.cpp @@ -23,9 +23,7 @@ #include #include #include -#include -#include "fs_manager/fstab.h" -#include "fs_manager/fstab_api.h" +#include "fs_manager/fs_manager.h" #include "fs_manager/mount.h" #include "log/log.h" #include "utils.h" @@ -55,95 +53,98 @@ void FstabApiUnitTest::TearDownTestCase(void) {} HWTEST_F(FstabApiUnitTest, ReadFstabFromFile_unitest, TestSize.Level1) { - Fstab fstab; + Fstab *fstab = nullptr; const std::string fstabFile1 = "/data/fstab.updater1"; - bool ret = ReadFstabFromFile(fstabFile1, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile2 = "/data/updater/mount_unitest/ReadFstabFromFile1.fstable"; - ret = ReadFstabFromFile(fstabFile2, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile2.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile3 = "/data/updater/mount_unitest/ReadFstabFromFile2.fstable"; - ret = ReadFstabFromFile(fstabFile3, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile3.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile4 = "/data/updater/mount_unitest/ReadFstabFromFile3.fstable"; - ret = ReadFstabFromFile(fstabFile4, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile4.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile5 = "/data/updater/mount_unitest/ReadFstabFromFile4.fstable"; - ret = ReadFstabFromFile(fstabFile5, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile5.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile6 = "/data/updater/mount_unitest/ReadFstabFromFile5.fstable"; - ret = ReadFstabFromFile(fstabFile6, fstab); - EXPECT_TRUE(ret); + fstab = ReadFstabFromFile(fstabFile6.c_str(), false); + EXPECT_NE(fstab, nullptr); + ReleaseFstab(fstab); } HWTEST_F(FstabApiUnitTest, FindFstabItemForPath_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/FindFstabItemForPath1.fstable"; - Fstab fstab1; - ReadFstabFromFile(fstabFile1, fstab1); - struct FstabItem* item = nullptr; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); + FstabItem* item = nullptr; const std::string path1 = ""; - item = FindFstabItemForPath(fstab1, path1); + item = FindFstabItemForPath(*fstab, path1.c_str()); if (item == nullptr) { SUCCEED(); } const std::string path2 = "/data"; - item = FindFstabItemForPath(fstab1, path2); + item = FindFstabItemForPath(*fstab, path2.c_str()); if (item != nullptr) { SUCCEED(); } const std::string path3 = "/data2"; - item = FindFstabItemForPath(fstab1, path3); + item = FindFstabItemForPath(*fstab, path3.c_str()); if (item == nullptr) { SUCCEED(); } const std::string path4 = "/data2/test"; - item = FindFstabItemForPath(fstab1, path4); + item = FindFstabItemForPath(*fstab, path4.c_str()); if (item != nullptr) { SUCCEED(); } + ReleaseFstab(fstab); + fstab = nullptr; } HWTEST_F(FstabApiUnitTest, FindFstabItemForMountPoint_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/FindFstabItemForMountPoint1.fstable"; - Fstab fstab1; - ReadFstabFromFile(fstabFile1, fstab1); - struct FstabItem* item = nullptr; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); + FstabItem* item = nullptr; const std::string mp1 = "/data"; const std::string mp2 = "/data2"; - item = FindFstabItemForMountPoint(fstab1, mp2); + item = FindFstabItemForMountPoint(*fstab, mp2.c_str()); if (item == nullptr) { SUCCEED(); } const std::string mp3 = "/data"; - item = FindFstabItemForMountPoint(fstab1, mp3); + item = FindFstabItemForMountPoint(*fstab, mp3.c_str()); if (item != nullptr) { SUCCEED(); } + ReleaseFstab(fstab); + fstab = nullptr; } HWTEST_F(FstabApiUnitTest, GetMountFlags_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/GetMountFlags1.fstable"; - int fd = open(fstabFile1.c_str(), O_RDONLY); - if (fd < 0) { - cout << "fstabFile open failed, fd = " << fd << endl; - FAIL(); - return; - } else { - close(fd); - } - Fstab fstab1; - ReadFstabFromFile(fstabFile1, fstab1); + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); struct FstabItem* item = nullptr; const std::string mp = "/hos"; - item = FindFstabItemForMountPoint(fstab1, mp); + item = FindFstabItemForMountPoint(*fstab, mp.c_str()); if (item == nullptr) { SUCCEED(); } - std::string fsSpecificOptions; - unsigned long flags = GetMountFlags(item->mountOptions, fsSpecificOptions); + const int bufferSize = 512; + char fsSpecificOptions[bufferSize] = {0}; + unsigned long flags = GetMountFlags(item->mountOptions, fsSpecificOptions, bufferSize); EXPECT_EQ(flags, static_cast(MS_NOSUID | MS_NODEV | MS_NOATIME)); + ReleaseFstab(fstab); + fstab = nullptr; } } // namespace updater_ut diff --git a/test/unittest/mount_test/mount_unittest.cpp b/test/unittest/mount_test/mount_unittest.cpp index 80f80b8d..e008ecdb 100755 --- a/test/unittest/mount_test/mount_unittest.cpp +++ b/test/unittest/mount_test/mount_unittest.cpp @@ -25,8 +25,7 @@ #include #include #include -#include "fs_manager/fstab.h" -#include "fs_manager/fstab_api.h" +#include "fs_manager/fs_manager.h" #include "fs_manager/mount.h" #include "log/log.h" #include "utils.h" @@ -129,29 +128,6 @@ HWTEST_F(MountUnitTest, GetMountStatusForPath_unitest, TestSize.Level1) EXPECT_EQ(ret, MountStatus::MOUNT_UMOUNTED); } -HWTEST_F(MountUnitTest, GetItemForMountPoint_unitest, TestSize.Level1) -{ - const std::string fstabFile1 = "/data/updater/mount_unitest/GetItemForMountPoint1.fstable"; - LoadSpecificFstab(fstabFile1); - const std::string mountPoint1 = "/data"; - struct FstabItem * item = GetItemForMountPoint(mountPoint1); - if (item == nullptr) { - SUCCEED(); - } - const std::string fstabFile2 = "/data/updater/mount_unitest/GetItemForMountPoint2.fstable"; - LoadSpecificFstab(fstabFile2); - const std::string mountPoint2 = "/data2"; - item = GetItemForMountPoint(mountPoint2); - if (item == nullptr) { - SUCCEED(); - } - const std::string mountPoint3 = "/data"; - item = GetItemForMountPoint(mountPoint3); - if (item != nullptr) { - SUCCEED(); - } -} - HWTEST_F(MountUnitTest, SetupPartitions_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/SetupPartitions1.fstable"; diff --git a/test/unittest/package/pkg_manager_unittest.cpp b/test/unittest/package/pkg_manager_unittest.cpp index ec795918..b7143e9f 100755 --- a/test/unittest/package/pkg_manager_unittest.cpp +++ b/test/unittest/package/pkg_manager_unittest.cpp @@ -52,7 +52,8 @@ constexpr int32_t ZIP_MAX_LEVEL = 9; class TestPkgStream : public PkgStreamImpl { public: - explicit TestPkgStream(std::string fileName) : PkgStreamImpl(fileName) {} + explicit TestPkgStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName) + : PkgStreamImpl(pkgManager, fileName) {} virtual ~TestPkgStream() {} int32_t Read(const PkgBuffer &buff, size_t start, size_t size, size_t &readLen) override @@ -229,7 +230,7 @@ public: int TestPkgStreamImpl() { std::string path = TEST_PATH_TO + testCombinePkgName; - std::unique_ptr stream = std::make_unique(path); + std::unique_ptr stream = std::make_unique(pkgManager_, path); EXPECT_NE(stream, nullptr); constexpr size_t buffSize = 10; uint8_t buff[buffSize]; @@ -342,7 +343,7 @@ public: { std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - auto stream = std::make_unique(testPackageName, nullptr, 0); + auto stream = std::make_unique(pkgManager_, testPackageName, nullptr, 0); size_t start = 0; size_t readLen = 0; size_t bufferSize = 10; diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index 56272e3b..2880e5cd 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -41,7 +41,8 @@ constexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; class TestFile : public PkgFile { public: - explicit TestFile(PkgStreamPtr stream) : PkgFile(stream, PKG_TYPE_MAX) {} + explicit TestFile(PkgManager::PkgManagerPtr pkgManager, PkgStreamPtr stream) + : PkgFile(pkgManager, stream, PKG_TYPE_MAX) {} virtual ~TestFile() {} @@ -78,7 +79,7 @@ public: std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; int ret = pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); - auto file = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + auto file = std::make_unique(pkgManager_, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); constexpr uint32_t lz4NodeId = 100; auto entry = std::make_unique(file.get(), lz4NodeId); @@ -102,7 +103,8 @@ public: packagePath += testPackageName; int ret = pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); FileInfo fileInfo; - std::unique_ptr file = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + std::unique_ptr file = std::make_unique(pkgManager_, + PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); ret = file->AddEntry(&fileInfo, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_EQ(ret, 0); @@ -122,7 +124,8 @@ public: packagePath += testPackageName; pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); EXPECT_NE(stream, nullptr); - std::unique_ptr file = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + std::unique_ptr file = std::make_unique(pkgManager_, + PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); std::unique_ptr entry = std::make_unique(file.get(), zipNodeId); EXPECT_NE(entry, nullptr); @@ -154,7 +157,7 @@ public: centralDir->internalAttr = 0; centralDir->externalAttr = 0; centralDir->localHeaderOffset = 0; - int ret = memcpy_s(buff.data() + sizeof(CentralDirEntry), name.length(), name.c_str(), name.length()); + int ret = memcpy_s(buff.data() + sizeof(CentralDirEntry), name.length(), name.c_str(), name.length()); EXPECT_EQ(ret, 0); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length(), 1); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetHalfWord, offset4Words); @@ -215,7 +218,8 @@ public: sizeof(endDir), &endDir, sizeof(endDir)), 0); - std::unique_ptr zipFile = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + std::unique_ptr zipFile = std::make_unique(pkgManager_, + PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(zipFile, nullptr); std::vector components; int ret = zipFile->LoadPackage(components); diff --git a/test/unittest/updater_main_test/updater_main_unittest.cpp b/test/unittest/updater_main_test/updater_main_unittest.cpp index 5a696c0a..a3e33c78 100755 --- a/test/unittest/updater_main_test/updater_main_unittest.cpp +++ b/test/unittest/updater_main_test/updater_main_unittest.cpp @@ -24,6 +24,7 @@ #include "securec.h" #include "updater_main.h" #include "updater_ui.h" +#include "updater/updater.h" #include "utils.h" using namespace updater; @@ -131,10 +132,12 @@ HWTEST_F(UpdaterMainUnitTest, updater_main_test_004, TestSize.Level1) bool ret = WriteUpdaterMessage(MISC_FILE, boot); EXPECT_EQ(ret, true); - int lRet = 0; - int argc = 1; char **argv = new char*[MAX_ARG_SIZE]; argv[0] = new char[10]; + EXPECT_EQ(strncpy_s(argv[0], MAX_ARG_SIZE, "./main", MAX_ARG_SIZE), 0); + int argc = 1; + int lRet = UpdaterMain(argc, argv); + EXPECT_EQ(lRet, 0); EXPECT_EQ(memset_s(boot.update, sizeof(boot.update), 0, sizeof(boot.update)), 0); const std::string command3 = "--user_wipe_data"; diff --git a/test/unittest/updater_test/updater_unittest.cpp b/test/unittest/updater_test/updater_unittest.cpp index 60dced83..c11ffe0c 100755 --- a/test/unittest/updater_test/updater_unittest.cpp +++ b/test/unittest/updater_test/updater_unittest.cpp @@ -112,4 +112,11 @@ HWTEST_F(UpdaterUnitTest, updater_GetUpdatePackageInfo, TestSize.Level1) PkgManager::ReleasePackageInstance(pkgManager); EXPECT_EQ(ret, static_cast(PKG_SUCCESS)); } + +HWTEST_F(UpdaterUnitTest, updater_UpdateSdcard, TestSize.Level1) +{ + UpdaterStatus status; + status = UpdaterFromSdcard(); + EXPECT_EQ(status, UPDATE_SUCCESS); +} } // namespace updater_ut diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 07028461..2adba505 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -21,6 +21,7 @@ ohos_static_library("libutils") { "//base/update/updater/interfaces/kits/include/", "//base/update/updater/services/include/", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ "//third_party/bounds_checking_function:libsec_static" ] @@ -53,6 +54,7 @@ ohos_executable("write_updater") { "//base/update/updater/interfaces/kits/include/", "//base/update/updater/services/include/", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ diff --git a/utils/include/utils.h b/utils/include/utils.h index 9540675a..62366084 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -48,15 +48,13 @@ int64_t GetFilesFromDirectory(const std::string &path, std::vector std::vector SplitString(const std::string &str, const std::string del = " \t"); std::string Trim(const std::string &str); std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length); -void DoReboot(const std::string& rebootTarget); +void DoReboot(const std::string& rebootTarget, const std::string& extData = ""); std::string GetCertName(); bool WriteFully(int fd, const void *data, size_t size); 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); } // utils } // updater #endif // UPDATER_UTILS_H diff --git a/utils/updater_reboot.cpp b/utils/updater_reboot.cpp index 87546f3b..7c57ff61 100644 --- a/utils/updater_reboot.cpp +++ b/utils/updater_reboot.cpp @@ -32,8 +32,12 @@ int main(int argc, char **argv) std::string updaterStr = "updater"; if (!memcmp(argv[1], updaterStr.c_str(), updaterStr.length())) { updater::utils::DoReboot(argv[1]); + } else if (strcmp(argv[1], "flash") == 0) { + updater::utils::DoReboot(argv[1]); + } else if (strncmp(argv[1], "flash:", strlen("flash:")) == 0) { + updater::utils::DoReboot("flash", argv[1] + strlen("flash:")); } else { - updater::LOG(updater::INFO) << "param must be updater!"; + updater::LOG(updater::INFO) << "param must be updater/flash!"; } } return 0; diff --git a/utils/utils.cpp b/utils/utils.cpp index 84b21d20..4f2ead20 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -39,8 +39,6 @@ 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; int32_t DeleteFile(const std::string& filename) { UPDATER_ERROR_CHECK (!filename.empty(), "Invalid filename", return -1); @@ -159,33 +157,42 @@ std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length) return haxSha256; } -void DoReboot(const std::string& rebootTarget) +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 == "updater") { - std::string command = "boot_updater"; - bool ret = ReadUpdaterMessage(miscBlockDevice, msg); - UPDATER_ERROR_CHECK(ret == true, "DoReboot read misc failed", return); - if (strcmp(msg.command, command.c_str()) != 0) { - UPDATER_ERROR_CHECK(memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE) == 0, - "Failed to clear update message", return); - UPDATER_ERROR_CHECK(!memcpy_s(msg.command, MAX_COMMAND_SIZE - 1, command.c_str(), command.size()), - "Memcpy failed", return); - } - ret = WriteUpdaterMessage(miscBlockDevice, msg); - if (ret != true) { - LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error"; + 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) { + LOG(INFO) << "DoReboot: WriteUpdaterMessage empty error"; return; } sync(); } else { - UPDATER_ERROR_CHECK(!memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE), "Memset_s failed", return); - bool ret = WriteUpdaterMessage(miscBlockDevice, msg); - if (ret != true) { - LOG(INFO) << "DoReboot: WriteUpdaterMessage empty error"; + int result = 0; + bool ret = ReadUpdaterMessage(miscBlockDevice, 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"); + msg.command[maxCommandSize] = 0; + } else if (rebootTarget == "flash" && strcmp(msg.command, "flash") != 0) { + result = strcpy_s(msg.command, maxCommandSize, "boot_flash"); + msg.command[maxCommandSize] = 0; + } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) { + result = strcpy_s(msg.command, maxCommandSize, "boot_loader"); + msg.command[maxCommandSize] = 0; + } + UPDATER_ERROR_CHECK(result == 0, "strcpy failed", return); + if (!extData.empty()) { + result = strcpy_s(msg.update, MAX_UPDATE_SIZE - 1, extData.c_str()); + UPDATER_ERROR_CHECK(result == 0, "Failed to copy update", return); + msg.update[MAX_UPDATE_SIZE - 1] = 0; + } + if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { + LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error"; return; } sync(); @@ -278,74 +285,5 @@ 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) { - fwrite(buf, 1, bytes, dFp); - } - 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; -} } // utils } // namespace updater -- Gitee From 9cbb4101725713daecad2740c32c7977ada7d2a0 Mon Sep 17 00:00:00 2001 From: "411148299@qq.com" <411148299@qq.com> Date: Mon, 18 Oct 2021 16:20:56 +0800 Subject: [PATCH 3/5] fix code style Signed-off-by: 411148299@qq.com <411148299@qq.com> --- ohos.build | 1 - 1 file changed, 1 deletion(-) diff --git a/ohos.build b/ohos.build index 341a12ee..2a46178a 100644 --- a/ohos.build +++ b/ohos.build @@ -32,7 +32,6 @@ ], "test_list": [ "//base/update/updater:unittest", - "//base/update/updateservice:unittest" ] } } -- Gitee From 17e79e7387155ee9377f63550ee3f771375790a9 Mon Sep 17 00:00:00 2001 From: "411148299@qq.com" <411148299@qq.com> Date: Mon, 18 Oct 2021 16:25:37 +0800 Subject: [PATCH 4/5] fix code style Signed-off-by: 411148299@qq.com <411148299@qq.com> --- ohos.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ohos.build b/ohos.build index 2a46178a..591fd5bd 100644 --- a/ohos.build +++ b/ohos.build @@ -31,7 +31,7 @@ "//base/update/updater/services/flashd:updater_flashd" ], "test_list": [ - "//base/update/updater:unittest", + "//base/update/updater:unittest" ] } } -- Gitee From 0205a362b6409115597d0506e121732b06c118d9 Mon Sep 17 00:00:00 2001 From: "411148299@qq.com" <411148299@qq.com> Date: Tue, 19 Oct 2021 11:16:39 +0800 Subject: [PATCH 5/5] fix code style Signed-off-by: 411148299@qq.com <411148299@qq.com> --- ohos.build | 3 +-- services/BUILD.gn | 1 - services/main.cpp | 5 ----- test/unittest/BUILD.gn | 21 --------------------- 4 files changed, 1 insertion(+), 29 deletions(-) diff --git a/ohos.build b/ohos.build index 591fd5bd..9ef224ed 100644 --- a/ohos.build +++ b/ohos.build @@ -27,8 +27,7 @@ "//base/update/updateservice/interfaces/innerkits/engine:updateservicekits", "//base/update/updater/services/ui:libui", "//third_party/libdrm:libdrm", - "//third_party/e2fsprogs:e2fsprogs", - "//base/update/updater/services/flashd:updater_flashd" + "//third_party/e2fsprogs:e2fsprogs" ], "test_list": [ "//base/update/updater:unittest" diff --git a/services/BUILD.gn b/services/BUILD.gn index 945f511d..a52c4d29 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -95,7 +95,6 @@ ohos_executable("updater") { "//base/update/updater/interfaces/kits/packages:libpackageExt", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/patch:libpatch", - "//base/update/updater/services/flashd:libflashd", "//base/update/updater/services/fs_manager:libfsmanager", "//base/update/updater/services/log:libupdaterlog", "//base/update/updater/services/package:libupdaterpackage", diff --git a/services/main.cpp b/services/main.cpp index e0173eef..e492a280 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "flashd/flashd.h" #include "fs_manager/mount.h" #include "log/log.h" #include "misc_info/misc_info.h" @@ -37,7 +36,6 @@ int main(int argc, char **argv) printf("ReadUpdaterMessage COMMAND_FILE failed!\n"); } } - const int flashBootLength = 10; bool useFlash = memcmp(boot.command, "boot_flash", flashBootLength) == 0; InitUpdaterLogger(useFlash ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); @@ -46,8 +44,5 @@ int main(int argc, char **argv) STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; LOG(INFO) << "boot.command " << boot.command; LOG(INFO) << "boot.update " << boot.update; - if (useFlash) { - return flashd::flashd_main(argc, argv); - } return updater::UpdaterMain(argc, argv); } diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 5a7a54c8..14ec0f0f 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,8 +44,6 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", - "flashd_test/flash_host_unittest.cpp", - "flashd_test/flash_service_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -93,12 +91,6 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/diffpatch/patch/blocks_patch.cpp", "//base/update/updater/services/diffpatch/patch/image_patch.cpp", "//base/update/updater/services/diffpatch/patch/update_patch.cpp", - "//base/update/updater/services/flashd/blockdevice.cpp", - "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", - "//base/update/updater/services/flashd/daemon/flashd_main.cpp", - "//base/update/updater/services/flashd/flash_service.cpp", - "//base/update/updater/services/flashd/host/host_updater.cpp", - "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", "//base/update/updater/services/fs_manager/mount.cpp", @@ -164,9 +156,6 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package/pkg_package", "//base/update/updater/services/updater_binary", "//base/update/updater/services/include/fs_manager", - "//base/update/updater/services/flashd", - "//base/update/updater/services/flashd/daemon", - "//base/update/updater/services/flashd/host", "//base/update/updater/services/fs_manager", "//base/update/updater/services/applypatch", "//base/update/updater/services/diffpatch", @@ -196,11 +185,6 @@ ohos_unittest("updater_unittest") { "//drivers/peripheral/input/hal/include", "//drivers/peripheral/input/interfaces/include", "//third_party/bounds_checking_function/include", - "//developtools/hdc_standard/src", - "//developtools/hdc_standard/src/daemon", - "//developtools/hdc_standard/src/common", - "//developtools/hdc_standard/src/host", - "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static", @@ -214,13 +198,11 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/ui:libui", "//base/update/updater/utils:libutils", - "//developtools/hdc_standard:hdc_deamon_flashd", "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", - "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", @@ -237,9 +219,6 @@ ohos_unittest("updater_unittest") { defines = [ "UPDATER_UT", "BUILD_OHOS", - "HDC_DEBUG", - "HDC_SUPPORT_FLASHD", - "HARMONY_PROJECT", ] public_configs = [ ":utest_config" ] -- Gitee