once
|
Whether the current service process is a one-off process.
@@ -248,5 +255,5 @@ A single job can hold a maximum of 30 commands \(only **start**, **mkdir**, *
[startup\_bootstrap\_lite](https://gitee.com/openharmony/startup_bootstrap_lite/blob/master/README.md)
-**[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README.md)**
+**[startup\_init\_lite]**
diff --git a/README_zh.md b/README_zh.md
index 2caa463d4f9b14ffd6e2523a6aca4f94a715ec11..4efaac39973a170153a6a103c36085eadd63414c 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -1,252 +1,91 @@
-# init组件
-
-- [简介](#section469617221261)
-- [目录](#section15884114210197)
-- [约束](#section12212842173518)
-- [使用说明](#section837771600)
-- [相关仓](#section641143415335)
+# 启动子系统
## 简介
init组件负责处理从内核加载第一个用户态进程开始,到第一个应用程序启动之间的系统服务进程启动过程。启动恢复子系统除负责加载各系统关键进程之外,还需在启动的同时设置其对应权限,并在子进程启动后对指定进程实行保活(若进程意外退出要重新启动),对于特殊进程意外退出时,启动恢复子系统还要执行系统复位操作。
-## 目录
+## 系统架构
+
+**图 1** OHOS启动框架图
+
+
+## 目录
+仓目录结构如下:
```
-base/startup/init_lite/ # init组件
-├── LICENSE
-└── services
- ├── include # init组件头文件目录
- ├── src # init组件源文件目录
- └── test # init组件测试用例源文件目录
- └── unittest
-vendor
-└──huawei
- └──camera
- └──init_configs # init配置文件目录(json格式,镜像烧写后部署于/etc/init.cfg)
+base/startup/init/
+├── device_info # 提供设备信息的SA服务
+├── initsync # 同步命令(小型系统)
+├── interfaces # 对外接口
+├── scripts # 脚本(LiteOS系统使用)
+├── services
+│ ├── begetctl # 命令集合。提供服务的dump,拉起等一系列命令
+│ ├── etc # init配置文件目录(标准系统)
+│ ├── etc_lite # init配置文件目录(小型系统)
+│ ├── include # init头文件目录
+│ ├── init # init核心功能源码
+│ │ ├── adapter # 内核适配层
+│ │ ├── include # 头文件目录
+│ │ ├── lite # init核心功能源码(小型系统)
+│ │ └── standard # init核心功能源码(标准系统)
+│ ├── log # init日志部件。
+│ ├── loopevent # 事件库
+│ │ ├── include # 头文件目录
+│ │ ├── loop # 基于epoll封装的I/O多路复用接口
+│ │ ├── signal # 信号处理接口封装。提供信号的添加,handler注册等功能
+│ │ ├── socket # socket通信接口
+│ │ ├── task # 事件的抽象任务,如signal, timer等事件都要创建对应task
+│ │ ├── timer # 定时器接口
+│ │ └── utils # loopevent通用接口
+│ ├── modules # 插件化模块
+│ │ ├── bootchart # bootchart插件化源码
+│ │ ├── bootevent # bootevent插件化源码
+│ │ ├── init_hook # init提供的回调函数
+│ │ ├── reboot # reboot插件化源码
+│ │ ├── seccomp # seccomp插件化源码
+│ │ └── selinux # selinux插件化源码
+│ ├── param # 系统参数部件
+│ └── utils # init通用接口
+├── test # init组件测试用例源文件目录
+├── ueventd # ueventd服务源码
+│ ├── etc # ueventd配置文件目录
+│ ├── include # ueventd头文件目录
+│ ├── lite # ueventd核心功能源码(小型系统)
+│ └── standard # ueventd核心功能源码(标准系统)
+└── watchdog # 看门狗服务源码
```
+
## 约束
-目前支持小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300。
+目前支持小型系统设备(参考内存≥1MB),标准系统Hi3516DV300、Hi3518EV300以及RK3568等
-## 使用说明
+## 说明
-init将系统启动分为三个阶段:
+详细使用说明参考开发指南:
-“pre-init”阶段:启动系统服务之前需要先执行的操作,例如挂载文件系统、创建文件夹、修改权限等
+[启动恢复子系统概述](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-overview.md)
-“init”阶段:系统服务启动阶段
+[引导启动配置文件](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-cfg.md)
-“post-init”阶段:系统服务启动完后还需要执行的操作
+[jobs管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-jobs.md)
-上述每个阶段在配置文件init.cfg中都用一个job表示,每个job都对应一个命令集合,init通过依次执行每个job中的命令来完成系统初始化。job执行顺序:先执行“pre-init”,再执行“init”,最后执行“post-init”,所有job都集中放在init.cfg的jobs数组中。
+[插件](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-plugin.md)
-除上述jobs数组之外,init.cfg中还有一个services数组,用于存放所有需要由init进程启动的系统关键服务的服务名、可执行文件路径、权限和其他属性信息。
+[沙盒管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sandbox.md)
-配置文件init.cfg位于代码仓库/vendor/hisilicon/hispark\_aries/init\_configs/目录,部署在/etc/下,采用json格式,文件大小目前限制在100KB以内。
+[服务管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-service.md)
-配置文件格式和内容说明如下所示:
+[系统参数](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sysparam.md)
-```
-{
- "jobs" : [{
- "name" : "pre-init",
- "cmds" : [
- "mkdir /testdir",
- "chmod 0700 /testdir",
- "chown 99 99 /testdir",
- "mkdir /testdir2",
- "mount vfat /dev/mmcblk0p0 /testdir2 noexec nosuid"
- ]
- }, {
- "name" : "init",
- "cmds" : [
- "start service1",
- "start service2"
- ]
- }, {
- "name" : "post-init",
- "cmds" : []
- }
- ],
- "services" : [{
- "name" : "service1",
- "path" : "/bin/process1",
- "uid" : 1,
- "gid" : 1,
- "once" : 0,
- "importance" : 1,
- "caps" : [0, 1, 2, 5]
- }, {
- "name" : "service2",
- "path" : "/bin/process2",
- "uid" : 2,
- "gid" : 2,
- "once" : 1,
- "importance" : 0,
- "caps" : []
- }
- ]
-}
-```
+[日志管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-log.md)
-**表 1** 执行job介绍
-
-
-job名
- |
-说明
- |
-
-
-pre-init
- |
-最先执行的job,如果开发者的进程在启动之前需要首先执行一些操作(例如创建文件夹),可以把操作放到pre-init中先执行。
- |
-
-init
- |
-中间执行的job,例如服务启动。
- |
-
-post-init
- |
-最后被执行的job,如果开发者的进程在启动完成之后需要有一些处理(如驱动初始化后再挂载设备),可以把这类操作放到该job执行。
- |
-
-
-
-
-单个job最多支持30条命令(当前仅支持start/mkdir/chmod/chown/mount/loadcfg),命令名称和后面的参数(参数长度≤128字节)之间有且只能有一个空格。
-
-**表 2** 命令集说明
-
-
-命令
- |
-命令格式和示例
- |
-说明
- |
-
-
-mkdir
- |
-mkdir 目标文件夹
-如:mkdir /storage/myDirectory
- |
-创建文件夹命令,mkdir和目标文件夹之间有且只能有一个空格。
- |
-
-chmod
- |
-chmod 权限 目标
-如:chmod 0600 /storage/myFile.txt
-chmod 0750 /storage/myDir
- |
-修改权限命令,chmod 权限 目标 之间间隔有且仅有一个空格,权限必须为0xxx格式。
- |
-
-chown
- |
-chown uid gid 目标
-如:chown 900 800 /storage/myDir
-chown 100 100 /storage/myFile.txt
- |
-修改属组命令,chown uid gid 目标 之间间隔有且仅有一个空格。
- |
-
-mount
- |
-mount fileSystemType src dst flags data
-如:mount vfat /dev/mmcblk0 /sdc rw,umask=000
-mount jffs2 /dev/mtdblock3 /storage nosuid
- |
-挂载命令,各参数之间有且仅有一个空格。flags当前仅支持nodev、noexec、nosuid、rdonly,data为可选字段。
- |
-
-start
- |
-start serviceName
-如:start foundation
-start shell
- |
-启动服务命令,start后面跟着service名称,该service名称必须能够在services数组中找到。
- |
-
-loadcfg
- |
-loadcfg filePath
-如:loadcfg /patch/fstab.cfg
- |
-加载其他cfg文件命令。后面跟着的目标文件大小不得超过50KB,且目前仅支持加载/patch/fstab.cfg,其他文件路径和文件名均不支持。/patch/fstab.cfg文件的每一行都是一条命令,命令类型和格式必须符合本表格描述,命令条数不得超过20条。
- |
-
-
-
-
-**表 3** service字段说明
-
-
-字段名
- |
-说明
- |
-
-
-name
- |
-当前服务的名称,须确保非空且长度≤32字节。
- |
-
-path
- |
-当前服务的可执行文件全路径和参数,数组形式。须确保第一个数组元素为可执行文件路径、数组元素个数≤20、每个元素为字符串形式以及每个字符串长度≤64字节。
- |
-
-uid
- |
-当前服务进程的uid值。
- |
-
-gid
- |
-当前服务进程的gid值。
- |
-
-once
- |
-当前服务进程是否为一次性进程:
-1:一次性进程,当该进程退出时,init不会重新启动该服务进程
-0 : 常驻进程,当该进程退出时,init收到SIGCHLD信号并重新启动该服务进程;
-注意:对于常驻进程,若在4分钟之内连续退出5次,第5次退出时init将不会再重新拉起该服务进程。
- |
-
-importance
- |
-当前服务进程是否为关键系统进程:
-0:非关键系统进程,当该进程退出时,init不会将系统复位重启;
-1:关键系统进程,当该进程退出时,init将系统复位重启。
- |
-
-caps
- |
-当前服务所需的capability值,根据安全子系统已支持的capability,评估所需的capability,遵循最小权限原则配置(当前最多可配置100个值)。
- |
-
-
-
+[组件化启动](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sub-unit.md)
## 相关仓
-[启动恢复子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%90%AF%E5%8A%A8%E6%81%A2%E5%A4%8D%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
-
-[startup\_syspara\_lite](https://gitee.com/openharmony/startup_syspara_lite/blob/master/README_zh.md)
-
-[startup\_appspawn\_lite](https://gitee.com/openharmony/startup_appspawn_lite/blob/master/README_zh.md)
-
-[startup\_bootstrap\_lite](https://gitee.com/openharmony/startup_bootstrap_lite/blob/master/README_zh.md)
+**[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite)**
-**[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)**
+[startup\_appspawn](https://gitee.com/openharmony/startup_appspawn)
+[startup\_bootstrap\_lite](https://gitee.com/openharmony/startup_bootstrap_lite)
diff --git a/begetd.gni b/begetd.gni
new file mode 100644
index 0000000000000000000000000000000000000000..6d6cd9eeef71ce33344e231f9372cc055038eee6
--- /dev/null
+++ b/begetd.gni
@@ -0,0 +1,79 @@
+# 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.
+
+init_innerkits_path = "//base/startup/init/interfaces/innerkits"
+
+declare_args() {
+ enable_ohos_startup_init_feature_watcher = true
+ enable_ohos_startup_init_feature_deviceinfo = true
+
+ # only for test
+ param_test = true
+ param_base_log = false
+ init_feature_ab_partition = false
+
+ # init begetctl support liteos
+ init_feature_begetctl_liteos = false
+
+ # only support mbedtls for hash
+ init_lite_use_thirdparty_mbedtls = true
+ init_lite_use_posix_file_api = false
+ config_ohos_startup_init_lite_data_path = "/"
+
+ # enable process_priority for ohos_lite
+ init_feature_enable_lite_process_priority = false
+
+ # config memory size for liteos-m
+ init_lite_memory_size = 5120
+
+ startup_init_feature_decode_group_file = false
+
+ startup_init_test_performance = true
+
+ # log display control
+ init_lite_no_log = false
+
+ startup_init_with_param_base = false
+ if (!use_musl) {
+ startup_init_with_param_base = true
+ startup_init_feature_decode_group_file = true
+ }
+
+ #deps appspawn_client
+ init_appspawn_client_module = true
+
+ # begetutil extension module
+ init_begetutil_extra_modules = ""
+ init_extra_static_modules = ""
+
+ init_use_encaps = false
+
+ # erofs overlay feature switch
+ init_startup_feature_erofs_overlay = false
+
+ # system call wrap switch
+ init_startup_feature_system_call_switch = false
+
+ #deps param_watcher xcollie
+ init_paramwatcher_hicollie_enable = true
+ if (defined(global_parts_info) &&
+ !defined(global_parts_info.hiviewdfx_hicollie)) {
+ init_paramwatcher_hicollie_enable = false
+ }
+
+ # seccomp privilege
+ init_feature_seccomp_privilege = false
+
+ # group_type support system
+ init_feature_group_type = true
+}
diff --git a/bundle.json b/bundle.json
new file mode 100755
index 0000000000000000000000000000000000000000..28ceb22cd16f02c18c7539a6a7b671a373e05398
--- /dev/null
+++ b/bundle.json
@@ -0,0 +1,198 @@
+{
+ "name": "@ohos/init",
+ "description": "ohos init process",
+ "homePage": "https://gitee.com/openharmony",
+ "version": "4.0.2",
+ "license": "Apache License 2.0",
+ "repository": "https://gitee.com/openharmony/startup_init",
+ "supplier": "Organization: OpenHarmony",
+ "publishAs": "code-segment",
+ "segment": {
+ "destPath": "base/startup/init"
+ },
+ "dirs": {},
+ "scripts": {},
+ "component": {
+ "name": "init",
+ "subsystem": "startup",
+ "syscap": [
+ "SystemCapability.Startup.SystemInfo",
+ "SystemCapability.Startup.SystemInfo.Lite",
+ "SystemCapability.Base"
+ ],
+ "features": [
+ "init_feature_begetctl_liteos",
+ "init_lite_use_posix_file_api",
+ "init_feature_ab_partition",
+ "init_feature_loader",
+ "init_lite_use_thirdparty_mbedtls",
+ "init_appspawn_client_module",
+ "init_feature_seccomp_privilege"
+ ],
+ "adapted_system_type": [
+ "mini",
+ "small",
+ "standard"
+ ],
+ "rom": "3.9MB",
+ "ram": "8356KB",
+ "hisysevent_config": [
+ "//base/startup/init/services/modules/sysevent/init_events.yaml"
+ ],
+ "deps": {
+ "components": [
+ "appspawn",
+ "safwk",
+ "c_utils",
+ "napi",
+ "ipc",
+ "config_policy",
+ "hilog",
+ "hilog_lite",
+ "samgr",
+ "access_token",
+ "hvb",
+ "hisysevent",
+ "hiprofiler",
+ "bounds_checking_function",
+ "bundle_framework",
+ "selinux",
+ "selinux_adapter",
+ "storage_service",
+ "mbedtls",
+ "zlib",
+ "cJSON",
+ "mksh",
+ "libunwind",
+ "toybox",
+ "hicollie",
+ "drivers_interface_partitionslot"
+ ],
+ "third_party": [
+ "mksh",
+ "e2fsprogs",
+ "f2fs-tools"
+ ]
+ },
+ "build": {
+ "group_type": {
+ "base_group": [
+ ],
+ "fwk_group": [
+ "//base/startup/init:init_fwk_group"
+ ],
+ "service_group": [
+ "//base/startup/init:init_service_group"
+ ]
+ },
+ "inner_kits": [
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/include/",
+ "header_files": [
+ "init_socket.h",
+ "init_file.h",
+ "init_reboot.h",
+ "loop_event.h",
+ "hookmgr.h",
+ "service_control.h",
+ "beget_ext.h",
+ "systemcapability.h",
+ "syspara/parameter.h",
+ "syspara/parameters.h",
+ "syspara/param_wrapper.h",
+ "syspara/sysparam_errno.h",
+ "syspara/sysversion.h",
+ "param/init_param.h"
+ ]
+ },
+ "name": "//base/startup/init/interfaces/innerkits:libbegetutil"
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/include/",
+ "header_files": []
+ },
+ "name": "//base/startup/init/interfaces/innerkits:libbegetutil_static",
+ "visibility": [ "updater" ]
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/include/fs_manager/",
+ "header_files": [
+ "fs_manager.h"
+ ]
+ },
+ "name": "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static"
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/include/fs_manager/",
+ "header_files": []
+ },
+ "name": "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static_real",
+ "visibility": [ "updater" ]
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/include/",
+ "header_files": [
+ "service_watcher.h",
+ "syspara/parameter.h",
+ "syspara/sysparam_errno.h"
+ ]
+ },
+ "name": "//base/startup/init/interfaces/innerkits:libbeget_proxy"
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits",
+ "header_files": [
+ "init_module_engine/include/init_module_engine.h"
+ ]
+ },
+ "name": "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine"
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/seccomp/include/",
+ "header_files": [
+ "seccomp_policy.h"
+ ]
+ },
+ "name": "//base/startup/init/interfaces/innerkits/seccomp:seccomp"
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/interfaces/innerkits/include/param",
+ "header_files": [
+ ]
+ },
+ "name": "//base/startup/init/interfaces/innerkits/zh_extral_dir:export_headers_lib"
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/services/param/base",
+ "header_files": []
+ },
+ "name": "//base/startup/init/services/param/base:parameterbase",
+ "visibility": [ "musl" ]
+ },
+ {
+ "header": {
+ "header_base": "//base/startup/init/services/param/base",
+ "header_files": []
+ },
+ "name": "//base/startup/init/services/param/base:parameterbase_noflto",
+ "visibility": [ "musl" ]
+ },
+ {
+ "name": "//base/startup/init/interfaces/kits/syscap_ts:syscap_ts"
+ }
+ ],
+ "test": [
+ "//base/startup/init/test:testgroup"
+ ]
+ }
+ }
+}
diff --git a/device_info/BUILD.gn b/device_info/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..e61fa2a7bb64726e4f960fbb505e9110c2a5cd26
--- /dev/null
+++ b/device_info/BUILD.gn
@@ -0,0 +1,92 @@
+# 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("//base/startup/init/begetd.gni")
+if (!defined(ohos_lite)) {
+ import("//build/ohos.gni")
+ import("//build/ohos/sa_profile/sa_profile.gni")
+
+ ohos_sa_profile("device_info_profile") {
+ sources = [ "etc/3902.json" ]
+ part_name = "init"
+ }
+
+ ohos_prebuilt_etc("device_info.cfg") {
+ source = "etc/deviceinfoservice.cfg"
+ relative_install_dir = "init"
+ part_name = "init"
+ subsystem_name = "startup"
+ }
+
+ ohos_shared_library("deviceinfoservice") {
+ sources = [
+ "//base/startup/init/interfaces/innerkits/syspara/param_comm.c",
+ "device_info_stub.cpp",
+ ]
+
+ branch_protector_ret = "pac_ret"
+ sanitize = {
+ cfi = true
+ cfi_cross_dso = true
+ debug = false
+ }
+
+ shlib_type = "sa"
+
+ include_dirs = [
+ ".",
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/include/param",
+ "//base/startup/init/interfaces/innerkits/include/syspara",
+ "//base/startup/init/interfaces/innerkits/syspara",
+ "//base/startup/init/interfaces/hals",
+ ]
+ defines = [
+ "INIT_AGENT",
+ "_GNU_SOURCE",
+ "USE_MBEDTLS",
+ "DINFO_TAG=\"DeviceInfoService\"",
+ ]
+ deps = [
+ "//base/startup/init/interfaces/innerkits:libbegetutil",
+ "//base/startup/init/services/log:agent_log",
+ "//base/startup/init/services/modules/udid:libudidcomm",
+ "//base/startup/init/services/utils:libinit_utils",
+ ]
+
+ external_deps = [
+ "bounds_checking_function:libsec_shared",
+ "c_utils:utils",
+ "ipc:ipc_single",
+ "safwk:system_ability_fwk",
+ "samgr:samgr_proxy",
+ ]
+ if (defined(global_parts_info) &&
+ defined(global_parts_info.security_access_token)) {
+ external_deps += [ "access_token:libaccesstoken_sdk" ]
+ defines += [ "INIT_SUPPORT_ACCESS_TOKEN" ]
+ }
+ install_images = [ "system" ]
+ part_name = "init"
+ subsystem_name = "startup"
+ }
+}
+
+group("device_info_group") {
+ if (!defined(ohos_lite) && enable_ohos_startup_init_feature_deviceinfo) {
+ deps = [
+ ":device_info.cfg",
+ ":device_info_profile",
+ ":deviceinfoservice",
+ ]
+ }
+}
diff --git a/device_info/device_info.cpp b/device_info/device_info.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..89947e2928058b86545a8fd9667e73c2d03297d9
--- /dev/null
+++ b/device_info/device_info.cpp
@@ -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.
+ */
+#include "beget_ext.h"
+#ifdef PARAM_FEATURE_DEVICEINFO
+#include "device_info_kits.h"
+#endif
+#include "param_comm.h"
+#include "securec.h"
+#include "sysparam_errno.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+int AclGetDevUdid(char *udid, int size)
+{
+ if (udid == nullptr || size < UDID_LEN) {
+ return SYSPARAM_INVALID_INPUT;
+ }
+ (void)memset_s(udid, size, 0, size);
+#ifdef PARAM_FEATURE_DEVICEINFO
+ std::string result = {};
+ OHOS::device_info::DeviceInfoKits &instance = OHOS::device_info::DeviceInfoKits::GetInstance();
+ int ret = instance.GetUdid(result);
+ if (ret == 0) {
+ ret = strcpy_s(udid, size, result.c_str());
+ }
+#else
+ int ret = GetDevUdid_(udid, size);
+#endif
+ return ret;
+}
+
+const char *AclGetSerial(void)
+{
+ static char serialNumber[MAX_SERIAL_LEN] = {0};
+#ifdef PARAM_FEATURE_DEVICEINFO
+ std::string result = {};
+ OHOS::device_info::DeviceInfoKits &instance = OHOS::device_info::DeviceInfoKits::GetInstance();
+ int ret = instance.GetSerialID(result);
+ if (ret == 0) {
+ ret = strcpy_s(serialNumber, sizeof(serialNumber), result.c_str());
+ BEGET_ERROR_CHECK(ret == 0, return nullptr, "Failed to copy");
+ }
+#else
+ const char *tmpSerial = GetSerial_();
+ if (tmpSerial != nullptr) {
+ int ret = strcpy_s(serialNumber, sizeof(serialNumber), tmpSerial);
+ BEGET_ERROR_CHECK(ret == 0, return nullptr, "Failed to copy");
+ }
+#endif
+ return serialNumber;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
diff --git a/device_info/device_info_kits.cpp b/device_info/device_info_kits.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..61c1424c8ff0a169756e92315f0ed226a5f4d658
--- /dev/null
+++ b/device_info/device_info_kits.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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 "device_info_kits.h"
+
+#include "beget_ext.h"
+#include "device_info_proxy.h"
+#include "device_info_load.h"
+#include "idevice_info.h"
+#include "if_system_ability_manager.h"
+#include "iservice_registry.h"
+#include "system_ability_definition.h"
+#include "securec.h"
+#include "sysparam_errno.h"
+
+namespace OHOS {
+namespace device_info {
+
+static const int DEVINFO_SAID = 3902;
+static const int DEVICEINFO_LOAD_SA_TIMEOUT_MS = 5000;
+
+DeviceInfoKits::DeviceInfoKits() {}
+
+DeviceInfoKits::~DeviceInfoKits() {}
+
+DeviceInfoKits &DeviceInfoKits::GetInstance()
+{
+ return DelayedRefSingleton::GetInstance();
+}
+
+void DeviceInfoKits::LoadDeviceInfoSa(std::unique_lock &lock)
+{
+ DINFO_LOGV("deviceInfoService_ is %d", deviceInfoService_ == nullptr);
+ if (deviceInfoService_ != nullptr) {
+ return;
+ }
+ auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ DINFO_CHECK(sam != nullptr, return, "GetSystemAbilityManager return null");
+
+ auto remoteObject = sam->CheckSystemAbility(DEVINFO_SAID);
+ if (remoteObject) {
+ DINFO_LOGV("deviceinfo sa is already loaded");
+ deviceInfoService_ = iface_cast(remoteObject);
+ return;
+ }
+ sptr deviceInfoLoad = new (std::nothrow) DeviceInfoLoad();
+ DINFO_CHECK(deviceInfoLoad != nullptr, return, "new deviceInfoLoad fail.");
+
+ int32_t ret = sam->LoadSystemAbility(SYSPARAM_DEVICE_SERVICE_ID, deviceInfoLoad);
+ DINFO_CHECK(ret == ERR_OK, return, "LoadSystemAbility deviceinfo sa failed");
+
+ if (deathRecipient_ == nullptr) {
+ deathRecipient_ = new DeathRecipient();
+ }
+
+ // wait_for release lock and block until time out(60s) or match the condition with notice
+ auto waitStatus = deviceInfoLoadCon_.wait_for(lock, std::chrono::milliseconds(DEVICEINFO_LOAD_SA_TIMEOUT_MS),
+ [this]() { return deviceInfoService_ != nullptr; });
+ if (!waitStatus || deviceInfoService_ == nullptr) {
+ // time out or loadcallback fail
+ DINFO_LOGE("tokensync load sa timeout");
+ return;
+ }
+
+ // for dead
+ auto object = deviceInfoService_->AsObject();
+ if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
+ DINFO_LOGE("Failed to add death recipient");
+ }
+}
+
+sptr DeviceInfoKits::GetService(std::unique_lock &lock)
+{
+ LoadDeviceInfoSa(lock);
+ return deviceInfoService_;
+}
+
+void DeviceInfoKits::FinishStartSASuccess(const sptr &remoteObject)
+{
+ DINFO_LOGI("get deviceinfo sa success.");
+ // get lock which wait_for release and send a notice so that wait_for can out of block
+ std::unique_lock lock(lock_);
+ deviceInfoService_ = iface_cast(remoteObject);
+ deviceInfoLoadCon_.notify_one();
+}
+
+void DeviceInfoKits::FinishStartSAFailed()
+{
+ DINFO_LOGI("Get deviceinfo sa failed.");
+ // get lock which wait_for release and send a notice
+ std::unique_lock lock(lock_);
+ deviceInfoService_ = nullptr;
+ deviceInfoLoadCon_.notify_one();
+}
+
+int32_t DeviceInfoKits::GetUdid(std::string& result)
+{
+ std::unique_lock lock(lock_);
+ static std::optional> resultPair;
+ if (resultPair.has_value()) {
+ int32_t ret = resultPair->first;
+ result = resultPair->second;
+ DINFO_LOGV("GetUdid from resultPair ret = %d", ret);
+ return ret;
+ }
+ auto deviceService = GetService(lock);
+ DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager");
+ int ret = deviceService->GetUdid(result);
+ DINFO_LOGV("GetSerialID from remote ret = %d", ret);
+ if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) {
+ resultPair = std::make_optional(std::make_pair(ret, result));
+ }
+ return ret;
+}
+
+int32_t DeviceInfoKits::GetSerialID(std::string& result)
+{
+ std::unique_lock lock(lock_);
+ static std::optional> resultPair;
+ if (resultPair.has_value()) {
+ int32_t ret = resultPair->first;
+ result = resultPair->second;
+ DINFO_LOGV("GetSerialID from resultPair ret = %d", ret);
+ return ret;
+ }
+ auto deviceService = GetService(lock);
+ DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager");
+ int ret = deviceService->GetSerialID(result);
+ DINFO_LOGV("GetSerialID from remote ret = %d", ret);
+ if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) {
+ resultPair = std::make_optional(std::make_pair(ret, result));
+ }
+ return ret;
+}
+
+void DeviceInfoKits::DeathRecipient::OnRemoteDied(const wptr &remote)
+{
+ DelayedRefSingleton::GetInstance().ResetService(remote);
+}
+
+void DeviceInfoKits::ResetService(const wptr &remote)
+{
+ DINFO_LOGI("Remote is dead, reset service instance");
+ std::lock_guard lock(lock_);
+ if (deviceInfoService_ != nullptr) {
+ sptr object = deviceInfoService_->AsObject();
+ if ((object != nullptr) && (remote == object)) {
+ object->RemoveDeathRecipient(deathRecipient_);
+ deviceInfoService_ = nullptr;
+ }
+ }
+}
+} // namespace device_info
+} // namespace OHOS
diff --git a/device_info/device_info_kits.h b/device_info/device_info_kits.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f3e71cc1b13a851e506af1a9b2536361dc3b91d
--- /dev/null
+++ b/device_info/device_info_kits.h
@@ -0,0 +1,60 @@
+/*
+ * 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 OHOS_SYSTEM_DEVICE_ID_KITS_S
+#define OHOS_SYSTEM_DEVICE_ID_KITS_S
+#include
+#include "idevice_info.h"
+#include "singleton.h"
+#include "beget_ext.h"
+
+namespace OHOS {
+namespace device_info {
+class INIT_LOCAL_API DeviceInfoKits final : public DelayedRefSingleton {
+ DECLARE_DELAYED_REF_SINGLETON(DeviceInfoKits);
+public:
+ DISALLOW_COPY_AND_MOVE(DeviceInfoKits);
+
+ static DeviceInfoKits &GetInstance();
+ int32_t GetUdid(std::string& result);
+ int32_t GetSerialID(std::string& result);
+
+ void FinishStartSASuccess(const sptr &remoteObject);
+ void FinishStartSAFailed();
+ void ResetService(const wptr &remote);
+private:
+ // For death event procession
+ class DeathRecipient final : public IRemoteObject::DeathRecipient {
+ public:
+ DeathRecipient(void) = default;
+ ~DeathRecipient(void) final = default;
+ DISALLOW_COPY_AND_MOVE(DeathRecipient);
+ void OnRemoteDied(const wptr &remote) final;
+ };
+ sptr GetDeathRecipient(void)
+ {
+ return deathRecipient_;
+ }
+
+ void LoadDeviceInfoSa(std::unique_lock &lock);
+ sptr GetService(std::unique_lock &lock);
+ std::mutex lock_;
+ std::condition_variable deviceInfoLoadCon_;
+ sptr deathRecipient_ {};
+ sptr deviceInfoService_ {};
+};
+} // namespace device_info
+} // namespace OHOS
+#endif // OHOS_SYSTEM_DEVICE_ID_KITS_S
diff --git a/device_info/device_info_load.cpp b/device_info/device_info_load.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e392ebe8571bcd3e34d9d730a3209db0ecb2c183
--- /dev/null
+++ b/device_info/device_info_load.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "device_info_load.h"
+
+#include "device_info_kits.h"
+#include "system_ability_definition.h"
+
+namespace OHOS {
+namespace device_info {
+DeviceInfoLoad::DeviceInfoLoad()
+{
+}
+
+void DeviceInfoLoad::OnLoadSystemAbilitySuccess(int32_t systemAbilityId,
+ const sptr& remoteObject)
+{
+ DINFO_CHECK(systemAbilityId == SYSPARAM_DEVICE_SERVICE_ID, return,
+ "start systemabilityId is not deviceinfo! %d", systemAbilityId);
+ if (remoteObject == nullptr) {
+ DINFO_LOGI("OnLoadSystemAbilitySuccess but remote is null %d", systemAbilityId);
+ DeviceInfoKits::GetInstance().FinishStartSAFailed();
+ return;
+ }
+
+ DINFO_LOGI("OnLoadSystemAbilitySuccess start systemAbilityId: %d success!", systemAbilityId);
+ DeviceInfoKits::GetInstance().FinishStartSASuccess(remoteObject);
+}
+
+void DeviceInfoLoad::OnLoadSystemAbilityFail(int32_t systemAbilityId)
+{
+ DINFO_CHECK(systemAbilityId == SYSPARAM_DEVICE_SERVICE_ID, return,
+ "start systemabilityId is not deviceinfo! %d", systemAbilityId);
+
+ DINFO_LOGI("OnLoadSystemAbilityFail systemAbilityId: %d failed.", systemAbilityId);
+
+ DeviceInfoKits::GetInstance().FinishStartSAFailed();
+}
+} // namespace device_info
+} // namespace OHOS
diff --git a/device_info/device_info_load.h b/device_info/device_info_load.h
new file mode 100644
index 0000000000000000000000000000000000000000..9cf74126f2188715e887902dc1531112aae5f176
--- /dev/null
+++ b/device_info/device_info_load.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEVICE_INFO_LOAD_H
+#define DEVICE_INFO_LOAD_H
+
+#include "system_ability_load_callback_stub.h"
+#include "idevice_info.h"
+
+namespace OHOS {
+namespace device_info {
+class DeviceInfoLoad : public SystemAbilityLoadCallbackStub {
+public:
+ explicit DeviceInfoLoad();
+
+ void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr& remoteObject);
+ void OnLoadSystemAbilityFail(int32_t systemAbilityId);
+private:
+};
+} // namespace device_info
+} // namespace OHOS
+#endif // DEVICE_INFO_LOAD_H
diff --git a/device_info/device_info_proxy.cpp b/device_info/device_info_proxy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ffe8acf4e801b9101efae47ba8ea14356783fbc3
--- /dev/null
+++ b/device_info/device_info_proxy.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "device_info_proxy.h"
+
+#include "beget_ext.h"
+#include "idevice_info.h"
+#include "parcel.h"
+#include "string_ex.h"
+#include "sysparam_errno.h"
+#include "deviceinfoservice_ipc_interface_code.h"
+
+namespace OHOS {
+namespace device_info {
+int32_t DeviceInfoProxy::DeviceInfoSendRequest(uint32_t code,
+ MessageParcel &data, MessageParcel &reply, MessageOption &option)
+{
+#ifdef STARTUP_INIT_TEST
+ int ret = 0;
+#else
+ int ret = SYSPARAM_SYSTEM_ERROR;
+#endif
+ auto remote = Remote();
+ if (remote != nullptr) {
+ ret = remote->SendRequest(code, data, reply, option);
+ }
+ return ret;
+}
+
+int32_t DeviceInfoProxy::GetUdid(std::string& result)
+{
+ MessageParcel data;
+ MessageParcel reply;
+ MessageOption option { MessageOption::TF_SYNC };
+ data.WriteInterfaceToken(DeviceInfoProxy::GetDescriptor());
+ int32_t ret = DeviceInfoSendRequest(static_cast (DeviceInfoInterfaceCode::COMMAND_GET_UDID),
+ data, reply, option);
+ DINFO_CHECK(ret == ERR_NONE, return ret, "getUdid failed, error code is %d", ret);
+ result = Str16ToStr8(reply.ReadString16());
+ return ERR_OK;
+}
+
+int32_t DeviceInfoProxy::GetSerialID(std::string& result)
+{
+ MessageParcel data;
+ MessageParcel reply;
+ MessageOption option { MessageOption::TF_SYNC };
+
+ data.WriteInterfaceToken(DeviceInfoProxy::GetDescriptor());
+ int32_t ret = DeviceInfoSendRequest(static_cast (DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID),
+ data, reply, option);
+ DINFO_CHECK(ret == ERR_NONE, return ret, "GetSerial failed, error code is %d", ret);
+ result = Str16ToStr8(reply.ReadString16());
+ return ERR_OK;
+}
+} // namespace device_info
+} // namespace OHOS
diff --git a/device_info/device_info_proxy.h b/device_info/device_info_proxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca7acef3ff8617c715170c426b27660b3f134348
--- /dev/null
+++ b/device_info/device_info_proxy.h
@@ -0,0 +1,39 @@
+/*
+ * 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 OHOS_SYSTEM_DEVICEIDPROXY_H
+#define OHOS_SYSTEM_DEVICEIDPROXY_H
+
+#include "iremote_proxy.h"
+#include "idevice_info.h"
+#include "beget_ext.h"
+
+namespace OHOS {
+namespace device_info {
+class INIT_LOCAL_API DeviceInfoProxy : public IRemoteProxy {
+public:
+ explicit DeviceInfoProxy(const sptr &impl) : IRemoteProxy(impl) {}
+ virtual ~DeviceInfoProxy() {}
+
+ int32_t GetUdid(std::string& result) override;
+ int32_t GetSerialID(std::string& result) override;
+private:
+ int32_t DeviceInfoSendRequest(uint32_t code,
+ MessageParcel &data, MessageParcel &reply, MessageOption &option);
+ static inline BrokerDelegator delegator_;
+};
+} // namespace system
+} // namespace OHOS
+#endif // OHOS_SYSTEM_DEVICEIDPROXY_H
\ No newline at end of file
diff --git a/device_info/device_info_stub.cpp b/device_info/device_info_stub.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fbe51d262bb67bbe27b6d896a25733395fdbab40
--- /dev/null
+++ b/device_info/device_info_stub.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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 "device_info_stub.h"
+
+#include
+#include
+
+#include "beget_ext.h"
+#include "idevice_info.h"
+#include "ipc_skeleton.h"
+#ifdef INIT_SUPPORT_ACCESS_TOKEN
+#include "accesstoken_kit.h"
+#endif
+#include "parcel.h"
+#include "string_ex.h"
+#include "if_system_ability_manager.h"
+#include "iservice_registry.h"
+#include "system_ability_definition.h"
+#include "param_comm.h"
+#include "parameter.h"
+#include "sysparam_errno.h"
+#include "init_utils.h"
+#include "deviceinfoservice_ipc_interface_code.h"
+
+namespace OHOS {
+#ifdef INIT_SUPPORT_ACCESS_TOKEN
+using namespace Security;
+using namespace Security::AccessToken;
+#endif
+
+namespace device_info {
+REGISTER_SYSTEM_ABILITY_BY_ID(DeviceInfoService, SYSPARAM_DEVICE_SERVICE_ID, true)
+
+static std::mutex g_lock;
+static struct timespec g_lastTime;
+#ifndef STARTUP_INIT_TEST
+static const int DEVICE_INFO_EXIT_TIMEOUT_S = 60;
+#else
+static const int DEVICE_INFO_EXIT_TIMEOUT_S = 3;
+#endif
+static const int DEVICE_INFO_EXIT_WAITTIMES = 12;
+
+static int UnloadDeviceInfoSa(void)
+{
+ {
+ std::unique_lock lock(g_lock);
+ struct timespec currTimer = {0};
+ (void)clock_gettime(CLOCK_MONOTONIC, &currTimer);
+ if (IntervalTime(&g_lastTime, &currTimer) < DEVICE_INFO_EXIT_TIMEOUT_S) {
+ return 0;
+ }
+ }
+ DINFO_LOGI("DeviceInfoService::UnloadDeviceInfoSa");
+ auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ DINFO_CHECK(sam != nullptr, return 0, "GetSystemAbilityManager return null");
+
+ int32_t ret = sam->UnloadSystemAbility(SYSPARAM_DEVICE_SERVICE_ID);
+ DINFO_CHECK(ret == ERR_OK, return 0, "UnLoadSystemAbility deviceinfo sa failed");
+ return 1;
+}
+
+int32_t DeviceInfoStub::OnRemoteRequest(uint32_t code,
+ MessageParcel &data, MessageParcel &reply, MessageOption &option)
+{
+ std::u16string myDescriptor = IDeviceInfo::GetDescriptor();
+ std::u16string remoteDescriptor = data.ReadInterfaceToken();
+ DINFO_CHECK(myDescriptor == remoteDescriptor, return ERR_FAIL, "Invalid remoteDescriptor");
+
+ {
+ std::unique_lock lock(g_lock);
+ (void)clock_gettime(CLOCK_MONOTONIC, &g_lastTime);
+ }
+
+ int ret = ERR_FAIL;
+ switch (code) {
+ case static_cast(DeviceInfoInterfaceCode::COMMAND_GET_UDID): {
+ if (!CheckPermission(data, "ohos.permission.sec.ACCESS_UDID")) {
+ return SYSPARAM_PERMISSION_DENIED;
+ }
+ char localDeviceInfo[UDID_LEN] = {0};
+ ret = GetDevUdid_(localDeviceInfo, UDID_LEN);
+ DINFO_CHECK(ret == 0, break, "Failed to get dev udid");
+ reply.WriteString16(Str8ToStr16(localDeviceInfo));
+ break;
+ }
+ case static_cast(DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID): {
+ if (!CheckPermission(data, "ohos.permission.sec.ACCESS_UDID")) {
+ return SYSPARAM_PERMISSION_DENIED;
+ }
+ const char *serialNumber = GetSerial_();
+ DINFO_CHECK(serialNumber != nullptr, break, "Failed to get serialNumber");
+ reply.WriteString16(Str8ToStr16(serialNumber));
+ ret = ERR_NONE;
+ break;
+ }
+ default: {
+ return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
+ }
+ }
+ return ret;
+}
+
+bool DeviceInfoStub::CheckPermission(MessageParcel &data, const std::string &permission)
+{
+#ifdef INIT_SUPPORT_ACCESS_TOKEN
+ AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
+ int32_t result = TypePermissionState::PERMISSION_GRANTED;
+ int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(callerToken);
+ if (tokenType == TOKEN_INVALID) {
+ DINFO_LOGE("AccessToken type:%d, permission:%d denied!", tokenType, callerToken);
+ return false;
+ } else {
+ result = AccessTokenKit::VerifyAccessToken(callerToken, permission);
+ }
+ if (result == TypePermissionState::PERMISSION_DENIED) {
+ DINFO_LOGE("permission:%s denied!", permission.c_str());
+ return false;
+ }
+ return true;
+#else
+ DINFO_LOGE("CheckPermission is not supported");
+ return false;
+#endif
+}
+
+int32_t DeviceInfoService::GetUdid(std::string& result)
+{
+ return 0;
+}
+int32_t DeviceInfoService::GetSerialID(std::string& result)
+{
+ return 0;
+}
+
+void DeviceInfoService::OnStart(void)
+{
+ int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_INFO);
+ SetInitLogLevel((InitLogLevel)level);
+ DINFO_LOGI("DeviceInfoService OnStart");
+ bool res = Publish(this);
+ if (!res) {
+ DINFO_LOGE("DeviceInfoService Publish failed");
+ }
+ threadStarted_ = true;
+ std::thread([this] {this->ThreadForUnloadSa();}).detach();
+ return;
+}
+
+void DeviceInfoService::OnStop(void)
+{
+ threadStarted_ = false;
+ DINFO_LOGI("DeviceInfoService OnStop");
+}
+
+int DeviceInfoService::Dump(int fd, const std::vector& args)
+{
+ (void)args;
+ DINFO_LOGI("DeviceInfoService Dump");
+ DINFO_CHECK(fd >= 0, return -1, "Invalid fd for dump %d", fd);
+ return dprintf(fd, "%s\n", "No information to dump for this service");
+}
+
+void DeviceInfoService::ThreadForUnloadSa(void)
+{
+ while (1) {
+ std::this_thread::sleep_for(std::chrono::seconds(DEVICE_INFO_EXIT_TIMEOUT_S / DEVICE_INFO_EXIT_WAITTIMES));
+ if (!threadStarted_) {
+ break;
+ }
+ if (UnloadDeviceInfoSa() == 1) {
+ break;
+ }
+ }
+}
+} // namespace device_info
+} // namespace OHOS
diff --git a/device_info/device_info_stub.h b/device_info/device_info_stub.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0d7a9b93fe64fe1aad6af35108ba94c4e84b816
--- /dev/null
+++ b/device_info/device_info_stub.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 OHOS_SYSTEM_DEVICEIDSTUB_H
+#define OHOS_SYSTEM_DEVICEIDSTUB_H
+
+#include
+#include
+#include "iremote_stub.h"
+#include "idevice_info.h"
+#include "system_ability.h"
+
+namespace OHOS {
+namespace device_info {
+class DeviceInfoStub : public IRemoteStub {
+public:
+ explicit DeviceInfoStub(bool serialInvokeFlag = true)
+ : IRemoteStub(serialInvokeFlag), serialInvokeFlag_(serialInvokeFlag) {}
+ int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply,
+ MessageOption &option) override;
+ bool serialInvokeFlag_ = { true };
+private:
+ bool CheckPermission(MessageParcel &data, const std::string &permission);
+};
+
+class DeviceInfoService : public SystemAbility, public DeviceInfoStub {
+public:
+ DECLARE_SYSTEM_ABILITY(DeviceInfoService);
+ DISALLOW_COPY_AND_MOVE(DeviceInfoService);
+ explicit DeviceInfoService(int32_t systemAbilityId, bool runOnCreate = true)
+ : SystemAbility(systemAbilityId, runOnCreate)
+ {
+ }
+ ~DeviceInfoService() override {}
+ int32_t GetUdid(std::string& result) override;
+ int32_t GetSerialID(std::string& result) override;
+protected:
+ void OnStart(void) override;
+ void OnStop(void) override;
+ int Dump(int fd, const std::vector& args) override;
+ void ThreadForUnloadSa(void);
+ std::atomic_bool threadStarted_ { false };
+};
+} // namespace device_info
+} // namespace OHOS
+#endif // OHOS_SYSTEM_DEVICEIDSTUB_H
\ No newline at end of file
diff --git a/device_info/deviceinfoservice_ipc_interface_code.h b/device_info/deviceinfoservice_ipc_interface_code.h
new file mode 100644
index 0000000000000000000000000000000000000000..f97c9464bd0e8ce3fdb6ab2f6b6f8186542afce9
--- /dev/null
+++ b/device_info/deviceinfoservice_ipc_interface_code.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEVICEINFOSERVICE_IPC_INTERFACE_CODE_H
+#define DEVICEINFOSERVICE_IPC_INTERFACE_CODE_H
+
+/* SAID: 3902 */
+namespace OHOS {
+namespace device_info {
+enum class DeviceInfoInterfaceCode {
+ COMMAND_GET_UDID = 1,
+ COMMAND_GET_SERIAL_ID = 2,
+};
+} // namespace device_info
+} // namespace OHOS
+
+#endif // DEVICEINFOSERVICE_IPC_INTERFACE_CODE_H
diff --git a/device_info/etc/3902.json b/device_info/etc/3902.json
new file mode 100644
index 0000000000000000000000000000000000000000..4eeaf8415761e9d1eb09dbb2f935ec20e7bc6279
--- /dev/null
+++ b/device_info/etc/3902.json
@@ -0,0 +1,12 @@
+{
+ "process": "deviceinfoservice",
+ "systemability": [
+ {
+ "name": 3902,
+ "libpath": "libdeviceinfoservice.z.so",
+ "run-on-create": true,
+ "distributed": false,
+ "dump_level": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/device_info/etc/deviceinfoservice.cfg b/device_info/etc/deviceinfoservice.cfg
new file mode 100755
index 0000000000000000000000000000000000000000..6a4ca239c2e9d5c74e8d9f510671ef55b03c2111
--- /dev/null
+++ b/device_info/etc/deviceinfoservice.cfg
@@ -0,0 +1,12 @@
+{
+ "services" : [{
+ "name" : "deviceinfoservice",
+ "path" : ["/system/bin/sa_main", "/system/profile/deviceinfoservice.json"],
+ "uid" : "deviceinfo",
+ "gid" : ["deviceinfo", "shell"],
+ "ondemand" : true,
+ "secon" : "u:r:deviceinfoservice:s0",
+ "recycle-strategy": "low-memory"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/device_info/idevice_info.h b/device_info/idevice_info.h
new file mode 100644
index 0000000000000000000000000000000000000000..14791c93a2768bc6334ebd178fb33ce99832004d
--- /dev/null
+++ b/device_info/idevice_info.h
@@ -0,0 +1,60 @@
+/*
+ * 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 OHOS_SYSTEM_IDEVICEID_H
+#define OHOS_SYSTEM_IDEVICEID_H
+
+#include
+#include "beget_ext.h"
+#include "iremote_broker.h"
+#include "iremote_proxy.h"
+
+namespace OHOS {
+namespace device_info {
+class IDeviceInfo : public OHOS::IRemoteBroker {
+public:
+ DECLARE_INTERFACE_DESCRIPTOR(u"ohos.system.IDeviceInfo");
+
+ virtual int32_t GetUdid(std::string& result) = 0;
+ virtual int32_t GetSerialID(std::string& result) = 0;
+
+ static constexpr int ERR_FAIL = -1;
+};
+} // namespace device_info
+} // namespace OHOS
+
+#ifndef DINFO_DOMAIN
+#define DINFO_DOMAIN (BASE_DOMAIN + 8)
+#endif
+
+#ifndef DINFO_TAG
+#define DINFO_TAG "DeviceInfoKits"
+#endif
+
+#define DINFO_LOGI(fmt, ...) STARTUP_LOGI(DINFO_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__)
+#define DINFO_LOGE(fmt, ...) STARTUP_LOGE(DINFO_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__)
+#define DINFO_LOGV(fmt, ...) STARTUP_LOGV(DINFO_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__)
+
+#define DINFO_CHECK(ret, exper, ...) \
+ if (!(ret)) { \
+ DINFO_LOGE(__VA_ARGS__); \
+ exper; \
+ }
+#define DINFO_ONLY_CHECK(ret, exper, ...) \
+ if (!(ret)) { \
+ exper; \
+ }
+
+#endif // OHOS_SYSTEM_IDEVICEID_H
\ No newline at end of file
diff --git "a/figures/init\347\263\273\347\273\237\346\236\266\346\236\204.png" "b/figures/init\347\263\273\347\273\237\346\236\266\346\236\204.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b6a2c9eb76c086e8c48a9e60facd4936305b18fb
Binary files /dev/null and "b/figures/init\347\263\273\347\273\237\346\236\266\346\236\204.png" differ
diff --git a/initsync/BUILD.gn b/initsync/BUILD.gn
index 773ee36c3b2b0c823a13ee80eacaf9e066726188..f6e0f22fb5ec03eed33bbc1c36db0350886e5db1 100644
--- a/initsync/BUILD.gn
+++ b/initsync/BUILD.gn
@@ -14,30 +14,29 @@
import("//build/lite/config/component/lite_component.gni")
lite_component("initsync") {
- features = [ "//base/startup/init_lite/initsync:libinitsync_shared" ]
+ features = [ "//base/startup/init/initsync:libinitsync_shared" ]
}
shared_library("libinitsync_shared") {
sources = [ "src/init_sync.c" ]
- cflags = [ "-Wall" ]
include_dirs = [
- "//base/startup/init_lite/initsync/include",
- "//base/startup/init_lite/interfaces/kits",
- "//base/startup/init_lite/services/log",
- ]
- public_deps = [
- "//base/startup/init_lite/services/log:init_log",
- "//third_party/bounds_checking_function:libsec_shared",
+ "//base/startup/init/initsync/include",
+ "//base/startup/init/interfaces/kits/syscap",
+ "//base/startup/init/services/log",
+ "//base/startup/init/interfaces/innerkits/include",
]
+ public_deps = [ "//base/startup/init/services/log:init_log" ]
+
+ external_deps = [ "bounds_checking_function:libsec_shared" ]
}
static_library("libinitsync_static") {
sources = [ "src/init_sync.c" ]
- cflags = [ "-Wall" ]
include_dirs = [
- "//base/startup/init_lite/initsync/include",
- "//base/startup/init_lite/interfaces/kits",
- "//base/startup/init_lite/services/log",
+ "//base/startup/init/initsync/include",
+ "//base/startup/init/interfaces/kits/syscap",
+ "//base/startup/init/services/log",
+ "//base/startup/init/interfaces/innerkits/include",
]
- public_deps = [ "//third_party/bounds_checking_function:libsec_static" ]
+ external_deps = [ "bounds_checking_function:libsec_static" ]
}
diff --git a/initsync/include/init_stage.h b/initsync/include/init_stage.h
index 7d5b7848b38e6f62cf6c707df5b8d38911d18800..e1c3b8723067f047de87693b0ee467e18a30fb94 100644
--- a/initsync/include/init_stage.h
+++ b/initsync/include/init_stage.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-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
@@ -51,7 +51,7 @@ typedef struct {
#define QUICKSTART_NODE "/dev/quickstart"
-/* Simple sample Useage:
+/* Simple sample Usage:
* INIT PROCESS
* SystemInitStage(QS_STAGE1)----(1)fork----> key APP
* |(2) |(3)
diff --git a/initsync/src/init_sync.c b/initsync/src/init_sync.c
index 73ba642b7afcddc341e892277ae9104ad60a97ad..e58145b6cc970367cc6c35704bf1b3e99065544b 100644
--- a/initsync/src/init_sync.c
+++ b/initsync/src/init_sync.c
@@ -18,14 +18,13 @@
#include
#include
#include
-#include
-#include
#include
#include
#include
#include
#include
#include "init_log.h"
+
static int SendCmd(int cmd, unsigned long arg)
{
int fd = open(QUICKSTART_NODE, O_RDONLY);
diff --git a/interfaces/hals/hal_sys_param.h b/interfaces/hals/hal_sys_param.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2aea3097d035c5d34b7aa541a250ab46e74a8b2
--- /dev/null
+++ b/interfaces/hals/hal_sys_param.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HAL_SYS_PARAM_H
+#define HAL_SYS_PARAM_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+const char* HalGetDeviceType(void);
+const char* HalGetManufacture(void);
+const char* HalGetBrand(void);
+const char* HalGetMarketName(void);
+const char* HalGetProductSeries(void);
+const char* HalGetProductModel(void);
+const char* HalGetSoftwareModel(void);
+const char* HalGetHardwareModel(void);
+const char* HalGetHardwareProfile(void);
+const char* HalGetSerial(void);
+const char* HalGetBootloaderVersion(void);
+const char* HalGetAbiList(void);
+const char* HalGetDisplayVersion(void);
+const char* HalGetIncrementalVersion(void);
+const char* HalGetBuildType(void);
+const char* HalGetBuildUser(void);
+const char* HalGetBuildHost(void);
+const char* HalGetBuildTime(void);
+int HalGetFirstApiVersion(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif // HAL_SYS_PARAM_H
\ No newline at end of file
diff --git a/interfaces/hals/hal_token.h b/interfaces/hals/hal_token.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ed1f1ca7b6c5d33d80413199d2d92a44d01bb1d
--- /dev/null
+++ b/interfaces/hals/hal_token.h
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2020-2022 Huawei Device Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef HAL_TOKEN_H
+#define HAL_TOKEN_H
+
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+#define KIT_FRAMEWORK_UID_MAX 1000
+
+/**
+ * @brief Read token value from device.
+ *
+ * @param token the result token value, if read successfully.
+ * @param len length of the token.
+ * @returns 0 if success and get the update area token,
+ * 1 if success and get the pre-made token,
+ * -1 if failed,
+ * -2 if no pre-made token.
+ */
+int HalReadToken(char *token, unsigned int len);
+
+/**
+ * @brief Write token value to device.
+ *
+ * @param token the token to write.
+ * @param len length of the token.
+ * @returns 0 if success, otherwise -1.
+ */
+int HalWriteToken(const char *token, unsigned int len);
+
+/**
+ * @brief Get AcKey value from device.
+ *
+ * @param acKey the result acKey, if get successfully.
+ * @param len length of the acKey.
+ * @returns 0 if success, otherwise -1.
+ */
+int HalGetAcKey(char *acKey, unsigned int len);
+
+/**
+ * @brief Get ProdId value from device.
+ *
+ * @param productId product IDs to be populated with.
+ * @param len length of the productId.
+ * @returns 0 if success, otherwise -1.
+ */
+int HalGetProdId(char *productId, unsigned int len);
+
+/**
+ * @brief Get ProdKey value from device.
+ *
+ * @param productKey The productKey value
+ * @param len The productKey len.
+ * @returns 0 if success, otherwise -1.
+ */
+int HalGetProdKey(char *productKey, unsigned int len);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif // HAL_TOKEN_H
diff --git a/interfaces/hals/utils/sys_param/BUILD.gn b/interfaces/hals/utils/sys_param/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..73e041b58442a860991c8fdb16ce7d7dbd50f2dd
--- /dev/null
+++ b/interfaces/hals/utils/sys_param/BUILD.gn
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2020-2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("hal_sys_param") {
+ sources = [ "hal_sys_param.c" ]
+ include_dirs = [ "//base/startup/init/interfaces/hals" ]
+ defines = [
+ "INCREMENTAL_VERSION=\"${ohos_version}\"",
+ "BUILD_TYPE=\"${ohos_build_type}\"",
+ "BUILD_USER=\"${ohos_build_user}\"",
+ "BUILD_TIME=\"${ohos_build_time}\"",
+ "BUILD_HOST=\"${ohos_build_host}\"",
+ "BUILD_ROOTHASH=\"${ohos_build_roothash}\"",
+ ]
+}
diff --git a/interfaces/hals/utils/sys_param/hal_sys_param.c b/interfaces/hals/utils/sys_param/hal_sys_param.c
new file mode 100644
index 0000000000000000000000000000000000000000..a373b0b217e16e24bc3e9a161b92e220e7191ef1
--- /dev/null
+++ b/interfaces/hals/utils/sys_param/hal_sys_param.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "hal_sys_param.h"
+
+static const char OHOS_ABI_LIST[] = {"****"};
+static const char OHOS_BOOTLOADER_VERSION[] = {"bootloader"};
+static const char OHOS_BRAND[] = {"****"};
+static const char OHOS_DEVICE_TYPE[] = {"****"};
+static const char OHOS_DISPLAY_VERSION[] = {"OpenHarmony 3.1"};
+static const char OHOS_HARDWARE_MODEL[] = {"****"};
+static const char OHOS_HARDWARE_PROFILE[] = {"aout:true,display:true"};
+static const char OHOS_MARKET_NAME[] = {"****"};
+static const char OHOS_MANUFACTURE[] = {"****"};
+static const char OHOS_PRODUCT_MODEL[] = {"****"};
+static const char OHOS_PRODUCT_SERIES[] = {"****"};
+static const char OHOS_SERIAL[] = {"****"}; // provided by OEM.
+static const char OHOS_SOFTWARE_MODEL[] = {"****"};
+static const int OHOS_FIRST_API_VERSION = 1;
+
+__attribute__((weak)) const char* HalGetDeviceType(void)
+{
+ return OHOS_DEVICE_TYPE;
+}
+
+__attribute__((weak)) const char* HalGetManufacture(void)
+{
+ return OHOS_MANUFACTURE;
+}
+
+__attribute__((weak)) const char* HalGetBrand(void)
+{
+ return OHOS_BRAND;
+}
+
+__attribute__((weak)) const char* HalGetMarketName(void)
+{
+ return OHOS_MARKET_NAME;
+}
+
+__attribute__((weak)) const char* HalGetProductSeries(void)
+{
+ return OHOS_PRODUCT_SERIES;
+}
+
+__attribute__((weak)) const char* HalGetProductModel(void)
+{
+ return OHOS_PRODUCT_MODEL;
+}
+
+__attribute__((weak)) const char* HalGetSoftwareModel(void)
+{
+ return OHOS_SOFTWARE_MODEL;
+}
+
+__attribute__((weak)) const char* HalGetHardwareModel(void)
+{
+ return OHOS_HARDWARE_MODEL;
+}
+
+__attribute__((weak)) const char* HalGetHardwareProfile(void)
+{
+ return OHOS_HARDWARE_PROFILE;
+}
+
+__attribute__((weak)) const char* HalGetSerial(void)
+{
+ return OHOS_SERIAL;
+}
+
+__attribute__((weak)) const char* HalGetBootloaderVersion(void)
+{
+ return OHOS_BOOTLOADER_VERSION;
+}
+
+__attribute__((weak)) const char* HalGetAbiList(void)
+{
+ return OHOS_ABI_LIST;
+}
+
+__attribute__((weak)) const char* HalGetDisplayVersion(void)
+{
+ return OHOS_DISPLAY_VERSION;
+}
+
+__attribute__((weak)) const char* HalGetIncrementalVersion(void)
+{
+ return INCREMENTAL_VERSION;
+}
+
+__attribute__((weak)) const char* HalGetBuildType(void)
+{
+ return BUILD_TYPE;
+}
+
+__attribute__((weak)) const char* HalGetBuildUser(void)
+{
+ return BUILD_USER;
+}
+
+__attribute__((weak)) const char* HalGetBuildHost(void)
+{
+ return BUILD_HOST;
+}
+
+__attribute__((weak)) const char* HalGetBuildTime(void)
+{
+ return BUILD_TIME;
+}
+
+__attribute__((weak)) int HalGetFirstApiVersion(void)
+{
+ return OHOS_FIRST_API_VERSION;
+}
\ No newline at end of file
diff --git a/interfaces/hals/utils/token/BUILD.gn b/interfaces/hals/utils/token/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..95c818a966a659e44809cc8652149e8d8de69e54
--- /dev/null
+++ b/interfaces/hals/utils/token/BUILD.gn
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2020-2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("static_hal_token") {
+ sources = [ "hal_token.c" ]
+ include_dirs = [
+ "//base/startup/init/interfaces/hals",
+ "//commonlibrary/utils_lite/include",
+ ]
+ deps = []
+}
diff --git a/interfaces/hals/utils/token/hal_token.c b/interfaces/hals/utils/token/hal_token.c
new file mode 100644
index 0000000000000000000000000000000000000000..99512a5edeb639db0ec76b24a01ddc61b4aedd3b
--- /dev/null
+++ b/interfaces/hals/utils/token/hal_token.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hal_token.h"
+#include "ohos_errno.h"
+#include "ohos_types.h"
+
+__attribute__((weak)) static int OEMReadToken(char* token, unsigned int len)
+{
+ // OEM need add here, read token from device
+ (void)(token);
+ (void)(len);
+ return EC_SUCCESS;
+}
+
+__attribute__((weak)) static int OEMWriteToken(const char* token, unsigned int len)
+{
+ // OEM need add here, write token to device
+ (void)(token);
+ (void)(len);
+ return EC_SUCCESS;
+}
+
+__attribute__((weak)) static int OEMGetAcKey(char* acKey, unsigned int len)
+{
+ // OEM need add here, get AcKey
+ (void)(acKey);
+ (void)(len);
+ return EC_SUCCESS;
+}
+
+__attribute__((weak)) static int OEMGetProdId(char* productId, unsigned int len)
+{
+ // OEM need add here, get ProdId
+ (void)(productId);
+ (void)(len);
+ return EC_SUCCESS;
+}
+
+__attribute__((weak)) static int OEMGetProdKey(char* productKey, unsigned int len)
+{
+ // OEM need add here, get ProdKey
+ (void)(productKey);
+ (void)(len);
+ return EC_SUCCESS;
+}
+
+__attribute__((weak)) int HalReadToken(char* token, unsigned int len)
+{
+ if (token == NULL) {
+ return EC_FAILURE;
+ }
+
+ return OEMReadToken(token, len);
+}
+
+__attribute__((weak)) int HalWriteToken(const char* token, unsigned int len)
+{
+ if (token == NULL) {
+ return EC_FAILURE;
+ }
+
+ return OEMWriteToken(token, len);
+}
+
+__attribute__((weak)) int HalGetAcKey(char* acKey, unsigned int len)
+{
+ if (acKey == NULL) {
+ return EC_FAILURE;
+ }
+
+ return OEMGetAcKey(acKey, len);
+}
+
+__attribute__((weak)) int HalGetProdId(char* productId, unsigned int len)
+{
+ if (productId == NULL) {
+ return EC_FAILURE;
+ }
+
+ return OEMGetProdId(productId, len);
+}
+
+__attribute__((weak)) int HalGetProdKey(char* productKey, unsigned int len)
+{
+ if (productKey == NULL) {
+ return EC_FAILURE;
+ }
+
+ return OEMGetProdKey(productKey, len);
+}
\ No newline at end of file
diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn
new file mode 100755
index 0000000000000000000000000000000000000000..b9eddfd1140acbcb5a78ee0a356436d196b62812
--- /dev/null
+++ b/interfaces/innerkits/BUILD.gn
@@ -0,0 +1,346 @@
+# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//base/startup/init/begetd.gni")
+if (!defined(ohos_lite) || init_feature_begetctl_liteos) {
+ syspara_sources = [
+ "syscap/init_syscap.c",
+ "syspara/param_comm.c",
+ "syspara/parameter.c",
+ "syspara/sysversion.c",
+ ]
+}
+
+config("exported_header_files") {
+ visibility = [ ":*" ]
+ include_dirs = [
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/include/syspara",
+ "//base/startup/init/interfaces/innerkits/include/token",
+ "//base/startup/init/interfaces/innerkits/include/param",
+ ]
+}
+
+include_common = [
+ "./include",
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/include/param",
+ "//base/startup/init/interfaces/innerkits/fd_holder",
+ "//base/startup/init/interfaces/innerkits/include/syspara",
+ "//base/startup/init/interfaces/hals",
+ "//base/startup/init/interfaces/innerkits/syspara",
+ "//base/startup/init/services/param/include",
+]
+
+if (defined(ohos_lite)) {
+ import("//build/lite/config/component/lite_component.gni")
+ import("//build/lite/ndk/ndk.gni")
+
+ if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") {
+ shared_library("libbegetutil") {
+ cflags = [ "-fPIC" ]
+ defines = [
+ "_GNU_SOURCE",
+ "OHOS_LITE",
+ ]
+ sources = []
+ include_dirs = include_common
+ include_dirs += [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits" ]
+ public_configs = [ ":exported_header_files" ]
+ deps = [
+ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
+ "//base/startup/init/services/modules/init_hook:inithook",
+ ]
+ deps += [
+ "//base/startup/init/services/log:init_log",
+ "//base/startup/init/services/modules/udid:libudidcomm",
+ "//base/startup/init/services/utils:libinit_utils",
+ ]
+ external_deps = [ "bounds_checking_function:libsec_shared" ]
+ if (init_feature_begetctl_liteos) {
+ sources += syspara_sources
+ defines += [ "LITEOS_SUPPORT" ]
+ deps += [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ]
+ } else {
+ sources += [ "syscap/init_syscap.c" ]
+ }
+ if (ohos_kernel_type == "liteos_a") {
+ defines += [ "__LITEOS_A__" ]
+ deps +=
+ [ "//base/startup/init/services/param/liteos:param_client_lite" ]
+ } else if (ohos_kernel_type == "linux") {
+ sources += [ "socket/init_socket.c" ]
+ defines += [ "__LINUX__" ]
+ deps += [
+ "//base/startup/init/services/loopevent:loopevent",
+ "//base/startup/init/services/param/base:param_base",
+ "//base/startup/init/services/param/linux:param_client",
+ ]
+ }
+ }
+
+ static_library("libbegetutil_static") {
+ }
+ }
+ if (ohos_kernel_type == "liteos_m") {
+ static_library("libbegetutil") {
+ public_configs = [ ":exported_header_files" ]
+ defines = [
+ "_GNU_SOURCE",
+ "OHOS_LITE",
+ "__LITEOS_M__",
+ ]
+
+ include_dirs = include_common
+ include_dirs += [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits" ]
+ deps = [
+ "//base/startup/init/services/modules/init_hook:inithook",
+ "//base/startup/init/services/modules/udid:libudidcomm",
+ ]
+ external_deps = [ "bounds_checking_function:libsec_static" ]
+ if (init_lite_no_log) {
+ defines += [ "INIT_NO_LOG" ]
+ } else {
+ deps +=
+ [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_static" ]
+ }
+
+ sources = []
+ if (init_feature_begetctl_liteos) {
+ PRODUCT_HAL_SYSPARAM_PATH =
+ rebase_path("${ohos_product_adapter_dir}/utils/sys_param")
+ cmd = "if [ -f ${PRODUCT_HAL_SYSPARAM_PATH}/BUILD.gn ]; then echo true; else echo false; fi"
+ PRODUCT_HAL_SYSPARAM_EXISTS =
+ exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value")
+ if (PRODUCT_HAL_SYSPARAM_EXISTS) {
+ deps += [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ]
+ }
+ deps += [
+ "//base/startup/init/interfaces/hals/utils/sys_param:hal_sys_param",
+ ]
+ defines += [ "LITEOS_SUPPORT" ]
+ sources += syspara_sources
+ } else {
+ sources += [ "syscap/init_syscap.c" ]
+ }
+
+ if (init_feature_begetctl_liteos) {
+ deps += [
+ "//base/startup/init/services/param/liteos:param_client_lite",
+ "//base/startup/init/services/utils:libinit_utils",
+ ]
+ if (!init_lite_no_log) {
+ deps += [ "//base/startup/init/services/log:init_log" ]
+ }
+ }
+ }
+
+ static_library("libbegetutil_static") {
+ }
+ }
+
+ lite_component("parameter") {
+ features = [ ":libbegetutil" ]
+ }
+
+ ndk_lib("parameter_notes") {
+ if (ohos_kernel_type != "liteos_m") {
+ lib_extension = ".so"
+ }
+ deps = [ ":libbegetutil" ]
+ head_files = [ "//base/startup/init/interfaces/innerkits/include/syspara" ]
+ }
+
+ group("libbeget_proxy") {
+ }
+} else {
+ import("//build/ohos.gni")
+ modulemgr_sources = [
+ "hookmgr/hookmgr.c",
+ "modulemgr/modulemgr.c",
+ ]
+
+ ohos_shared_library("libbegetutil") {
+ sources = [
+ "fd_holder/fd_holder.c",
+ "reboot/init_reboot_innerkits.c",
+ "service_control/service_control.c",
+ ]
+ sources += syspara_sources
+ sources += [ "syspara/param_wrapper.cpp" ]
+ sources += modulemgr_sources
+
+ innerapi_tags = [
+ "chipsetsdk",
+ "platformsdk",
+ "sasdk",
+ ]
+
+ version_script = "libbegetutil.versionscript"
+
+ defines = [
+ "INIT_AGENT",
+ "_GNU_SOURCE",
+ ]
+ if (target_cpu == "arm64" || target_cpu == "x86_64" ||
+ target_cpu == "riscv64") {
+ defines += [ "SUPPORT_64BIT" ]
+ }
+
+ include_dirs = include_common
+ deps = [
+ "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd",
+ "//base/startup/init/interfaces/innerkits/fd_holder:fdholder",
+ "//base/startup/init/interfaces/innerkits/file:libfile",
+ "//base/startup/init/interfaces/innerkits/socket:libsocket",
+ "//base/startup/init/services/log:agent_log",
+ "//base/startup/init/services/loopevent:loopevent",
+ "//base/startup/init/services/modules/udid:libudidcomm",
+ "//base/startup/init/services/param/linux:param_client",
+ "//base/startup/init/services/utils:libinit_utils",
+ ]
+ deps += [ "//base/startup/init/services/param/base:param_base" ]
+ if (init_begetutil_extra_modules != "") {
+ deps += [ init_begetutil_extra_modules ]
+ }
+
+ external_deps = [
+ "bounds_checking_function:libsec_shared",
+ "c_utils:utils",
+ "config_policy:configpolicy_util_for_init_static",
+ "hilog:libhilog_base",
+ ]
+ public_configs = [ ":exported_header_files" ]
+ part_name = "init"
+ subsystem_name = "startup"
+ install_images = [
+ "system",
+ "updater",
+ ]
+ }
+
+ # watcher lib must separate compilation avoid interdependence.
+ ohos_shared_library("libbeget_proxy") {
+ defines = [
+ "INIT_AGENT",
+ "_GNU_SOURCE",
+ ]
+ sources = [
+ "//base/startup/init/device_info/device_info.cpp",
+ "service_watcher/service_watcher.c",
+ ]
+
+ version_script = "libbeget_proxy.versionscript"
+
+ include_dirs = include_common
+ deps = [
+ ":libbegetutil",
+ "//base/startup/init/services/utils:libinit_utils",
+ ]
+
+ if (enable_ohos_startup_init_feature_watcher) {
+ sources += [
+ "//base/startup/init/services/param/watcher/agent/watcher.cpp",
+ "//base/startup/init/services/param/watcher/agent/watcher_manager_kits.cpp",
+ "//base/startup/init/services/param/watcher/agent/watcher_manager_proxy.cpp",
+ "//base/startup/init/services/param/watcher/agent/watcher_stub.cpp",
+ ]
+ deps += [ "//base/startup/init/services/param/linux:param_client" ]
+ include_dirs += [
+ "//base/startup/init/services/param/watcher/include",
+ "//base/startup/init/services/log",
+ "//base/startup/init/interfaces/innerkits/include/param",
+ ]
+ } else {
+ defines += [ "NO_PARAM_WATCHER" ]
+ }
+
+ if (enable_ohos_startup_init_feature_deviceinfo) {
+ sources += [
+ "//base/startup/init/device_info/device_info_kits.cpp",
+ "//base/startup/init/device_info/device_info_load.cpp",
+ "//base/startup/init/device_info/device_info_proxy.cpp",
+ ]
+ defines += [ "PARAM_FEATURE_DEVICEINFO" ]
+ } else {
+ sources +=
+ [ "//base/startup/init/interfaces/innerkits/syspara/param_comm.c" ]
+ }
+
+ external_deps = [
+ "bounds_checking_function:libsec_shared",
+ "c_utils:utils",
+ "hilog:libhilog_base",
+ "ipc:ipc_single",
+ "samgr:samgr_proxy",
+ ]
+ public_configs = [ ":exported_header_files" ]
+ innerapi_tags = [
+ "chipsetsdk",
+ "platformsdk",
+ ]
+ part_name = "init"
+ subsystem_name = "startup"
+ install_images = [ "system" ]
+ }
+
+ ohos_static_library("libbegetutil_static") {
+ sources = syspara_sources
+ sources += [
+ "reboot/init_reboot_innerkits.c",
+ "syspara/param_wrapper.cpp",
+ ]
+
+ defines = [
+ "INIT_AGENT",
+ "_GNU_SOURCE",
+ ]
+ if (target_cpu == "arm64" || target_cpu == "x86_64" ||
+ target_cpu == "riscv64") {
+ defines += [ "SUPPORT_64BIT" ]
+ }
+
+ include_dirs = include_common
+ deps = [
+ "//base/startup/init/services/log:agent_log",
+ "//base/startup/init/services/loopevent:loopevent",
+ "//base/startup/init/services/modules/udid:libudidcomm_static",
+ "//base/startup/init/services/param/linux:param_client",
+ "//base/startup/init/services/utils:libinit_utils",
+ ]
+ deps += [ "//base/startup/init/services/param/base:param_base" ]
+ external_deps = [
+ "bounds_checking_function:libsec_static",
+ "c_utils:utilsbase",
+ "hilog:libhilog_base",
+ ]
+ public_configs = [ ":exported_header_files" ]
+ part_name = "init"
+ subsystem_name = "startup"
+ }
+}
+
+group("innergroup") {
+ deps = [ ":libbegetutil" ]
+ if (build_seccomp) {
+ deps += [ "seccomp:seccomp" ]
+ }
+ if (!defined(ohos_lite)) {
+ deps += [
+ ":libbeget_proxy",
+ "file:libfile",
+ "init_module_engine:modulegroup",
+ "socket:libsocket",
+ ]
+ } else {
+ }
+}
diff --git a/interfaces/innerkits/control_fd/BUILD.gn b/interfaces/innerkits/control_fd/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..53db2865c28bebd0566324a2ec021304629e2a8d
--- /dev/null
+++ b/interfaces/innerkits/control_fd/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright (c) 2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//base/startup/init/begetd.gni")
+import("//build/ohos.gni")
+
+config("exported_header_files") {
+ visibility = [ ":*" ]
+ include_dirs = [
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/control_fd",
+ ]
+}
+
+ohos_static_library("libcontrolfd") {
+ sources = [
+ "control_fd_client.c",
+ "control_fd_service.c",
+ ]
+ public_configs = [ ":exported_header_files" ]
+ include_dirs = [
+ ".",
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/services/loopevent/include",
+ ]
+ external_deps = [ "bounds_checking_function:libsec_shared" ]
+ part_name = "init"
+ subsystem_name = "startup"
+}
diff --git a/interfaces/innerkits/control_fd/control_fd.h b/interfaces/innerkits/control_fd/control_fd.h
new file mode 100644
index 0000000000000000000000000000000000000000..e026899debcb29410afc68d0303ada709053fd0a
--- /dev/null
+++ b/interfaces/innerkits/control_fd/control_fd.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONTROL_FD_
+#define CONTROL_FD_
+
+#include
+#include
+#include
+
+#include "list.h"
+#include "loop_event.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define INIT_CONTROL_FD_SOCKET_PATH "/dev/unix/socket/init_control_fd"
+
+#define CONTROL_FD_FIFO_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
+#define PTY_BUF_SIZE 4096
+#define PTY_PATH_SIZE 128
+
+#ifdef STARTUP_INIT_TEST
+#define CONTROL_FD_STATIC
+#else
+#define CONTROL_FD_STATIC static
+#endif
+
+typedef struct CmdService_ {
+ TaskHandle serverTask;
+ struct ListNode head;
+} CmdService;
+
+typedef struct CmdAgent_ {
+ TaskHandle task;
+ WatcherHandle input; // watch stdin
+ WatcherHandle reader; // watch read pty
+ int ptyFd;
+} CmdAgent;
+
+typedef struct CmdTask_ {
+ TaskHandle task;
+ struct ListNode item;
+ int ptyFd;
+ pid_t pid;
+} CmdTask;
+
+typedef void (* CallbackControlFdProcess)(uint16_t type, const char *serviceCmd, const void *context);
+typedef int (* CallbackSendMsgProcess)(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName);
+
+typedef enum {
+ ACTION_SANDBOX = 0,
+ ACTION_DUMP,
+ ACTION_MODULEMGR,
+ ACTION_APP_SPAWNTIME,
+ ACTION_APP_SANDBOX,
+ ACTION_MAX
+} ActionType;
+
+typedef struct {
+ uint16_t msgSize;
+ uint16_t type;
+ char ptyName[PTY_PATH_SIZE];
+ char cmd[0];
+} CmdMessage;
+
+void CmdServiceInit(const char *socketPath, CallbackControlFdProcess func, LoopHandle loop);
+void CmdClientInit(const char *socketPath, uint16_t type, const char *cmd, CallbackSendMsgProcess callback);
+void CmdServiceProcessDelClient(pid_t pid);
+void CmdServiceProcessDestroyClient(void);
+int InitPtyInterface(CmdAgent *agent, uint16_t type, const char *cmd, CallbackSendMsgProcess callback);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif
diff --git a/interfaces/innerkits/control_fd/control_fd_client.c b/interfaces/innerkits/control_fd/control_fd_client.c
new file mode 100644
index 0000000000000000000000000000000000000000..c909fb45d7d703113c74c1c3d5f1484d5f14716e
--- /dev/null
+++ b/interfaces/innerkits/control_fd/control_fd_client.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "beget_ext.h"
+#include "control_fd.h"
+#include "securec.h"
+
+CallbackSendMsgProcess g_sendMsg = NULL;
+
+CONTROL_FD_STATIC void ProcessPtyWrite(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
+{
+ if ((fd < 0) || (events == NULL) || (context == NULL)) {
+ BEGET_LOGE("[control_fd] Invalid fifo write parameter");
+ return;
+ }
+ CmdAgent *agent = (CmdAgent *)context;
+ char rbuf[PTY_BUF_SIZE] = {0};
+ ssize_t rlen = read(fd, rbuf, PTY_BUF_SIZE - 1);
+ int ret = fflush(stdin);
+ BEGET_ERROR_CHECK(ret == 0, return, "[control_fd] Failed fflush err=%d", errno);
+ if (rlen > 0) {
+ ssize_t wlen = write(agent->ptyFd, rbuf, rlen);
+ BEGET_ERROR_CHECK(wlen == rlen, return, "[control_fd] Failed write fifo err=%d", errno);
+ }
+ ret = fflush(stdout);
+ BEGET_ERROR_CHECK(ret == 0, return, "[control_fd] Failed fflush err=%d", errno);
+ *events = EVENT_READ;
+}
+
+CONTROL_FD_STATIC void ProcessPtyRead(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
+{
+ if ((fd < 0) || (events == NULL) || (context == NULL)) {
+ BEGET_LOGE("[control_fd] Invalid fifo read parameter");
+ return;
+ }
+ CmdAgent *agent = (CmdAgent *)context;
+ char buf[PTY_BUF_SIZE] = {0};
+ ssize_t readlen = 0;
+ do {
+ readlen = read(fd, buf, PTY_BUF_SIZE - 1);
+ } while (readlen == -1 && errno == EINTR);
+
+ if (readlen > 0) {
+ fprintf(stdout, "%s", buf);
+ } else {
+ (void)close(agent->ptyFd);
+ LE_StopLoop(LE_GetDefaultLoop());
+ *events = 0;
+ return;
+ }
+ int ret = fflush(stdout);
+ BEGET_ERROR_CHECK(ret == 0, return, "[control_fd] Failed fflush err=%d", errno);
+ *events = EVENT_READ;
+}
+
+CONTROL_FD_STATIC void CmdClientOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen)
+{
+ BEGET_LOGI("[control_fd] CmdOnRecvMessage %s len %d.", (char *)buffer, buffLen);
+}
+
+CONTROL_FD_STATIC void CmdOnConnectComplete(const TaskHandle client)
+{
+ BEGET_LOGI("[control_fd] CmdOnConnectComplete");
+}
+
+CONTROL_FD_STATIC void CmdOnClose(const TaskHandle task)
+{
+ BEGET_LOGI("[control_fd] CmdOnClose");
+ CmdAgent *agent = (CmdAgent *)LE_GetUserData(task);
+ BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Invalid agent");
+ (void)close(agent->ptyFd);
+ agent->ptyFd = -1;
+ LE_StopLoop(LE_GetDefaultLoop());
+}
+
+CONTROL_FD_STATIC void CmdDisConnectComplete(const TaskHandle client)
+{
+ BEGET_LOGI("[control_fd] CmdDisConnectComplete");
+}
+
+CONTROL_FD_STATIC void CmdOnSendMessageComplete(const TaskHandle task, const BufferHandle handle)
+{
+ BEGET_LOGI("[control_fd] CmdOnSendMessageComplete");
+}
+
+CONTROL_FD_STATIC CmdAgent *CmdAgentCreate(const char *server)
+{
+ if (server == NULL) {
+ BEGET_LOGE("[control_fd] Invalid parameter");
+ return NULL;
+ }
+ TaskHandle task = NULL;
+ LE_StreamInfo info = {};
+ info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
+ info.server = (char *)server;
+ info.baseInfo.userDataSize = sizeof(CmdAgent);
+ info.baseInfo.close = CmdOnClose;
+ info.disConnectComplete = CmdDisConnectComplete;
+ info.connectComplete = CmdOnConnectComplete;
+ info.sendMessageComplete = CmdOnSendMessageComplete;
+ info.recvMessage = CmdClientOnRecvMessage;
+ LE_STATUS status = LE_CreateStreamClient(LE_GetDefaultLoop(), &task, &info);
+ BEGET_ERROR_CHECK(status == 0, return NULL, "[control_fd] Failed create client");
+ CmdAgent *agent = (CmdAgent *)LE_GetUserData(task);
+ BEGET_ERROR_CHECK(agent != NULL, return NULL, "[control_fd] Invalid agent");
+ agent->task = task;
+ return agent;
+}
+
+CONTROL_FD_STATIC int SendCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName)
+{
+ if ((agent == NULL) || (cmd == NULL) || (ptyName == NULL)) {
+ BEGET_LOGE("[control_fd] Invalid parameter");
+ return -1;
+ }
+ BufferHandle handle = NULL;
+ uint32_t bufferSize = sizeof(CmdMessage) + strlen(cmd) + PTY_PATH_SIZE + 1;
+ handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
+ char *buff = (char *)LE_GetBufferInfo(handle, NULL, NULL);
+ BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info");
+ CmdMessage *message = (CmdMessage *)buff;
+ message->msgSize = bufferSize;
+ message->type = type;
+ int ret = strcpy_s(message->ptyName, PTY_PATH_SIZE - 1, ptyName);
+ BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), agent->task, handle);
+ return -1, "[control_fd] Failed to copy pty name %s", ptyName);
+ ret = strcpy_s(message->cmd, bufferSize - sizeof(CmdMessage) - PTY_PATH_SIZE, cmd);
+ BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), agent->task, handle);
+ return -1, "[control_fd] Failed to copy cmd %s", cmd);
+ ret = LE_Send(LE_GetDefaultLoop(), agent->task, handle, bufferSize);
+ BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed LE_Send msg type %d, cmd %s",
+ message->type, message->cmd);
+ return 0;
+}
+
+int InitPtyInterface(CmdAgent *agent, uint16_t type, const char *cmd, CallbackSendMsgProcess callback)
+{
+ if ((cmd == NULL) || (agent == NULL)) {
+ return -1;
+ }
+#ifndef STARTUP_INIT_TEST
+ g_sendMsg = callback;
+ // initialize terminal
+ struct termios term;
+ int ret = tcgetattr(STDIN_FILENO, &term);
+ BEGET_ERROR_CHECK(ret == 0, return -1, "Failed tcgetattr stdin, err=%d", errno);
+ cfmakeraw(&term);
+ term.c_cc[VTIME] = 0;
+ term.c_cc[VMIN] = 1;
+ ret = tcsetattr(STDIN_FILENO, TCSANOW, &term);
+ BEGET_ERROR_CHECK(ret == 0, return -1, "Failed tcsetattr term, err=%d", errno);
+ // open master pty and get slave pty
+ int pfd = open("/dev/ptmx", O_RDWR | O_CLOEXEC);
+ BEGET_ERROR_CHECK(pfd >= 0, return -1, "Failed open pty err=%d", errno);
+ BEGET_ERROR_CHECK(grantpt(pfd) >= 0, close(pfd); return -1, "Failed to call grantpt");
+ BEGET_ERROR_CHECK(unlockpt(pfd) >= 0, close(pfd); return -1, "Failed to call unlockpt");
+ char ptsbuffer[PTY_PATH_SIZE] = {0};
+ ret = ptsname_r(pfd, ptsbuffer, sizeof(ptsbuffer));
+ BEGET_ERROR_CHECK(ret >= 0, close(pfd); return -1, "Failed to get pts name err=%d", errno);
+ BEGET_LOGI("ptsbuffer is %s", ptsbuffer);
+ BEGET_ERROR_CHECK(chmod(ptsbuffer, S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0,
+ close(pfd); return -1, "Failed to chmod %s, err=%d", ptsbuffer, errno);
+ agent->ptyFd = pfd;
+
+ LE_WatchInfo info = {};
+ info.flags = 0;
+ info.events = EVENT_READ;
+ info.processEvent = ProcessPtyRead;
+ info.fd = pfd; // read ptmx
+ BEGET_ERROR_CHECK(LE_StartWatcher(LE_GetDefaultLoop(), &agent->reader, &info, agent) == LE_SUCCESS,
+ close(pfd); return -1, "[control_fd] Failed le_loop start watcher ptmx read");
+ info.processEvent = ProcessPtyWrite;
+ info.fd = STDIN_FILENO; // read stdin and write ptmx
+ BEGET_ERROR_CHECK(LE_StartWatcher(LE_GetDefaultLoop(), &agent->input, &info, agent) == LE_SUCCESS,
+ close(pfd); return -1, "[control_fd] Failed le_loop start watcher stdin read and write ptmx");
+ if (g_sendMsg == NULL) {
+ ret = SendCmdMessage(agent, type, cmd, ptsbuffer);
+ } else {
+ ret = g_sendMsg(agent, type, cmd, ptsbuffer);
+ }
+ BEGET_ERROR_CHECK(ret == 0, close(pfd); return -1, "[control_fd] Failed send message");
+#endif
+ return 0;
+}
+
+void CmdClientInit(const char *socketPath, uint16_t type, const char *cmd, CallbackSendMsgProcess callback)
+{
+ if ((socketPath == NULL) || (cmd == NULL)) {
+ BEGET_LOGE("[control_fd] Invalid parameter");
+ }
+ BEGET_LOGI("[control_fd] CmdAgentInit");
+ CmdAgent *agent = CmdAgentCreate(socketPath);
+ BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Failed to create agent");
+#ifndef STARTUP_INIT_TEST
+ int ret = InitPtyInterface(agent, type, cmd, callback);
+ if (ret != 0) {
+ return;
+ }
+ LE_RunLoop(LE_GetDefaultLoop());
+ LE_CloseLoop(LE_GetDefaultLoop());
+#endif
+ BEGET_LOGI("Cmd Client exit ");
+}
diff --git a/interfaces/innerkits/control_fd/control_fd_service.c b/interfaces/innerkits/control_fd/control_fd_service.c
new file mode 100644
index 0000000000000000000000000000000000000000..8b4ffce5a61567ed133422ed157a83af5ad001ca
--- /dev/null
+++ b/interfaces/innerkits/control_fd/control_fd_service.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "beget_ext.h"
+#include "control_fd.h"
+#include "init_utils.h"
+#include "securec.h"
+
+static CmdService g_cmdService;
+static LoopHandle g_controlFdLoop = NULL;
+
+CallbackControlFdProcess g_controlFdFunc = NULL;
+
+static void OnClose(const TaskHandle task)
+{
+ CmdTask *agent = (CmdTask *)LE_GetUserData(task);
+ BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent");
+ OH_ListRemove(&agent->item);
+ OH_ListInit(&agent->item);
+}
+
+CONTROL_FD_STATIC int CheckSocketPermission(const TaskHandle task)
+{
+ struct ucred uc = {-1, -1, -1};
+ socklen_t len = sizeof(uc);
+ if (getsockopt(LE_GetSocketFd(task), SOL_SOCKET, SO_PEERCRED, &uc, &len) < 0) {
+ BEGET_LOGE("Failed to get socket option. err = %d", errno);
+ return -1;
+ }
+ // Only root is permitted to use control fd of init.
+ if (uc.uid != 0) { // non-root user
+ errno = EPERM;
+ return -1;
+ }
+ return 0;
+}
+
+CONTROL_FD_STATIC void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen)
+{
+ if (buffer == NULL) {
+ return;
+ }
+ CmdTask *agent = (CmdTask *)LE_GetUserData(task);
+ BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent");
+
+ // parse msg to exec
+ CmdMessage *msg = (CmdMessage *)buffer;
+ if ((msg->type >= ACTION_MAX) || (msg->cmd[0] == '\0') || (msg->ptyName[0] == '\0')) {
+ BEGET_LOGE("[control_fd] Received msg is invalid");
+ return;
+ }
+
+ BEGET_ERROR_CHECK(CheckSocketPermission(task) >= 0, return, "Check socket permission failed, err = %d", errno);
+
+#ifndef STARTUP_INIT_TEST
+ agent->pid = fork();
+ if (agent->pid == 0) {
+ OpenConsole();
+ char *realPath = GetRealPath(msg->ptyName);
+ BEGET_ERROR_CHECK(realPath != NULL, _exit(1), "Failed get realpath, err=%d", errno);
+ int n = strncmp(realPath, "/dev/pts/", strlen("/dev/pts/"));
+ BEGET_ERROR_CHECK(n == 0, free(realPath); _exit(1), "pts path %s is invaild", realPath);
+ int fd = open(realPath, O_RDWR);
+ free(realPath);
+ BEGET_ERROR_CHECK(fd >= 0, _exit(1), "Failed open %s, err=%d", msg->ptyName, errno);
+ (void)dup2(fd, STDIN_FILENO);
+ (void)dup2(fd, STDOUT_FILENO);
+ (void)dup2(fd, STDERR_FILENO); // Redirect fd to 0, 1, 2
+ (void)close(fd);
+ if (g_controlFdFunc != NULL) {
+ g_controlFdFunc(msg->type, msg->cmd, NULL);
+ }
+ _exit(0);
+ } else if (agent->pid < 0) {
+ BEGET_LOGE("[control_fd] Failed to fork child process, err = %d", errno);
+ }
+#endif
+ return;
+}
+
+CONTROL_FD_STATIC int SendMessage(LoopHandle loop, TaskHandle task, const char *message)
+{
+ if (message == NULL) {
+ BEGET_LOGE("[control_fd] Invalid parameter");
+ return -1;
+ }
+ BufferHandle handle = NULL;
+ uint32_t bufferSize = strlen(message) + 1;
+ handle = LE_CreateBuffer(loop, bufferSize);
+ char *buff = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize);
+ BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info");
+ int ret = memcpy_s(buff, bufferSize, message, strlen(message) + 1);
+ BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(g_controlFdLoop, task, handle);
+ return -1, "[control_fd] Failed memcpy_s err=%d", errno);
+ LE_STATUS status = LE_Send(loop, task, handle, strlen(message) + 1);
+ BEGET_ERROR_CHECK(status == LE_SUCCESS, return -1, "[control_fd] Failed le send msg");
+ return 0;
+}
+
+CONTROL_FD_STATIC int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server)
+{
+ TaskHandle client = NULL;
+ LE_StreamInfo info = {};
+#ifndef STARTUP_INIT_TEST
+ info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
+#else
+ info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT | TASK_TEST;
+#endif
+ info.baseInfo.close = OnClose;
+ info.baseInfo.userDataSize = sizeof(CmdTask);
+ info.disConnectComplete = NULL;
+ info.sendMessageComplete = NULL;
+ info.recvMessage = CmdOnRecvMessage;
+ int ret = LE_AcceptStreamClient(g_controlFdLoop, server, &client, &info);
+ BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed accept stream")
+ CmdTask *agent = (CmdTask *)LE_GetUserData(client);
+ BEGET_ERROR_CHECK(agent != NULL, return -1, "[control_fd] Invalid agent");
+ agent->task = client;
+ OH_ListInit(&agent->item);
+ ret = SendMessage(g_controlFdLoop, agent->task, "connect success.");
+ BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed send msg");
+ OH_ListAddTail(&g_cmdService.head, &agent->item);
+ return 0;
+}
+
+void CmdServiceInit(const char *socketPath, CallbackControlFdProcess func, LoopHandle loop)
+{
+ if ((socketPath == NULL) || (func == NULL) || (loop == NULL)) {
+ BEGET_LOGE("[control_fd] Invalid parameter");
+ return;
+ }
+ OH_ListInit(&g_cmdService.head);
+ LE_StreamServerInfo info = {};
+ info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE;
+ info.server = (char *)socketPath;
+ info.socketId = -1;
+ info.baseInfo.close = NULL;
+ info.disConnectComplete = NULL;
+ info.incommingConnect = CmdOnIncommingConnect;
+ info.sendMessageComplete = NULL;
+ info.recvMessage = NULL;
+ g_controlFdFunc = func;
+ if (g_controlFdLoop == NULL) {
+ g_controlFdLoop = loop;
+ }
+ (void)LE_CreateStreamServer(g_controlFdLoop, &g_cmdService.serverTask, &info);
+}
+
+static int ClientTraversalProc(ListNode *node, void *data)
+{
+ CmdTask *info = ListEntry(node, CmdTask, item);
+ int pid = *(int *)data;
+ return pid - info->pid;
+}
+
+void CmdServiceProcessDelClient(pid_t pid)
+{
+ ListNode *node = OH_ListFind(&g_cmdService.head, (void *)&pid, ClientTraversalProc);
+ if (node != NULL) {
+ CmdTask *agent = ListEntry(node, CmdTask, item);
+ OH_ListRemove(&agent->item);
+ OH_ListInit(&agent->item);
+ LE_CloseTask(g_controlFdLoop, agent->task);
+ }
+}
+
+static void CmdServiceDestroyProc(ListNode *node)
+{
+ if (node == NULL) {
+ return;
+ }
+ CmdTask *agent = ListEntry(node, CmdTask, item);
+ OH_ListRemove(&agent->item);
+ OH_ListInit(&agent->item);
+ LE_CloseTask(g_controlFdLoop, agent->task);
+}
+
+void CmdServiceProcessDestroyClient(void)
+{
+ OH_ListRemoveAll(&g_cmdService.head, CmdServiceDestroyProc);
+ LE_StopLoop(g_controlFdLoop);
+}
diff --git a/interfaces/innerkits/reboot/BUILD.gn b/interfaces/innerkits/fd_holder/BUILD.gn
similarity index 54%
rename from interfaces/innerkits/reboot/BUILD.gn
rename to interfaces/innerkits/fd_holder/BUILD.gn
index d603b712bd10d036e37f1d8144c7bb743e3a0268..be043bd40dbc092179a50a6e65825336eb5ebc12 100644
--- a/interfaces/innerkits/reboot/BUILD.gn
+++ b/interfaces/innerkits/fd_holder/BUILD.gn
@@ -12,20 +12,23 @@
# limitations under the License.
import("//build/ohos.gni")
-ohos_static_library("libreboot") {
- sources =
- [ "//base/startup/init_lite/interfaces/innerkits/reboot/init_reboot.c" ]
+config("exported_header_files") {
+ visibility = [ ":*" ]
include_dirs = [
- "//base/startup/init_lite/interfaces/innerkits/include",
- "//base/startup/init_lite/services/include/param",
- "//third_party/bounds_checking_function/include",
- "//base/startup/init_lite/services/log",
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/fd_holder",
]
+}
- deps = [
- "//base/startup/init_lite/services/log:init_log",
- "//base/startup/init_lite/services/param:paramclient",
- "//third_party/bounds_checking_function:libsec_static",
+ohos_static_library("fdholder") {
+ sources = [ "fd_holder_internal.c" ]
+ include_dirs = [
+ "//base/startup/init/services/loopevent/include",
+ "//base/startup/init/interfaces/innerkits/include",
]
+ public_configs = [ ":exported_header_files" ]
+ external_deps = [ "bounds_checking_function:libsec_static" ]
+ part_name = "init"
+ subsystem_name = "startup"
}
diff --git a/interfaces/innerkits/fd_holder/fd_holder.c b/interfaces/innerkits/fd_holder/fd_holder.c
new file mode 100644
index 0000000000000000000000000000000000000000..13ffbfaaefd9b0f229185fbfbbb6c98c736b08ab
--- /dev/null
+++ b/interfaces/innerkits/fd_holder/fd_holder.c
@@ -0,0 +1,193 @@
+/*
+* 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 "fd_holder.h"
+#include
+#include
+
+#include "beget_ext.h"
+#include "fd_holder_internal.h"
+#include "init_utils.h"
+#include "securec.h"
+
+static int BuildClientSocket(void)
+{
+ int sockFd;
+ sockFd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ BEGET_ERROR_CHECK(sockFd >= 0, return -1, "Failed to build socket, err = %d", errno);
+
+ struct sockaddr_un addr;
+ (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ int ret = strncpy_s(addr.sun_path, sizeof(addr.sun_path), INIT_HOLDER_SOCKET_PATH,
+ strlen(INIT_HOLDER_SOCKET_PATH));
+ BEGET_ERROR_CHECK(ret == 0, close(sockFd);
+ return -1, "Failed to build socket path");
+
+ socklen_t len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1);
+
+ ret = connect(sockFd, (struct sockaddr *)&addr, len);
+ BEGET_ERROR_CHECK(ret >= 0, close(sockFd);
+ return -1, "Failed to connect to socket, err = %d", errno);
+ return sockFd;
+}
+
+STATIC int BuildSendData(char *buffer, size_t size, const char *serviceName, bool hold, bool poll)
+{
+ if (buffer == NULL || size == 0 || serviceName == 0) {
+ return -1;
+ }
+
+ if (!hold && poll) {
+ BEGET_LOGE("Get fd with poll set, invalid parameter");
+ return -1;
+ }
+
+ char *holdString = ACTION_HOLD;
+ if (!hold) {
+ holdString = ACTION_GET;
+ }
+ char *pollString = WITHPOLL;
+ if (!poll) {
+ pollString = WITHOUTPOLL;
+ }
+
+ if (snprintf_s(buffer, size, size - 1, "%s|%s|%s", serviceName, holdString, pollString) == -1) {
+ BEGET_LOGE("Failed to build send data");
+ return -1;
+ }
+ return 0;
+}
+
+static int ServiceSendFds(const char *serviceName, int *fds, int fdCount, bool doPoll)
+{
+ int sock = BuildClientSocket();
+ BEGET_CHECK(sock >= 0, return -1);
+
+ struct iovec iovec = {};
+ struct msghdr msghdr = {
+ .msg_iov = &iovec,
+ .msg_iovlen = 1,
+ };
+
+ char sendBuffer[MAX_FD_HOLDER_BUFFER] = {};
+ int ret = BuildSendData(sendBuffer, sizeof(sendBuffer), serviceName, true, doPoll);
+ BEGET_ERROR_CHECK(ret >= 0, close(sock);
+ return -1, "Failed to build send data");
+
+ BEGET_LOGV("Send data: [%s]", sendBuffer);
+ iovec.iov_base = sendBuffer;
+ iovec.iov_len = strlen(sendBuffer);
+
+ if (BuildControlMessage(&msghdr, fds, fdCount, true) < 0) {
+ BEGET_LOGE("Failed to build control message");
+ if (msghdr.msg_control != NULL) {
+ free(msghdr.msg_control);
+ msghdr.msg_control = NULL;
+ }
+ msghdr.msg_controllen = 0;
+ close(sock);
+ return -1;
+ }
+
+ if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) {
+ BEGET_LOGE("Failed to send fds to init, err = %d", errno);
+ if (msghdr.msg_control != NULL) {
+ free(msghdr.msg_control);
+ msghdr.msg_control = NULL;
+ }
+ msghdr.msg_controllen = 0;
+ close(sock);
+ return -1;
+ }
+ if (msghdr.msg_control != NULL) {
+ free(msghdr.msg_control);
+ msghdr.msg_control = NULL;
+ }
+ msghdr.msg_controllen = 0;
+ BEGET_LOGI("Send fds done");
+ close(sock);
+ return 0;
+}
+
+int ServiceSaveFd(const char *serviceName, int *fds, int fdCount)
+{
+ // Sanity checks
+ if (serviceName == NULL || fds == NULL ||
+ fdCount < 0 || fdCount > MAX_HOLD_FDS) {
+ BEGET_LOGE("Invalid parameters");
+ return -1;
+ }
+ return ServiceSendFds(serviceName, fds, fdCount, false);
+}
+
+int ServiceSaveFdWithPoll(const char *serviceName, int *fds, int fdCount)
+{
+ // Sanity checks
+ if (serviceName == NULL || fds == NULL ||
+ fdCount < 0 || fdCount > MAX_HOLD_FDS) {
+ BEGET_LOGE("Invalid parameters");
+ return -1;
+ }
+ return ServiceSendFds(serviceName, fds, fdCount, true);
+}
+
+int *ServiceGetFd(const char *serviceName, size_t *outfdCount)
+{
+ if (serviceName == NULL || outfdCount == NULL) {
+ BEGET_LOGE("Invalid parameters");
+ return NULL;
+ }
+
+ char path[MAX_FD_HOLDER_BUFFER] = {};
+ int ret = snprintf_s(path, MAX_FD_HOLDER_BUFFER, MAX_FD_HOLDER_BUFFER - 1, ENV_FD_HOLD_PREFIX"%s", serviceName);
+ BEGET_ERROR_CHECK(ret > 0, return NULL, "Failed snprintf_s err=%d", errno);
+ const char *value = getenv(path);
+ if (value == NULL) {
+ BEGET_LOGE("Cannot get env %s\n", path);
+ return NULL;
+ }
+
+ char fdBuffer[MAX_FD_HOLDER_BUFFER] = {};
+ ret = strncpy_s(fdBuffer, MAX_FD_HOLDER_BUFFER - 1, value, strlen(value));
+ BEGET_ERROR_CHECK(ret == 0, return NULL, "Failed strncpy_s err=%d", errno);
+ BEGET_LOGV("fds = %s", fdBuffer);
+ int fdCount = 0;
+ char **fdList = SplitStringExt(fdBuffer, " ", &fdCount, MAX_HOLD_FDS);
+ BEGET_ERROR_CHECK(fdList != NULL, return NULL, "Cannot get fd list");
+
+ int *fds = calloc((size_t)fdCount, sizeof(int));
+ BEGET_ERROR_CHECK(fds != NULL, FreeStringVector(fdList, fdCount);
+ *outfdCount = 0;
+ return NULL,
+ "Allocate memory for fd failed. err = %d", errno);
+
+ bool encounterError = false;
+ for (int i = 0; i < fdCount; i++) {
+ errno = 0;
+ fds[i] = (int)strtol(fdList[i], NULL, DECIMAL_BASE);
+ BEGET_ERROR_CHECK(errno == 0, encounterError = true;
+ break, "Failed to convert \' %s \' to fd number", fdList[i]);
+ }
+
+ if (encounterError) {
+ free(fds);
+ fds = NULL;
+ fdCount = 0;
+ }
+ *outfdCount = fdCount;
+ FreeStringVector(fdList, fdCount);
+ return fds;
+}
diff --git a/interfaces/innerkits/fd_holder/fd_holder_internal.c b/interfaces/innerkits/fd_holder/fd_holder_internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..314c4087b1e7b6424e5b5078459bb793a1659393
--- /dev/null
+++ b/interfaces/innerkits/fd_holder/fd_holder_internal.c
@@ -0,0 +1,140 @@
+/*
+* 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 "fd_holder_internal.h"
+#include
+#include
+#include "beget_ext.h"
+#include "securec.h"
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE (4096U)
+#endif
+
+int BuildControlMessage(struct msghdr *msghdr, int *fds, int fdCount, bool sendUcred)
+{
+ if (msghdr == NULL || (fdCount > 0 && fds == NULL)) {
+ BEGET_LOGE("Build control message with invalid parameter");
+ return -1;
+ }
+
+ if (fdCount > 0) {
+ msghdr->msg_controllen = CMSG_SPACE(sizeof(int) * fdCount);
+ } else {
+ msghdr->msg_controllen = 0;
+ }
+
+ if (sendUcred) {
+ msghdr->msg_controllen += CMSG_SPACE(sizeof(struct ucred));
+ }
+
+ msghdr->msg_control = calloc(1, ((msghdr->msg_controllen == 0) ? 1 : msghdr->msg_controllen));
+ BEGET_ERROR_CHECK(msghdr->msg_control != NULL, return -1, "Failed to build control message");
+
+ struct cmsghdr *cmsg = NULL;
+ cmsg = CMSG_FIRSTHDR(msghdr);
+ BEGET_ERROR_CHECK(cmsg != NULL, return -1, "Failed to build cmsg");
+
+ if (fdCount > 0) {
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
+ int ret = memcpy_s(CMSG_DATA(cmsg), cmsg->cmsg_len, fds, sizeof(int) * fdCount);
+ BEGET_ERROR_CHECK(ret == 0, free(msghdr->msg_control);
+ msghdr->msg_control = NULL;
+ return -1, "Control message is not valid");
+ // build ucred info
+ cmsg = CMSG_NXTHDR(msghdr, cmsg);
+ }
+
+ if (sendUcred) {
+ BEGET_ERROR_CHECK(cmsg != NULL, free(msghdr->msg_control);
+ msghdr->msg_control = NULL;
+ return -1, "Control message is not valid");
+
+ struct ucred *ucred;
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_CREDENTIALS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ ucred = (struct ucred*) CMSG_DATA(cmsg);
+ ucred->pid = getpid();
+ ucred->uid = getuid();
+ ucred->gid = getgid();
+ }
+ return 0;
+}
+
+STATIC int *GetFdsFromMsg(size_t *outFdCount, pid_t *requestPid, struct msghdr msghdr)
+{
+ if ((msghdr.msg_flags) & MSG_TRUNC) {
+ BEGET_LOGE("Message was truncated when receiving fds");
+ return NULL;
+ }
+
+ struct cmsghdr *cmsg = NULL;
+ int *fds = NULL;
+ size_t fdCount = 0;
+ for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ fds = (int*)CMSG_DATA(cmsg);
+ fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+ BEGET_ERROR_CHECK(fdCount <= MAX_HOLD_FDS, return NULL, "Too many fds returned.");
+ }
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ // Ignore credentials
+ if (requestPid != NULL) {
+ struct ucred *ucred = (struct ucred*)CMSG_DATA(cmsg);
+ *requestPid = ucred->pid;
+ }
+ continue;
+ }
+ }
+ int *outFds = NULL;
+ if (fds != NULL && fdCount > 0) {
+ outFds = calloc(fdCount + 1, sizeof(int));
+ BEGET_ERROR_CHECK(outFds != NULL, return NULL, "Failed to allocate memory for fds");
+ BEGET_ERROR_CHECK(memcpy_s(outFds, sizeof(int) * (fdCount + 1), fds, sizeof(int) * fdCount) == 0,
+ free(outFds); return NULL, "Failed to copy fds");
+ }
+ *outFdCount = fdCount;
+ return outFds;
+}
+
+// This function will allocate memory to store FDs
+// Remember to delete when not used anymore.
+int *ReceiveFds(int sock, struct iovec iovec, size_t *outFdCount, bool nonblock, pid_t *requestPid)
+{
+ CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
+ CMSG_SPACE(sizeof(int) * MAX_HOLD_FDS)) control;
+
+ BEGET_ERROR_CHECK(sizeof(control) <= PAGE_SIZE, return NULL, "Too many fds, out of memory");
+
+ struct msghdr msghdr = {
+ .msg_iov = &iovec,
+ .msg_iovlen = 1,
+ .msg_control = &control,
+ .msg_controllen = sizeof(control),
+ .msg_flags = 0,
+ };
+
+ int flags = MSG_CMSG_CLOEXEC | MSG_TRUNC;
+ if (nonblock) {
+ flags |= MSG_DONTWAIT;
+ }
+ ssize_t rc = TEMP_FAILURE_RETRY(recvmsg(sock, &msghdr, flags));
+ BEGET_ERROR_CHECK(rc >= 0, return NULL, "Failed to get fds from remote, err = %d", errno);
+ return GetFdsFromMsg(outFdCount, requestPid, msghdr);
+}
\ No newline at end of file
diff --git a/interfaces/innerkits/fd_holder/fd_holder_internal.h b/interfaces/innerkits/fd_holder/fd_holder_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..b334dfb3c7a00df99fc90e2939d3057d90a5fa2c
--- /dev/null
+++ b/interfaces/innerkits/fd_holder/fd_holder_internal.h
@@ -0,0 +1,59 @@
+/*
+* 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 BASE_STARTUP_INITLITE_FD_HOLDER_INTERNAL_H
+#define BASE_STARTUP_INITLITE_FD_HOLDER_INTERNAL_H
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define INIT_HOLDER_SOCKET_PATH "/dev/unix/socket/fd_holder"
+#define MAX_HOLD_FDS (64)
+#define MAX_FD_HOLDER_BUFFER (MAX_HOLD_FDS * sizeof(int))
+
+#define ENV_FD_HOLD_PREFIX "OHOS_FD_HOLD_"
+
+// actions
+#define ACTION_HOLD "hold"
+#define ACTION_GET "get"
+
+// poll or not
+#define WITHPOLL "poll"
+#define WITHOUTPOLL "withoutpoll"
+
+int BuildControlMessage(struct msghdr *msghdr, int *fds, int fdCount, bool sendUcred);
+// This function will allocate memory to store FDs
+// Remember to delete when not used anymore.
+int *ReceiveFds(int sock, struct iovec iovec, size_t *outFdCount, bool nonblock, pid_t *requestPid);
+
+#define CMSG_BUFFER_TYPE(size) \
+ union { \
+ struct cmsghdr cmsghdr; \
+ uint8_t buf[size]; \
+ uint8_t align_check[(size) >= CMSG_SPACE(0) && \
+ (size) == CMSG_ALIGN(size) ? 1 : -1]; \
+ }
+
+#ifdef __cplusplus
+}
+#endif
+#endif // BASE_STARTUP_INITLITE_FD_HOLDER_INTERNAL_H
diff --git a/interfaces/innerkits/file/BUILD.gn b/interfaces/innerkits/file/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..62a0a3e11bff0ac7c4597e6eaf1dc36af30fbc18
--- /dev/null
+++ b/interfaces/innerkits/file/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//build/ohos.gni")
+config("exported_header_files") {
+ visibility = [ ":*" ]
+ include_dirs = [ "//base/startup/init/interfaces/innerkits/include" ]
+}
+
+ohos_static_library("libfile") {
+ sources = [ "init_file.c" ]
+ include_dirs = [
+ "//base/startup/init/services/log",
+ "//base/startup/init/interfaces/innerkits/include",
+ ]
+ external_deps = [ "bounds_checking_function:libsec_shared" ]
+ public_configs = [ ":exported_header_files" ]
+ part_name = "init"
+ subsystem_name = "startup"
+}
diff --git a/interfaces/innerkits/file/init_file.c b/interfaces/innerkits/file/init_file.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6f6100427312b4f6daa62051164fc1308d7fb73
--- /dev/null
+++ b/interfaces/innerkits/file/init_file.c
@@ -0,0 +1,48 @@
+/*
+ * 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 "init_file.h"
+
+#include
+#include
+#include
+#include
+
+#include "beget_ext.h"
+#include "init_utils.h"
+#include "securec.h"
+
+#define N_DEC 10
+
+int GetControlFile(const char *pathName)
+{
+ if (pathName == NULL) {
+ return -1;
+ }
+ char path[PATH_MAX] = { 0 };
+ BEGET_ERROR_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1, OHOS_FILE_ENV_PREFIX "%s", pathName) >= 0,
+ return -1, "Failed snprintf_s err=%d", errno);
+ BEGET_ERROR_CHECK(StringReplaceChr(path, '/', '_') == 0,
+ return -1, "Failed string replace char");
+ BEGET_LOGI("Environment path is %s ", path);
+ const char *val = getenv(path);
+ BEGET_ERROR_CHECK(val != NULL, return -1, "Failed getenv err=%d", errno);
+ errno = 0;
+ int fd = strtol(val, NULL, N_DEC);
+ BEGET_ERROR_CHECK(errno == 0, return -1, "Failed strtol val");
+ BEGET_LOGI("Get environment fd is %d ", fd);
+ BEGET_ERROR_CHECK(fcntl(fd, F_GETFD) >= 0, return -1, "Failed fcntl fd err=%d ", errno);
+ return fd;
+}
diff --git a/interfaces/innerkits/fs_manager/BUILD.gn b/interfaces/innerkits/fs_manager/BUILD.gn
new file mode 100755
index 0000000000000000000000000000000000000000..e0ac82cc709901b2bc7e0101e94ae05698dec923
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/BUILD.gn
@@ -0,0 +1,132 @@
+# Copyright (c) 2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//base/startup/init/begetd.gni")
+import("//build/ohos.gni")
+
+# For init only
+config("libfsmanager_exported_configs") {
+ visibility = [ ":*" ]
+ include_dirs = [
+ "./libfs_dm/include",
+ "./libfs_hvb/include",
+ "//base/startup/init/interfaces/innerkits/include/fs_manager",
+ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include",
+ ]
+}
+
+ohos_static_library("libfsmanager_static") {
+ if (!defined(ohos_lite)) {
+ sources = [
+ "fstab.c",
+ "fstab_mount.c",
+ "switch_root/switch_root.c",
+ ]
+ include_dirs = [
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/include/param",
+ "//base/startup/init/interfaces/innerkits/init_module_engine/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include",
+ "//base/startup/init/services/log",
+ "//base/startup/init/services/param/include",
+ ]
+ defines = []
+ external_deps = [ "bounds_checking_function:libsec_static" ]
+ deps = [ "//base/startup/init/services/utils:libinit_utils" ]
+
+ if ((defined(global_parts_info) &&
+ defined(global_parts_info.startup_hvb)) ||
+ init_startup_feature_erofs_overlay) {
+ sources += [ "libfs_dm/fs_dm.c" ]
+ include_dirs += [
+ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include",
+ "//base/startup/init/ueventd/include",
+ ]
+ deps += [ "//base/startup/init/ueventd:libueventd_ramdisk_static" ]
+ }
+
+ if (defined(global_parts_info) && defined(global_parts_info.startup_hvb)) {
+ sources += [
+ "dm_verity/dm_verity.c",
+ "libfs_hvb/fs_hvb.c",
+ "libfs_hvb/hvb_ops.c",
+ ]
+
+ include_dirs += [
+ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/include",
+ ]
+
+ defines += [ "SUPPORT_HVB" ]
+ external_deps += [ "hvb:libhvb_static" ]
+ }
+ if (init_startup_feature_erofs_overlay) {
+ sources += [
+ "erofs_overlay/erofs_mount_overlay.c",
+ "erofs_overlay/erofs_overlay_common.c",
+ "erofs_overlay/erofs_remount_overlay.c",
+ ]
+ include_dirs += [ "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/include" ]
+
+ defines += [ "EROFS_OVERLAY" ]
+ }
+ }
+
+ public_configs = [ ":libfsmanager_exported_configs" ]
+ part_name = "init"
+ subsystem_name = "startup"
+}
+
+ohos_static_library("libfsmanager_static_real") {
+ if (!defined(ohos_lite)) {
+ sources = [
+ "fstab.c",
+ "fstab_mount.c",
+ "switch_root/switch_root.c",
+ ]
+ include_dirs = [
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/interfaces/innerkits/include/param",
+ "//base/startup/init/interfaces/innerkits/init_module_engine/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include",
+ "//base/startup/init/services/log",
+ "//base/startup/init/services/param/include",
+ ]
+ external_deps = [ "bounds_checking_function:libsec_static" ]
+ deps = [ "//base/startup/init/services/utils:libinit_utils" ]
+ if (defined(global_parts_info) && defined(global_parts_info.startup_hvb)) {
+ sources += [
+ "dm_verity/dm_verity.c",
+ "libfs_dm/fs_dm.c",
+ "libfs_hvb/fs_hvb.c",
+ "libfs_hvb/hvb_ops.c",
+ ]
+
+ include_dirs += [
+ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/include",
+ "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/include",
+ "//base/startup/init/ueventd/include",
+ ]
+
+ defines = [ "SUPPORT_HVB" ]
+ external_deps += [ "hvb:libhvb_static" ]
+ deps += [ "//base/startup/init/ueventd:libueventd_ramdisk_static_real" ]
+ }
+ }
+
+ public_configs = [ ":libfsmanager_exported_configs" ]
+ part_name = "init"
+ subsystem_name = "startup"
+}
diff --git a/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c b/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c
new file mode 100755
index 0000000000000000000000000000000000000000..6776bba151251e18fc8da6429e68508c445e06b1
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dm_verity.h"
+#include "fs_hvb.h"
+#include "hvb_cmdline.h"
+#include "securec.h"
+#include "beget_ext.h"
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define HVB_VB_STATE_STR_MAX_LEN 32
+#define HVB_FORCE_ENABLE_STR_MAX_LEN 16
+#define HVB_CMDLINE_HVB_FORCE_ENABLE "ohos.boot.hvb.oem_swtype"
+
+#define DM_VERITY_RETURN_ERR_IF_NULL(__ptr) \
+ do { \
+ if ((__ptr) == NULL) { \
+ BEGET_LOGE("error, %s is NULL\n", #__ptr); \
+ return -1; \
+ } \
+ } while (0)
+
+static bool HvbDmVerityIsEnable(void)
+{
+ int rc;
+ char forceEnable[HVB_FORCE_ENABLE_STR_MAX_LEN] = {0};
+ char vBState[HVB_VB_STATE_STR_MAX_LEN] = {0};
+
+ rc = FsHvbGetValueFromCmdLine(&forceEnable[0], sizeof(forceEnable), HVB_CMDLINE_HVB_FORCE_ENABLE);
+ if (rc == 0 && strcmp(&forceEnable[0], "factory") == 0) {
+ return true;
+ }
+
+ rc = FsHvbGetValueFromCmdLine(&vBState[0], sizeof(vBState), HVB_CMDLINE_VB_STATE);
+
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, get verifed boot state, force enable dm-verity", rc);
+ return true;
+ }
+
+ if (strcmp(&vBState[0], "false") == 0 || strcmp(&vBState[0], "FALSE") == 0) {
+ return false;
+ }
+
+ if (strcmp(&vBState[0], "orange") == 0 || strcmp(&vBState[0], "ORANGE") == 0) {
+ return false;
+ }
+
+ return true;
+}
+
+int HvbDmVerityinit(const Fstab *fstab)
+{
+ int rc;
+ FstabItem *p = NULL;
+
+ if (!HvbDmVerityIsEnable()) {
+ BEGET_LOGI("hvb not enable, not init");
+ return 0;
+ }
+
+ for (p = fstab->head; p != NULL; p = p->next) {
+ if (p->fsManagerFlags & FS_MANAGER_HVB)
+ break;
+ }
+
+ if (p == NULL) {
+ BEGET_LOGI("no need init fs hvb");
+ return 0;
+ }
+
+ rc = FsHvbInit(MAIN_HVB);
+ if (rc != 0) {
+ BEGET_LOGE("init fs hvb error, ret=%d", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+int HvbDmVeritySetUp(FstabItem *fsItem)
+{
+ int rc;
+
+ if (!HvbDmVerityIsEnable()) {
+ BEGET_LOGI("hvb not enable, not setup");
+ return 0;
+ }
+
+ DM_VERITY_RETURN_ERR_IF_NULL(fsItem);
+
+ if ((fsItem->fsManagerFlags & FS_MANAGER_HVB) == 0) {
+ BEGET_LOGW("device %s not need hvb", fsItem->deviceName ? fsItem->deviceName : "none");
+ return 0;
+ }
+
+ rc = FsHvbSetupHashtree(fsItem);
+ if (rc != 0) {
+ BEGET_LOGE("error, setup hashtree fail, ret=%d", rc);
+ }
+
+ return rc;
+}
+
+void HvbDmVerityFinal(void)
+{
+ int rc;
+
+ if (!HvbDmVerityIsEnable()) {
+ BEGET_LOGI("hvb not enable, not final");
+ return;
+ }
+
+ rc = FsHvbFinal(MAIN_HVB);
+ if (rc != 0) {
+ BEGET_LOGE("final fs hvb error, ret=%d", rc);
+ return;
+ }
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/services/param/cmd/param_set.c b/interfaces/innerkits/fs_manager/dm_verity/include/dm_verity.h
old mode 100644
new mode 100755
similarity index 45%
rename from services/param/cmd/param_set.c
rename to interfaces/innerkits/fs_manager/dm_verity/include/dm_verity.h
index 3c3943df95ad2df4048cecf61777cacc77536050..69e9fb813121489b0ff72cf3670373c6d984835a
--- a/services/param/cmd/param_set.c
+++ b/interfaces/innerkits/fs_manager/dm_verity/include/dm_verity.h
@@ -1,39 +1,39 @@
-/*
-* 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 "sys_param.h"
-
-#define HELP_PARAM "--help"
-
-int main(int argc, char* argv[])
-{
- if (argc == 1 || argc > 3) {
- printf("setparam: Need 2 arguments (see \"setparam --help\")\n");
- return 0;
- }
- if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) {
- printf("usage: setparam NAME VALUE\n");
- return 0;
- }
- int ret = SystemSetParameter(argv[1], argv[2]);
- if (ret == 0) {
- printf("setparam %s %s success\n", argv[1], argv[2]);
- } else {
- printf("setparam %s %s fail\n", argv[1], argv[2]);
- }
-}
+/*
+* Copyright (c) 2023 Huawei Device Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STARTUP_DM_VERITY_H
+#define STARTUP_DM_VERITY_H
+
+#include
+#include
+#include "fs_manager/fs_manager.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+int HvbDmVerityinit(const Fstab *fstab);
+int HvbDmVeritySetUp(FstabItem *fsItem);
+void HvbDmVerityFinal(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // STARTUP_DM_VERITY_H
diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c
new file mode 100644
index 0000000000000000000000000000000000000000..f74c27edbae2f1cace7770ffd8757baf6b2d8910
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2024-2024 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 "securec.h"
+#include "init_utils.h"
+#include "fs_dm.h"
+#include "switch_root.h"
+#include "fs_manager/fs_manager.h"
+
+#include "erofs_mount_overlay.h"
+
+#define BYTE_UNIT 1024
+#define ALIGN_BLOCK_SIZE (16 * BYTE_UNIT)
+#define MIN_DM_SIZE (2 * BYTE_UNIT * BYTE_UNIT)
+#define BLOCK_SIZE_UINT 4096
+#define EXTHDR_MAGIC 0xFEEDBEEF
+#define EXTHDR_BLKSIZE 4096
+
+struct extheader_v1 {
+ uint32_t magic_number;
+ uint16_t exthdr_size;
+ uint16_t bcc16;
+ uint64_t part_size;
+};
+
+INIT_STATIC void AllocDmName(const char *name, char *nameRofs, const uint64_t nameRofsLen,
+ char *nameExt4, const uint64_t nameExt4Len)
+{
+ if (snprintf_s(nameRofs, nameRofsLen, nameRofsLen - 1, "%s_erofs", name) < 0) {
+ BEGET_LOGE("Failed to copy nameRofs.");
+ return;
+ }
+
+ if (snprintf_s(nameExt4, nameExt4Len, nameExt4Len - 1, "%s_ext4", name) < 0) {
+ BEGET_LOGE("Failed to copy nameExt4.");
+ return;
+ }
+
+ uint64_t i = 0;
+ while (nameRofs[i] != '\0') {
+ if (nameRofs[i] == '/') {
+ nameRofs[i] = '_';
+ }
+ i++;
+ }
+ i = 0;
+ while (nameExt4[i] != '\0') {
+ if (nameExt4[i] == '/') {
+ nameExt4[i] = '_';
+ }
+ i++;
+ }
+
+ BEGET_LOGI("alloc dm namerofs:[%s], nameext4:[%s]", nameRofs, nameExt4);
+}
+
+INIT_STATIC uint64_t LookupErofsEnd(const char *dev)
+{
+ int fd = -1;
+ fd = open(dev, O_RDONLY | O_LARGEFILE);
+ if (fd < 0) {
+ BEGET_LOGE("open dev:[%s] failed.", dev);
+ return 0;
+ }
+
+ if (lseek(fd, EROFS_SUPER_BLOCK_START_POSITION, SEEK_SET) < 0) {
+ BEGET_LOGE("lseek dev:[%s] failed.", dev);
+ close(fd);
+ return 0;
+ }
+
+ struct erofs_super_block sb;
+ ssize_t nbytes = read(fd, &sb, sizeof(sb));
+ if (nbytes != sizeof(sb)) {
+ BEGET_LOGE("read dev:[%s] failed.", dev);
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ if (sb.magic != EROFS_SUPER_MAGIC) {
+ BEGET_LOGE("dev:[%s] is not erofs system, magic is 0x%x", dev, sb.magic);
+ return 0;
+ }
+
+ uint64_t erofsSize = (uint64_t)sb.blocks * BLOCK_SIZE_UINT;
+ return erofsSize;
+}
+
+INIT_STATIC uint64_t GetImgSize(const char *dev, uint64_t offset)
+{
+ int fd = -1;
+ fd = open(dev, O_RDONLY | O_LARGEFILE);
+ if (fd < 0) {
+ BEGET_LOGE("open dev:[%s] failed.", dev);
+ return 0;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ BEGET_LOGE("lseek dev:[%s] failed, offset is %llu", dev, offset);
+ close(fd);
+ return 0;
+ }
+
+ struct extheader_v1 header;
+ ssize_t nbytes = read(fd, &header, sizeof(header));
+ if (nbytes != sizeof(header)) {
+ BEGET_LOGE("read dev:[%s] failed.", dev);
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ if (header.magic_number != EXTHDR_MAGIC) {
+ BEGET_LOGI("dev:[%s] is not have ext path, magic is 0x%x", dev, header.magic_number);
+ return 0;
+ }
+ BEGET_LOGI("get img size [%llu]", header.part_size);
+ return header.part_size;
+}
+
+INIT_STATIC uint64_t GetFsSize(int fd)
+{
+ struct stat st;
+ if (fstat(fd, &st) == -1) {
+ BEGET_LOGE("fstat failed. errno: %d", errno);
+ return 0;
+ }
+
+ uint64_t size = 0;
+ if (S_ISBLK(st.st_mode)) {
+ if (ioctl(fd, BLKGETSIZE64, &size) == -1) {
+ BEGET_LOGE("ioctl failed. errno: %d", errno);
+ return 0;
+ }
+ } else if (S_ISREG(st.st_mode)) {
+ if (st.st_size < 0) {
+ BEGET_LOGE("st_size is not right. st_size: %lld", st.st_size);
+ return 0;
+ }
+ size = (uint64_t)st.st_size;
+ } else {
+ BEGET_LOGE("unspported type st_mode:[%llu]", st.st_mode);
+ errno = EACCES;
+ return 0;
+ }
+
+ BEGET_LOGI("get fs size:[%llu]", size);
+ return size;
+}
+
+INIT_STATIC uint64_t GetBlockSize(const char *dev)
+{
+ int fd = -1;
+ fd = open(dev, O_RDONLY | O_LARGEFILE);
+ if (fd < 0) {
+ BEGET_LOGE("open dev:[%s] failed.", dev);
+ return 0;
+ }
+
+ uint64_t blockSize = GetFsSize(fd);
+ close(fd);
+ return blockSize;
+}
+
+/* 字节对齐函数,基于alignment进行字节对齐 */
+INIT_STATIC uint64_t AlignTo(uint64_t base, uint64_t alignment)
+{
+ if (alignment == 0) {
+ return base;
+ }
+ return (((base - 1) / alignment + 1) * alignment);
+}
+
+INIT_STATIC int GetMapperAddr(const char *dev, uint64_t *start, uint64_t *length)
+{
+ /* 获取EROFS文件系统大小 */
+ *start = LookupErofsEnd(dev);
+ if (*start == 0) {
+ BEGET_LOGE("get erofs end failed.");
+ return -1;
+ }
+
+ /*
+ * 获取镜像大小 当前镜像布局有2种
+ * 老布局:EROFS文件系统 + 全0数据填充 + HVB数据 老布局不存在EXTHEADER,获取到的镜像大小为0。直接基于文件系统切分
+ * 新布局:EROFS文件系统 + EXTHEADER + HVB数据 新布局存在EXTHEADER,基于EXTHEADER获取镜像大小后进行分区切分
+ */
+ uint64_t imgSize = GetImgSize(dev, *start);
+ if (imgSize > 0) {
+ *start = AlignTo(imgSize, ALIGN_BLOCK_SIZE);
+ }
+
+ /* 获取分区大小,老分区布局:分区大小 = 镜像大小 新分区布局:分区大小 = 镜像大小 + 无镜像填充的分区空位 */
+ uint64_t totalSize = GetBlockSize(dev);
+ if (totalSize == 0) {
+ BEGET_LOGE("get block size failed.");
+ return -1;
+ }
+
+ BEGET_LOGI("total size:[%llu], used size: [%llu], empty size:[%llu] on dev: [%s]",
+ totalSize, *start, totalSize - *start, dev);
+
+ if (totalSize > *start) {
+ *length = totalSize - *start;
+ } else {
+ *length = 0;
+ }
+
+ if (*length < MIN_DM_SIZE) {
+ BEGET_LOGE("empty size is too small, skip...");
+ return -1;
+ }
+
+ return 0;
+}
+
+INIT_STATIC int ConstructLinearTarget(DmVerityTarget *target, const char *dev, uint64_t mapStart, uint64_t mapLength)
+{
+ if (target == NULL || dev == NULL) {
+ return -1;
+ }
+
+ target->start = 0;
+ target->length = mapLength / SECTOR_SIZE;
+ target->paras = calloc(1, MAX_BUFFER_LEN);
+ if (target->paras == NULL) {
+ BEGET_LOGE("Failed to calloc target paras");
+ return -1;
+ }
+
+ if (snprintf_s(target->paras, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s %llu", dev, mapStart / SECTOR_SIZE) < 0) {
+ BEGET_LOGE("Failed to copy target paras.");
+ return -1;
+ }
+ target->paras_len = strlen(target->paras);
+ BEGET_LOGI("dev [%s], linearparas [%s], length [%s]", dev, target->paras, target->paras_len);
+ return 0;
+}
+
+INIT_STATIC void DestoryLinearTarget(DmVerityTarget *target)
+{
+ if (target != NULL && target->paras != NULL) {
+ free(target->paras);
+ target->paras = NULL;
+ }
+}
+
+INIT_STATIC int GetOverlayDevice(FstabItem *item, char *devRofs, const uint32_t devRofsLen,
+ char *devExt4, const uint32_t devExt4Len)
+{
+ uint64_t mapStart;
+ uint64_t mapLength;
+ char nameExt4[MAX_BUFFER_LEN] = {0};
+ char nameRofs[MAX_BUFFER_LEN] = {0};
+
+ if (access(item->deviceName, 0) < 0) {
+ BEGET_LOGE("connot access dev [%s]", item->deviceName);
+ return -1;
+ }
+
+ AllocDmName(item->mountPoint, nameRofs, MAX_BUFFER_LEN, nameExt4, MAX_BUFFER_LEN);
+
+ if (GetMapperAddr(item->deviceName, &mapStart, &mapLength)) {
+ BEGET_LOGE("get mapper addr failed, dev is [%s]", item->deviceName);
+ return -1;
+ }
+
+ DmVerityTarget dmRofsTarget = {0};
+ DmVerityTarget dmExt4Target = {0};
+
+ int rc = ConstructLinearTarget(&dmRofsTarget, item->deviceName, 0, mapStart);
+ if (rc != 0) {
+ BEGET_LOGE("fs construct erofs linear target failed, dev is [%s]", item->deviceName);
+ goto exit;
+ }
+ rc = FsDmCreateLinearDevice(nameRofs, devRofs, devRofsLen, &dmRofsTarget);
+ if (rc != 0) {
+ BEGET_LOGE("fs create erofs linear device failed, dev is [%s]", item->deviceName);
+ goto exit;
+ }
+
+ rc = ConstructLinearTarget(&dmExt4Target, item->deviceName, mapStart, mapLength);
+ if (rc != 0) {
+ BEGET_LOGE("fs construct ext4 linear target failed, dev is [%s]", item->deviceName);
+ goto exit;
+ }
+ rc = FsDmCreateLinearDevice(nameExt4, devExt4, devExt4Len, &dmExt4Target);
+ if (rc != 0) {
+ BEGET_LOGE("fs create ext4 linear device failed, dev is [%s]", item->deviceName);
+ goto exit;
+ }
+ BEGET_LOGI("get overlay device success , dev is [%s]", item->deviceName);
+exit:
+ DestoryLinearTarget(&dmRofsTarget);
+ DestoryLinearTarget(&dmExt4Target);
+ return rc;
+}
+
+INIT_STATIC int MountRofsDevice(const char *dev, const char *mnt)
+{
+ int rc = 0;
+ int retryCount = 3;
+ while (retryCount-- > 0) {
+ rc = mount(dev, mnt, "erofs", MS_RDONLY, NULL);
+ if (rc && (errno != EBUSY)) {
+ BEGET_LOGI("mount erofs dev [%s] on mnt [%s] failed, retry", dev, mnt);
+ sleep(1);
+ continue;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int MountExt4Device(const char *dev, const char *mnt, bool isFirstMount)
+{
+ int ret = 0;
+ char dirExt4[MAX_BUFFER_LEN] = {0};
+ char dirUpper[MAX_BUFFER_LEN] = {0};
+ char dirWork[MAX_BUFFER_LEN] = {0};
+ ret = snprintf_s(dirExt4, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, PREFIX_OVERLAY"%s", mnt);
+ if (ret < 0) {
+ BEGET_LOGE("dirExt4 copy failed errno %d.", errno);
+ return -1;
+ }
+
+ ret = snprintf_s(dirUpper, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, PREFIX_OVERLAY"%s"PREFIX_UPPER, mnt);
+ if (ret < 0) {
+ BEGET_LOGE("dirUpper copy failed errno %d.", errno);
+ return -1;
+ }
+
+ ret = snprintf_s(dirWork, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, PREFIX_OVERLAY"%s"PREFIX_WORK, mnt);
+ if (ret < 0) {
+ BEGET_LOGE("dirWork copy failed errno %d.", errno);
+ return -1;
+ }
+
+ if (mkdir(dirExt4, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir %s failed.", dirExt4);
+ return -1;
+ }
+
+ int retryCount = 3;
+ while (retryCount-- > 0) {
+ ret = mount(dev, dirExt4, "ext4", MS_NOATIME | MS_NODEV, NULL);
+ if (ret && (errno != EBUSY)) {
+ BEGET_LOGI("mount ext4 dev [%s] on mnt [%s] failed, retry", dev, dirExt4);
+ sleep(1);
+ continue;
+ }
+ break;
+ }
+
+ if (isFirstMount && mkdir(dirUpper, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir dirUpper:%s failed.", dirUpper);
+ return -1;
+ }
+
+ if (isFirstMount && mkdir(dirWork, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir dirWork:%s failed.", dirWork);
+ return -1;
+ }
+
+ return ret;
+}
+
+INIT_STATIC void UnlinkMountPoint(const char *mountPoint)
+{
+ struct stat statInfo;
+ if (!lstat(mountPoint, &statInfo)) {
+ if ((statInfo.st_mode & S_IFMT) == S_IFLNK) {
+ unlink(mountPoint);
+ }
+ }
+}
+
+INIT_STATIC int MountPartitionDevice(FstabItem *item, const char *devRofs, const char *devExt4)
+{
+ UnlinkMountPoint(item->mountPoint);
+ if (mkdir(item->mountPoint, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir mountPoint:%s failed.errno %d", item->mountPoint, errno);
+ return -1;
+ }
+
+ WaitForFile(devRofs, WAIT_MAX_SECOND);
+ WaitForFile(devExt4, WAIT_MAX_SECOND);
+
+ if (MountRofsDevice(devRofs, item->mountPoint)) {
+ BEGET_LOGE("mount erofs dev [%s] on mnt [%s] failed", devRofs, item->mountPoint);
+ return -1;
+ }
+
+ if (strcmp(item->mountPoint, "/usr") == 0) {
+ SwitchRoot("/usr");
+ }
+
+ if (mkdir(PREFIX_LOWER, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir /lower failed. errno: %d", errno);
+ return -1;
+ }
+
+ if (mkdir(PREFIX_OVERLAY, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir /overlay failed. errno: %d", errno);
+ return -1;
+ }
+
+ char dirLower[MAX_BUFFER_LEN] = {0};
+ if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s", PREFIX_LOWER, item->mountPoint) < 0) {
+ BEGET_LOGE("dirLower[%s]copy failed errno %d.", dirLower, errno);
+ return -1;
+ }
+
+ if (mkdir(dirLower, MODE_MKDIR) && (errno != EEXIST)) {
+ BEGET_LOGE("mkdir dirLower[%s] failed. errno: %d", dirLower, errno);
+ return -1;
+ }
+
+ if (MountRofsDevice(devRofs, dirLower)) {
+ BEGET_LOGE("mount erofs dev [%s] on mnt [%s] failed", devRofs, dirLower);
+ return -1;
+ }
+
+ if (!CheckIsExt4(devExt4, 0)) {
+ BEGET_LOGI("is not ext4 devExt4 [%s] on mnt [%s]", devExt4, item->mountPoint);
+ return 0;
+ }
+
+ BEGET_LOGI("is ext4 devExt4 [%s] on mnt [%s]", devExt4, item->mountPoint);
+ if (MountExt4Device(devExt4, item->mountPoint, false)) {
+ BEGET_LOGE("mount ext4 dev [%s] on mnt [%s] failed", devExt4, item->mountPoint);
+ return -1;
+ }
+
+ return 0;
+}
+
+int DoMountOverlayDevice(FstabItem *item)
+{
+ char devRofs[MAX_BUFFER_LEN] = {0};
+ char devExt4[MAX_BUFFER_LEN] = {0};
+ int rc = 0;
+ rc = GetOverlayDevice(item, devRofs, MAX_BUFFER_LEN, devExt4, MAX_BUFFER_LEN);
+ if (rc) {
+ BEGET_LOGE("get overlay device failed, source [%s] target [%s]", item->deviceName, item->mountPoint);
+ return -1;
+ }
+
+ rc = FsDmInitDmDev(devRofs, true);
+ if (rc) {
+ BEGET_LOGE("init erofs dm dev failed");
+ return -1;
+ }
+
+ rc = FsDmInitDmDev(devExt4, true);
+ if (rc) {
+ BEGET_LOGE("init ext4 dm dev failed");
+ return -1;
+ }
+
+ rc = MountPartitionDevice(item, devRofs, devExt4);
+ if (rc) {
+ BEGET_LOGE("init ext4 dm dev failed");
+ return -1;
+ }
+ return rc;
+}
\ No newline at end of file
diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..b11df82831eb7d4361b3167d3ace6d4baaf8f6f1
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024-2024 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 "securec.h"
+#include "init_utils.h"
+
+#include "erofs_overlay_common.h"
+
+bool IsOverlayEnable(void)
+{
+ char oemMode[MAX_BUFFER_LEN] = {0};
+ int ret = GetExactParameterFromCmdLine("oemmode", oemMode, MAX_BUFFER_LEN, EMPTY_VALUE);
+ if (ret) {
+ BEGET_LOGE("Failed get oenmode from cmdline.");
+ return false;
+ }
+
+ char buildvariant[MAX_BUFFER_LEN] = {0};
+ ret = GetExactParameterFromCmdLine("buildvariant", buildvariant, MAX_BUFFER_LEN, EMPTY_VALUE);
+ if (ret) {
+ BEGET_LOGE("Failed get buildvariant from cmdline.");
+ return false;
+ }
+
+ if (strcmp(oemMode, "user") == 0 || strcmp(buildvariant, "eng") != 0) {
+ BEGET_LOGI("not support overlay, oemMode:[%s] buildvariant:[%s]", oemMode, buildvariant);
+ return false;
+ }
+ BEGET_LOGI("overlay enable.");
+ return true;
+}
+
+bool CheckIsExt4(const char *dev, uint64_t offset)
+{
+ int fd = open(dev, O_RDONLY | O_LARGEFILE);
+ if (fd < 0) {
+ BEGET_LOGE("cannot open [dev]:%s", dev);
+ return false;
+ }
+
+ if (lseek(fd, offset + EXT4_SUPER_BLOCK_START_POSITION, SEEK_SET) < 0) {
+ BEGET_LOGE("cannot seek [dev]:%s", dev);
+ close(fd);
+ return false;
+ }
+ ext4_super_block superBlock;
+ ssize_t nbytes = read(fd, &superBlock, sizeof(superBlock));
+ if (nbytes != sizeof(superBlock)) {
+ BEGET_LOGE("read ext4 super block fail");
+ close(fd);
+ return false;
+ }
+
+ if (superBlock.s_magic == EXT4_SUPER_MAGIC) {
+ BEGET_LOGI("this [dev] %s is ext4:[block cout]: %d, [size]: %d", dev,
+ superBlock.s_blocks_count_lo, (superBlock.s_blocks_count_lo * BLOCK_SIZE_UNIT));
+ close(fd);
+ return true;
+ }
+ close(fd);
+ return false;
+}
+
+bool CheckIsErofs(const char *dev)
+{
+ int fd = open(dev, O_RDONLY | O_LARGEFILE);
+ if (fd < 0) {
+ BEGET_LOGE("cannot open [dev]:%s", dev);
+ return false;
+ }
+
+ if (lseek(fd, EROFS_SUPER_BLOCK_START_POSITION, SEEK_SET) < 0) {
+ BEGET_LOGE("cannot seek [dev]:%s", dev);
+ close(fd);
+ return false;
+ }
+ struct erofs_super_block superBlock;
+ ssize_t nbytes = read(fd, &superBlock, sizeof(superBlock));
+ if (nbytes != sizeof(superBlock)) {
+ BEGET_LOGE("read erofs super block fail");
+ close(fd);
+ return false;
+ }
+
+ BEGET_LOGI("the [dev] %s magic [%u]", dev, superBlock.magic);
+ if (superBlock.magic == EROFS_SUPER_MAGIC) {
+ BEGET_LOGI("this [dev] %s is erofs", dev);
+ close(fd);
+ return true;
+ }
+ close(fd);
+ return false;
+}
\ No newline at end of file
diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c
new file mode 100644
index 0000000000000000000000000000000000000000..da52dd2ee6ce858647555e3b65993df6718ddbb2
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2024-2024 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 "securec.h"
+#include "init_utils.h"
+#include "fs_dm.h"
+#include "fs_manager/fs_manager.h"
+#include "erofs_remount_overlay.h"
+
+int GetRemountResult(void)
+{
+ int fd = open(REMOUNT_RESULT_FLAG, O_RDONLY);
+ if (fd >= 0) {
+ char buff[1];
+ int ret = read(fd, buff, 1);
+ if (ret < 0) {
+ BEGET_LOGE("read remount.result.done failed errno %d", errno);
+ close(fd);
+ return REMOUNT_FAIL;
+ }
+ close(fd);
+ if (buff[0] == '0' + REMOUNT_SUCC) {
+ return REMOUNT_SUCC;
+ }
+ }
+ return REMOUNT_FAIL;
+}
+
+void SetRemountResultFlag()
+{
+ struct stat st;
+ int ret;
+
+ int statRet = stat(REMOUNT_RESULT_PATH, &st);
+ if (statRet != 0) {
+ ret = mkdir(REMOUNT_RESULT_PATH, MODE_MKDIR);
+ if (ret < 0 && errno != EEXIST) {
+ BEGET_LOGE("mkdir remount path failed errno %d", errno);
+ return;
+ }
+ }
+
+ int fd = open(REMOUNT_RESULT_FLAG, O_WRONLY | O_CREAT, 0644);
+ if (fd < 0) {
+ BEGET_LOGE("open remount.result.done failed errno %d", errno);
+ return;
+ }
+
+ char buff[1];
+ buff[0] = '0' + REMOUNT_SUCC;
+
+ ret = write(fd, buff, 1);
+ if (ret < 0) {
+ BEGET_LOGE("write buff failed errno %d", errno);
+ }
+ close(fd);
+ BEGET_LOGI("set remount result flag successfully");
+}
+
+INIT_STATIC int Modem2Exchange(const char *modemPath, const char *exchangePath)
+{
+ int ret;
+ ret = mkdir(exchangePath, MODE_MKDIR);
+ if (ret) {
+ BEGET_LOGE("mkdir %s failed.", exchangePath);
+ } else {
+ BEGET_LOGI("mkdir %s succeed.", exchangePath);
+ }
+
+ ret = mount(modemPath, exchangePath, NULL, MS_BIND | MS_RDONLY, NULL);
+ if (ret) {
+ BEGET_LOGE("bind %s to %s failed.", modemPath, exchangePath);
+ } else {
+ BEGET_LOGI("bind %s to %s succeed.", modemPath, exchangePath);
+ }
+
+ return ret;
+}
+
+INIT_STATIC int Exchange2Modem(const char *modemPath, const char *exchangePath)
+{
+ int ret;
+ struct stat statInfo;
+ if (lstat(exchangePath, &statInfo)) {
+ BEGET_LOGE("no exchangePath %s.", exchangePath);
+ return 0;
+ }
+
+ ret = mount(exchangePath, modemPath, NULL, MS_BIND | MS_RDONLY, NULL);
+ if (ret) {
+ BEGET_LOGE("bind %s to %s failed.", exchangePath, modemPath);
+ } else {
+ BEGET_LOGI("bind %s to %s succeed.", exchangePath, modemPath);
+ }
+
+ ret = umount(exchangePath);
+ if (ret) {
+ BEGET_LOGE("umount %s failed.", exchangePath);
+ } else {
+ BEGET_LOGI("umount %s succeed.", exchangePath);
+ }
+
+ ret = remove(exchangePath);
+ if (ret) {
+ BEGET_LOGE("remove %s failed.", exchangePath);
+ } else {
+ BEGET_LOGI("remove %s succeed.", exchangePath);
+ }
+
+ return ret;
+}
+
+void OverlayRemountVendorPre(void)
+{
+ struct stat statInfo;
+
+ if (!stat(MODEM_DRIVER_MNT_PATH, &statInfo)) {
+ Modem2Exchange(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH);
+ }
+
+ if (!stat(MODEM_VENDOR_MNT_PATH, &statInfo)) {
+ Modem2Exchange(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH);
+ }
+
+ if (!stat(MODEM_FW_MNT_PATH, &statInfo)) {
+ Modem2Exchange(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH);
+ }
+}
+
+void OverlayRemountVendorPost()
+{
+ Exchange2Modem(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH);
+ Exchange2Modem(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH);
+ Exchange2Modem(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH);
+}
+
+int MountOverlayOne(const char *mnt)
+{
+ if ((strcmp(mnt, MODEM_DRIVER_MNT_PATH) == 0) || (strcmp(mnt, MODEM_VENDOR_MNT_PATH) == 0)) {
+ return 0;
+ }
+ char dirLower[MAX_BUFFER_LEN] = {0};
+ char dirUpper[MAX_BUFFER_LEN] = {0};
+ char dirWork[MAX_BUFFER_LEN] = {0};
+ char mntOpt[MAX_BUFFER_LEN] = {0};
+
+ if (strcmp(mnt, "/usr") == 0) {
+ if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s", "/system") < 0) {
+ BEGET_LOGE("copy system dirLower failed. errno %d", errno);
+ return -1;
+ }
+ } else {
+ if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s", PREFIX_LOWER, mnt) < 0) {
+ BEGET_LOGE("copy dirLower failed. errno %d", errno);
+ return -1;
+ }
+ }
+
+ if (snprintf_s(dirUpper, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_UPPER) < 0) {
+ BEGET_LOGE("copy dirUpper failed. errno %d", errno);
+ return -1;
+ }
+
+ if (snprintf_s(dirWork, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_WORK) < 0) {
+ BEGET_LOGE("copy dirWork failed. errno %d", errno);
+ return -1;
+ }
+
+ if (snprintf_s(mntOpt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1,
+ "upperdir=%s,lowerdir=%s,workdir=%s,override_creds=off", dirUpper, dirLower, dirWork) < 0) {
+ BEGET_LOGE("copy mntOpt failed. errno %d", errno);
+ return -1;
+ }
+
+ if (strcmp(mnt, "/usr") == 0) {
+ if (mount("overlay", "/system", "overlay", 0, mntOpt)) {
+ BEGET_LOGE("mount system overlay failed. errno %d", errno);
+ return -1;
+ }
+ } else {
+ if (mount("overlay", mnt, "overlay", 0, mntOpt)) {
+ BEGET_LOGE("mount overlay fs failed. errno %d", errno);
+ return -1;
+ }
+ }
+ BEGET_LOGI("mount overlay fs success on mnt:%s", mnt);
+ return 0;
+}
+
+int RemountOverlay(void)
+{
+ char *remountPath[] = {
+ "/usr", "/vendor", "/sys_prod", "/chip_prod", "/preload", "/cust", "/version", "/patch_hw"
+ };
+ for (size_t i = 0; i < ARRAY_LENGTH(remountPath); i++) {
+ struct stat statInfo;
+ char dirMnt[MAX_BUFFER_LEN] = {0};
+ if (snprintf_s(dirMnt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "/mnt/overlay%s/upper", remountPath[i]) < 0) {
+ BEGET_LOGE("copy dirMnt [%s] failed.", dirMnt);
+ return -1;
+ }
+
+ if (lstat(dirMnt, &statInfo)) {
+ BEGET_LOGW("dirMnt [%s] not exist.", dirMnt);
+ continue;
+ }
+
+ if (strcmp(remountPath[i], "/vendor") == 0) {
+ OverlayRemountVendorPre();
+ }
+
+ if (MountOverlayOne(remountPath[i])) {
+ BEGET_LOGE("mount overlay failed on mnt [%s].", dirMnt);
+ return -1;
+ }
+
+ if (strcmp(remountPath[i], "/vendor") == 0) {
+ OverlayRemountVendorPost();
+ }
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/services/include/init_read_cfg.h b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_mount_overlay.h
similarity index 62%
rename from services/include/init_read_cfg.h
rename to interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_mount_overlay.h
index 4cb57e130f98b570e9bb792492d3026ad04b1f93..591451e519f023edd8318770f8d83c92bf2609e0 100644
--- a/services/include/init_read_cfg.h
+++ b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_mount_overlay.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -13,20 +13,21 @@
* limitations under the License.
*/
-#ifndef BASE_STARTUP_INITLITE_READ_CFG_H
-#define BASE_STARTUP_INITLITE_READ_CFG_H
+#ifndef EROFS_MOUNT_OVERLAY_H
+#define EROFS_MOUNT_OVERLAY_H
+
+#include "fs_manager/fs_manager.h"
+#include "erofs_overlay_common.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
-#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
-#define MAX_PATH_ARGS_CNT 20
-#define MAX_ONE_ARG_LEN 200 // max length of one param/path
-void InitReadCfg();
-void ParseInitCfg(const char *configFile);
+int DoMountOverlayDevice(FstabItem *item);
+
+int MountExt4Device(const char *dev, const char *mnt, bool isFirstMount);
#ifdef __cplusplus
#if __cplusplus
@@ -34,4 +35,4 @@ void ParseInitCfg(const char *configFile);
#endif
#endif
-#endif // BASE_STARTUP_INITLITE_READ_CFG_H
+#endif // EROFS_MOUNT_OVERLAY_H
diff --git a/ueventd/list.h b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_overlay_common.h
old mode 100755
new mode 100644
similarity index 50%
rename from ueventd/list.h
rename to interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_overlay_common.h
index 06eaaff05d799f7c4c5f2f7c172c09fa69f8d841..71c9def506f33c4b6967791b4a84cf678ca8958d
--- a/ueventd/list.h
+++ b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_overlay_common.h
@@ -1,44 +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 BASE_STARTUP_INITLITE_LIST_H
-#define BASE_STARTUP_INITLITE_LIST_H
-
-#ifdef __cplusplus
-#if __cplusplus
-extern "C" {
-#endif
-#endif
-
-typedef struct ListNode {
- struct ListNode *next;
- struct ListNode *prev;
-} ListNode;
-
-#define ListEmpty(node) ((node).next == &(node) && (node).prev == &(node))
-#define ListEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member))
-#define ForEachListEntry(list, node) \
- for (node = (list)->next; node != (list); node = node->next)
-
-void ListInit(struct ListNode *list);
-void ListAddTail(struct ListNode *list, struct ListNode *item);
-void ListRemove(struct ListNode *item);
-#ifdef __cplusplus
-#if __cplusplus
-}
-#endif
-#endif
-
-#endif // BASE_STARTUP_INITLITE_LIST_H
+/*
+ * Copyright (c) 2024-2024 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 EROFS_OVERLAY_COMMON_H
+#define EROFS_OVERLAY_COMMON_H
+
+#include
+#include
+#include "fs_manager/ext4_super_block.h"
+#include "fs_manager/erofs_super_block.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define MODE_MKDIR 0755
+#define EXT4_SUPER_MAGIC 0xEF53
+#define EXT4_SUPER_OFFSET 0x400
+#define SECTOR_SIZE 512
+#define PREFIX_LOWER "/mnt/lower"
+#define PREFIX_OVERLAY "/mnt/overlay"
+#define PREFIX_UPPER "/upper"
+#define PREFIX_WORK "/work"
+
+bool IsOverlayEnable(void);
+
+bool CheckIsExt4(const char *dev, uint64_t offset);
+
+bool CheckIsErofs(const char *dev);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_remount_overlay.h b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_remount_overlay.h
new file mode 100644
index 0000000000000000000000000000000000000000..99f6e3102fe947c38392bdb3e69598b3920ac538
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_remount_overlay.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024-2024 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 EROFS_REMOUNT_OVERLAY_H
+#define EROFS_REMOUNT_OVERLAY_H
+
+#include "erofs_overlay_common.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define MODEM_DRIVER_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_driver"
+#define MODEM_VENDOR_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_vendor"
+#define MODEM_FW_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_fw"
+#define MODEM_DRIVER_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/driver_exchange"
+#define MODEM_VENDOR_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/vendor_exchange"
+#define MODEM_FW_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/fw_exchange"
+#define REMOUNT_RESULT_PATH STARTUP_INIT_UT_PATH"/data/service/el1/startup/remount/"
+#define REMOUNT_RESULT_FLAG STARTUP_INIT_UT_PATH"/data/service/el1/startup/remount/remount.result.done"
+
+#define REMOUNT_SUCC 0
+#define REMOUNT_FAIL 1
+
+int GetRemountResult(void);
+
+void SetRemountResultFlag();
+
+int RemountOverlay(void);
+
+int MountOverlayOne(const char *mnt);
+
+void OverlayRemountVendorPre(void);
+
+void OverlayRemountVendorPost(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // EROFS_REMOUNT_OVERLAY_H
diff --git a/interfaces/innerkits/fs_manager/fstab.c b/interfaces/innerkits/fs_manager/fstab.c
new file mode 100644
index 0000000000000000000000000000000000000000..8baad448fd7cfa8ffac1608b42ae287f3cf18761
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/fstab.c
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "beget_ext.h"
+#include "fs_manager/fs_manager.h"
+#include "init_utils.h"
+#include "securec.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define CMDLINE_LABEL_FSCRYPT_DISABLE "ohos.init.fscrypt.disable"
+#define CMDLINE_VALUE_FSCRYPT_DISABLE "disabled"
+#define CMDLINE_VALUE_LEN (sizeof(CMDLINE_VALUE_FSCRYPT_DISABLE) - 1)
+struct FsManagerFlags {
+ char *name;
+ unsigned int flags;
+};
+
+struct MountFlags {
+ char *name;
+ unsigned long flags;
+};
+
+static char *g_fscryptPolicy = NULL;
+
+static unsigned int ConvertFlags(char *flagBuffer)
+{
+ static struct FsManagerFlags fsFlags[] = {
+ {"check", FS_MANAGER_CHECK},
+ {"wait", FS_MANAGER_WAIT},
+ {"required", FS_MANAGER_REQUIRED},
+ {"nofail", FS_MANAGER_NOFAIL},
+#ifdef SUPPORT_HVB
+ {"hvb", FS_MANAGER_HVB},
+#endif
+ {"fsprojquota", FS_MANAGER_PROJQUOTA},
+ {"fscasefold", FS_MANAGER_CASEFOLD},
+ {"fscompression", FS_MANAGER_COMPRESSION},
+ {"fsdedup", FS_MANAGER_DEDUP},
+ {"formattable", FS_MANAGER_FORMATTABLE},
+ };
+
+ BEGET_CHECK_RETURN_VALUE(flagBuffer != NULL && *flagBuffer != '\0', 0); // No valid flags.
+ int flagCount = 0;
+ unsigned int flags = 0;
+ const int maxCount = 3;
+ char **vector = SplitStringExt(flagBuffer, ",", &flagCount, maxCount);
+ BEGET_CHECK_RETURN_VALUE(vector != NULL && flagCount != 0, 0);
+ for (size_t i = 0; i < ARRAY_LENGTH(fsFlags); i++) {
+ for (int j = 0; j < flagCount; j++) {
+ if (strcmp(fsFlags[i].name, vector[j]) == 0) {
+ flags |= fsFlags[i].flags;
+ }
+ }
+ }
+ FreeStringVector(vector, flagCount);
+ return flags;
+}
+
+static int AddToFstab(Fstab *fstab, FstabItem *item)
+{
+ if (fstab == NULL || item == NULL) {
+ return -1;
+ }
+ if (fstab->tail == NULL) {
+ fstab->head = fstab->tail = item;
+ } else {
+ fstab->tail->next = item;
+ fstab->tail = item;
+ }
+ return 0;
+}
+
+void ReleaseFstabItem(FstabItem *item)
+{
+ if (item != NULL) {
+ if (item->deviceName != NULL) {
+ free(item->deviceName);
+ item->deviceName = NULL;
+ }
+
+ if (item->mountPoint != NULL) {
+ free(item->mountPoint);
+ item->mountPoint = NULL;
+ }
+
+ if (item->fsType != NULL) {
+ free(item->fsType);
+ item->fsType = NULL;
+ }
+
+ if (item->mountOptions != NULL) {
+ free(item->mountOptions);
+ item->mountOptions = NULL;
+ }
+
+ free(item);
+ }
+}
+
+void ReleaseFstab(Fstab *fstab)
+{
+ if (fstab != NULL) {
+ FstabItem *item = fstab->head;
+ while (item != NULL) {
+ FstabItem *tmp = item->next;
+ ReleaseFstabItem(item);
+ item = tmp;
+ }
+ fstab->head = fstab->tail = NULL;
+ free(fstab);
+ fstab = NULL;
+ }
+}
+
+int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator)
+{
+ BEGET_CHECK_RETURN_VALUE(str != NULL && fstab != NULL, -1);
+ char *rest = NULL;
+ FstabItem *item = NULL;
+ char *p = NULL;
+ BEGET_ERROR_CHECK(separator != NULL && *separator != '\0', return -1, "Invalid separator for parsing fstab");
+
+ if ((item = (FstabItem *)calloc(1, sizeof(FstabItem))) == NULL) {
+ errno = ENOMEM;
+ BEGET_LOGE("Allocate memory for FS table item failed, err = %d", errno);
+ return -1;
+ }
+
+ do {
+ BEGET_ERROR_CHECK((p = strtok_r(str, separator, &rest)) != NULL, break, "Failed to parse block device.");
+ item->deviceName = strdup(p);
+ BEGET_ERROR_CHECK(item->deviceName != NULL, break, "strdup deviceName failed.");
+
+ BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse mount point.");
+ item->mountPoint = strdup(p);
+ BEGET_ERROR_CHECK(item->mountPoint != NULL, break, "strdup mountPoint failed.");
+
+ BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse fs type.");
+ item->fsType = strdup(p);
+ BEGET_ERROR_CHECK(item->fsType != NULL, break, "strdup fsType failed.");
+
+ BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse mount options.");
+ item->mountOptions = strdup(p);
+ BEGET_ERROR_CHECK(item->mountOptions != NULL, break, "strdup mountOptions failed.");
+
+ if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
+ BEGET_LOGE("Failed to parse fs manager flags.");
+ break;
+ }
+ // @fsManagerFlags only for fstab
+ // Ignore it if we read from /proc/mounts
+ if (!procMounts) {
+ item->fsManagerFlags = ConvertFlags(p);
+ } else {
+ item->fsManagerFlags = 0;
+ }
+ return AddToFstab(fstab, item);
+ } while (0);
+
+ ReleaseFstabItem(item);
+ item = NULL;
+ return -1;
+}
+
+Fstab *ReadFstabFromFile(const char *file, bool procMounts)
+{
+ char *line = NULL;
+ size_t allocn = 0;
+ ssize_t readn = 0;
+ Fstab *fstab = NULL;
+
+ FILE *fp = NULL;
+ char *realPath = GetRealPath(file);
+ if (realPath != NULL) {
+ fp = fopen(realPath, "r");
+ free(realPath);
+ } else {
+ fp = fopen(file, "r"); // no file system, can not get real path
+ }
+ BEGET_ERROR_CHECK(fp != NULL, return NULL, "Open %s failed, err = %d", file, errno);
+
+ if ((fstab = (Fstab *)calloc(1, sizeof(Fstab))) == NULL) {
+ BEGET_LOGE("Allocate memory for FS table failed, err = %d", errno);
+ fclose(fp);
+ fp = NULL;
+ return NULL;
+ }
+
+ // Record line number of fstab file
+ size_t ln = 0;
+ while ((readn = getline(&line, &allocn, fp)) != -1) {
+ char *p = NULL;
+ ln++;
+ if (line[readn - 1] == '\n') {
+ line[readn - 1] = '\0';
+ }
+ p = line;
+ while (isspace(*p)) {
+ p++;
+ }
+
+ if (*p == '\0' || *p == '#') {
+ continue;
+ }
+
+ if (ParseFstabPerLine(p, fstab, procMounts, " \t") < 0) {
+ if (errno == ENOMEM) {
+ // Ran out of memory, there is no reason to continue.
+ break;
+ }
+ // If one line in fstab file parsed with a failure. just give a warning
+ // and skip it.
+ BEGET_LOGW("Cannot parse file \" %s \" at line %zu. skip it", file, ln);
+ continue;
+ }
+ }
+ if (line != NULL) {
+ free(line);
+ }
+ (void)fclose(fp);
+ fp = NULL;
+ return fstab;
+}
+
+FstabItem *FindFstabItemForMountPoint(Fstab fstab, const char *mp)
+{
+ FstabItem *item = NULL;
+ if (mp != NULL) {
+ for (item = fstab.head; item != NULL; item = item->next) {
+ if ((item->mountPoint != NULL) && (strcmp(item->mountPoint, mp) == 0)) {
+ break;
+ }
+ }
+ }
+ return item;
+}
+
+FstabItem *FindFstabItemForPath(Fstab fstab, const char *path)
+{
+ FstabItem *item = NULL;
+
+ if (path == NULL || *path != '/') {
+ return NULL;
+ }
+
+ char tmp[PATH_MAX] = {0};
+ char *dir = NULL;
+ if (strncpy_s(tmp, PATH_MAX - 1, path, strlen(path)) != EOK) {
+ BEGET_LOGE("Failed to copy path.");
+ return NULL;
+ }
+
+ dir = tmp;
+ while (true) {
+ item = FindFstabItemForMountPoint(fstab, dir);
+ if (item != NULL) {
+ break;
+ }
+ dir = dirname(dir);
+ // Reverse walk through path and met "/", just quit.
+ if (dir == NULL || strcmp(dir, "/") == 0) {
+ break;
+ }
+ }
+ return item;
+}
+
+static char *GetFstabFile(char *fileName, size_t size)
+{
+ if (InUpdaterMode() == 1) {
+ if (strncpy_s(fileName, size, "/etc/fstab.updater", strlen("/etc/fstab.updater")) != 0) {
+ BEGET_LOGE("Failed strncpy_s err=%d", errno);
+ return NULL;
+ }
+ } else {
+ char hardware[MAX_BUFFER_LEN] = {0};
+ int ret = GetParameterFromCmdLine("hardware", hardware, MAX_BUFFER_LEN);
+ if (ret != 0) {
+ BEGET_LOGE("Failed get hardware from cmdline");
+ return NULL;
+ }
+ if (snprintf_s(fileName, size, size - 1, "/vendor/etc/fstab.%s", hardware) == -1) {
+ BEGET_LOGE("Failed to build fstab file, err=%d", errno);
+ return NULL;
+ }
+ }
+ BEGET_LOGI("fstab file is %s", fileName);
+ return fileName;
+}
+
+int GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char *deviceName, int nameLen)
+{
+ if (fstab == NULL || mountPoint == NULL || *mountPoint == '\0' || deviceName == NULL) {
+ return -1;
+ }
+ FstabItem *item = FindFstabItemForMountPoint(*fstab, mountPoint);
+ if (item == NULL) {
+ BEGET_LOGE("Failed to get fstab item from mount point \" %s \"", mountPoint);
+ return -1;
+ }
+ if (strncpy_s(deviceName, nameLen, item->deviceName, strlen(item->deviceName)) != 0) {
+ BEGET_LOGE("Failed to copy block device name, err=%d", errno);
+ return -1;
+ }
+ return 0;
+}
+
+int GetBlockDeviceByName(const char *deviceName, const Fstab *fstab, char* miscDev, size_t size)
+{
+ for (FstabItem *item = fstab->head; item != NULL; item = item->next) {
+ if (strstr(item->deviceName, deviceName) != NULL) {
+ BEGET_CHECK_RETURN_VALUE(strcpy_s(miscDev, size, item->deviceName) != 0, 0);
+ }
+ }
+ return -1;
+}
+
+static const struct MountFlags MOUNT_FLAGS[] = {
+ { "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 },
+};
+
+static bool IsDefaultMountFlags(const char *str)
+{
+ bool isDefault = false;
+
+ if (str != NULL) {
+ for (size_t i = 0; i < ARRAY_LENGTH(MOUNT_FLAGS); i++) {
+ if (strcmp(str, MOUNT_FLAGS[i].name) == 0) {
+ isDefault = true;
+ }
+ }
+ }
+ return isDefault;
+}
+
+static unsigned long ParseDefaultMountFlag(const char *str)
+{
+ unsigned long flags = 0;
+
+ if (str != NULL) {
+ for (size_t i = 0; i < ARRAY_LENGTH(MOUNT_FLAGS); i++) {
+ if (strcmp(str, MOUNT_FLAGS[i].name) == 0) {
+ flags = MOUNT_FLAGS[i].flags;
+ break;
+ }
+ }
+ }
+ return flags;
+}
+
+static bool IsFscryptOption(const char *option)
+{
+ if (!option) {
+ return false;
+ }
+ char *fscryptPre = "fscrypt=";
+ if (strncmp(option, fscryptPre, strlen(fscryptPre)) == 0) {
+ return true;
+ }
+ return false;
+}
+
+static void StoreFscryptPolicy(const char *option)
+{
+ if (option == NULL) {
+ return;
+ }
+
+ char fscryptDisable[CMDLINE_VALUE_LEN_MAX] = {0};
+ int ret = GetParameterFromCmdLine(CMDLINE_LABEL_FSCRYPT_DISABLE, fscryptDisable, sizeof(fscryptDisable));
+ if (ret == 0 && strncmp(fscryptDisable,
+ CMDLINE_VALUE_FSCRYPT_DISABLE, CMDLINE_VALUE_LEN) == 0) {
+ BEGET_LOGE("fscrypt policy is disabled by cmdline");
+ return;
+ }
+
+ if (g_fscryptPolicy != NULL) {
+ BEGET_LOGW("StoreFscryptPolicy:inited policy is not empty");
+ free(g_fscryptPolicy);
+ }
+ g_fscryptPolicy = strdup(option);
+ if (g_fscryptPolicy == NULL) {
+ BEGET_LOGE("StoreFscryptPolicy:no memory");
+ return;
+ }
+ BEGET_LOGI("StoreFscryptPolicy:store fscrypt policy, %s", option);
+}
+
+int LoadFscryptPolicy(char *buf, size_t size)
+{
+ BEGET_LOGI("LoadFscryptPolicy start");
+ if (buf == NULL || g_fscryptPolicy == NULL) {
+ BEGET_LOGE("LoadFscryptPolicy:buf or fscrypt policy is empty");
+ return -ENOMEM;
+ }
+ if (size == 0) {
+ BEGET_LOGE("LoadFscryptPloicy:size is invalid");
+ return -EINVAL;
+ }
+ if (strcpy_s(buf, size, g_fscryptPolicy) != 0) {
+ BEGET_LOGE("loadFscryptPolicy:strcmp failed, error = %d", errno);
+ return -EFAULT;
+ }
+ free(g_fscryptPolicy);
+ g_fscryptPolicy = NULL;
+ BEGET_LOGI("LoadFscryptPolicy success");
+
+ return 0;
+}
+
+unsigned long GetMountFlags(char *mountFlag, char *fsSpecificData, size_t fsSpecificDataSize,
+ const char *mountPoint)
+{
+ unsigned long flags = 0;
+ BEGET_CHECK_RETURN_VALUE(mountFlag != NULL && fsSpecificData != NULL, 0);
+ int flagCount = 0;
+ // Why max count of mount flags is 15?
+ // There are lots for mount flags defined in sys/mount.h
+ // But we only support to parse 15 in @ParseDefaultMountFlags() function
+ // So set default mount flag number to 15.
+ // If the item configured in fstab contains flag over than 15,
+ // @SplitStringExt can handle it and parse them all. but the parse function will drop it.
+ const int maxCount = 15;
+ char **flagsVector = SplitStringExt(mountFlag, ",", &flagCount, maxCount);
+
+ if (flagsVector == NULL || flagCount == 0) {
+ // No flags or something wrong in SplitStringExt,just return.
+ return 0;
+ }
+
+ for (int i = 0; i < flagCount; i++) {
+ char *p = flagsVector[i];
+ if (IsDefaultMountFlags(p)) {
+ flags |= ParseDefaultMountFlag(p);
+ } else {
+ if (IsFscryptOption(p) &&
+ !strncmp(mountPoint, "/data", strlen("/data"))) {
+ StoreFscryptPolicy(p + strlen("fscrypt="));
+ continue;
+ }
+ if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, p, strlen(p)) != EOK) {
+ BEGET_LOGW("Failed to append mount flag \" %s \", ignore it.", p);
+ continue;
+ }
+ if (i == flagCount - 1) { // last flags, do not need to append ','
+ break;
+ }
+ // Combined each mount flag with ','
+ if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) {
+ BEGET_LOGW("Failed to append comma");
+ break; // If cannot add ',' to the end of flags, there is not reason to continue.
+ }
+ }
+ }
+
+ FreeStringVector(flagsVector, flagCount);
+ return flags;
+}
+
+int GetBlockDevicePath(const char *partName, char *path, size_t size)
+{
+ BEGET_CHECK_RETURN_VALUE(partName != NULL && path != NULL, -1);
+ Fstab *fstab = LoadFstabFromCommandLine();
+ if (fstab == NULL) {
+ BEGET_LOGI("fstab not found from cmdline, try to get it from file");
+ char *fstabFile = GetFstabFile(path, size);
+ BEGET_CHECK_RETURN_VALUE(fstabFile != NULL, -1);
+ fstab = ReadFstabFromFile(fstabFile, false);
+ }
+ BEGET_CHECK_RETURN_VALUE(fstab != NULL, -1);
+ int ret = GetBlockDeviceByMountPoint(partName, fstab, path, size);
+ BEGET_INFO_CHECK(ret == 0, ret = GetBlockDeviceByName(partName, fstab, path, size),
+ "Mount point not found, try to get path by device name.");
+ ReleaseFstab(fstab);
+ return ret;
+}
+
+#define OHOS_REQUIRED_MOUNT_PREFIX "ohos.required_mount."
+/*
+ * Fstab includes block device node, mount point, file system type, MNT_ Flags and options.
+ * We separate them by spaces in fstab.required file, but the separator is '@' in CmdLine.
+ * The prefix "ohos.required_mount." is the flag of required fstab information in CmdLine.
+ * Format as shown below:
+ * @@@@
+ * e.g.
+ * ohos.required_mount.system=/dev/block/xxx/by-name/system@/usr@ext4@ro,barrier=1@wait,required
+ */
+static int ParseRequiredMountInfo(const char *item, Fstab *fstab)
+{
+ char mountOptions[MAX_BUFFER_LEN] = {};
+ char partName[NAME_SIZE] = {};
+ // Sanity checks
+ BEGET_CHECK(!(item == NULL || *item == '\0' || fstab == NULL), return -1);
+
+ char *p = NULL;
+ if ((p = strstr(item, "=")) != NULL) {
+ const char *q = item + strlen(OHOS_REQUIRED_MOUNT_PREFIX); // Get partition name
+ BEGET_CHECK(!(q == NULL || *q == '\0' || (p - q) <= 0), return -1);
+ BEGET_ERROR_CHECK(strncpy_s(partName, NAME_SIZE -1, q, p - q) == EOK,
+ return -1, "Failed to copy required partition name");
+ p++; // skip '='
+ BEGET_ERROR_CHECK(strncpy_s(mountOptions, MAX_BUFFER_LEN -1, p, strlen(p)) == EOK,
+ return -1, "Failed to copy required mount info: %s", item);
+ }
+ BEGET_LOGV("Config mount option of partition %s is [%s]", partName, mountOptions);
+ if (ParseFstabPerLine(mountOptions, fstab, false, "@") < 0) {
+ BEGET_LOGE("Failed to parse mount options of partition \' %s \', options: %s", partName, mountOptions);
+ return -1;
+ }
+ return 0;
+}
+
+Fstab* LoadFstabFromCommandLine(void)
+{
+ Fstab *fstab = NULL;
+ char *cmdline = ReadFileData(BOOT_CMD_LINE);
+ bool isDone = false;
+
+ BEGET_ERROR_CHECK(cmdline != NULL, return NULL, "Read from \'%s\' failed, err = %d", BOOT_CMD_LINE, errno);
+ TrimTail(cmdline, '\n');
+ fstab = (Fstab *)calloc(1, sizeof(Fstab));
+ BEGET_ERROR_CHECK(fstab != NULL, free(cmdline); return NULL,
+ "Allocate memory for FS table failed, err = %d", errno);
+ char *start = cmdline;
+ char *end = start + strlen(cmdline);
+ while (start < end) {
+ char *token = strstr(start, " ");
+ if (token == NULL) {
+ break;
+ }
+
+ // Startswith " "
+ if (token == start) {
+ start++;
+ continue;
+ }
+ *token = '\0';
+ if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX,
+ strlen(OHOS_REQUIRED_MOUNT_PREFIX)) != 0) {
+ start = token + 1;
+ continue;
+ }
+ isDone = true;
+ if (ParseRequiredMountInfo(start, fstab) < 0) {
+ BEGET_LOGE("Failed to parse \' %s \'", start);
+ isDone = false;
+ break;
+ }
+ start = token + 1;
+ }
+
+ // handle last one
+ if (start < end) {
+ if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX,
+ strlen(OHOS_REQUIRED_MOUNT_PREFIX)) == 0 &&
+ ParseRequiredMountInfo(start, fstab) < 0) {
+ BEGET_LOGE("Failed to parse \' %s \'", start);
+ isDone = false;
+ }
+ }
+
+ if (!isDone) {
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ }
+ free(cmdline);
+ return fstab;
+}
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c
new file mode 100755
index 0000000000000000000000000000000000000000..58bd6c5263a1bfe3d8b419e14feded6be468a2b6
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/fstab_mount.c
@@ -0,0 +1,798 @@
+/*
+ * 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
+#include
+#include
+#include "beget_ext.h"
+#include "fs_manager/fs_manager.h"
+#include "init_utils.h"
+#include "param/init_param.h"
+#include "securec.h"
+#include "switch_root.h"
+#ifdef SUPPORT_HVB
+#include "fs_dm.h"
+#include "dm_verity.h"
+#endif
+#include "init_filesystems.h"
+#ifdef EROFS_OVERLAY
+#include "erofs_mount_overlay.h"
+#endif
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define FS_MANAGER_BUFFER_SIZE 512
+#define BLOCK_SIZE_BUFFER (64)
+#define RESIZE_BUFFER_SIZE 1024
+const off_t PARTITION_ACTIVE_SLOT_OFFSET = 1024;
+const off_t PARTITION_ACTIVE_SLOT_SIZE = 4;
+
+__attribute__((weak)) void InitPostMount(const char *mountPoint, int rc)
+{
+}
+
+__attribute__((weak)) void InitTimerControl(bool isSuspend)
+{
+}
+
+__attribute__((weak)) bool NeedDoAllResize(const unsigned int fsManagerFlags)
+{
+ BEGET_LOGW("kdump: static");
+ return true;
+}
+
+static const SUPPORTED_FILE_SYSTEM supportedFileSystems[] = {
+ { "ext4", 0 },
+ { "f2fs", 1 },
+ { "overlay", 0 },
+ { NULL, 0 }
+};
+
+static void **extendedFileSystems_ = NULL;
+
+void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[])
+{
+ extendedFileSystems_ = (void **)extendedFileSystems;
+}
+
+static const SUPPORTED_FILE_SYSTEM *GetSupportedFileSystemInfo(const char *fsType)
+{
+ return (const SUPPORTED_FILE_SYSTEM *)OH_ExtendableStrDictGet((void **)supportedFileSystems,
+ sizeof(SUPPORTED_FILE_SYSTEM), fsType, 0, extendedFileSystems_);
+}
+
+static bool IsSupportedDataType(const char *fsType)
+{
+ const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType);
+ if (item == NULL) {
+ return false;
+ }
+ if (item->for_userdata) {
+ return true;
+ }
+ return false;
+}
+
+bool IsSupportedFilesystem(const char *fsType)
+{
+ const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType);
+ if (item == NULL) {
+ return false;
+ }
+ return true;
+}
+
+/* 1024(stdout buffer size) - 256(log tag max size approximately) */
+#define LOG_LINE_SZ 768
+#define PIPE_FDS 2
+
+static void LogToKmsg(int fd)
+{
+ char buffer[LOG_LINE_SZ] = {0};
+ int lineMaxSize = LOG_LINE_SZ - 1;
+ int pos = 0;
+
+ do {
+ ssize_t lineSize = read(fd, buffer, lineMaxSize);
+ if (lineSize < 0) {
+ BEGET_LOGE("Failed to read, errno: %d", errno);
+ break;
+ }
+ if (!lineSize) {
+ /* No more lines, just break */
+ break;
+ }
+ if (lineSize > lineMaxSize) {
+ BEGET_LOGE("Invalid read size, ret: %d is larger than buffer size: %d", lineSize, lineMaxSize);
+ lineSize = lineMaxSize;
+ }
+ /* Make sure that each line terminates with '\0' */
+ buffer[lineSize] = '\0';
+ int posStart = 0;
+ for (pos = posStart; pos < lineSize; pos++) {
+ if (buffer[pos] == '\n') {
+ buffer[pos] = '\0';
+ BEGET_LOGI("%s", &buffer[posStart]);
+ posStart = pos + 1;
+ }
+ }
+ if (posStart < pos) {
+ BEGET_LOGI("%s", &buffer[posStart]);
+ }
+ } while (1);
+ (void)close(fd);
+}
+
+static void RedirectToStdFd(int fd)
+{
+ if (dup2(fd, STDOUT_FILENO) < 0) {
+ BEGET_LOGE("Failed to dup2 stdout, errno: %d, just continue", errno);
+ }
+ if (dup2(fd, STDERR_FILENO) < 0) {
+ BEGET_LOGE("Failed to dup2 stderr, errno: %d, just continue", errno);
+ }
+ (void)close(fd);
+}
+
+static int ExecCommand(int argc, char **argv)
+{
+ BEGET_CHECK(!(argc == 0 || argv == NULL || argv[0] == NULL), return -1);
+
+ bool logToKmsg = false;
+ int pipeFds[PIPE_FDS];
+ if (pipe2(pipeFds, O_CLOEXEC) < 0) {
+ BEGET_LOGE("Failed to create pipe, errno: %d, just continue", errno);
+ } else {
+ logToKmsg = true;
+ }
+
+ BEGET_LOGI("Execute %s begin", argv[0]);
+ pid_t pid = fork();
+ BEGET_ERROR_CHECK(pid >= 0, return -1, "Fork new process to format failed: %d", errno);
+ if (pid == 0) {
+ if (logToKmsg) {
+ (void)close(pipeFds[0]);
+ RedirectToStdFd(pipeFds[1]);
+ }
+ execv(argv[0], argv);
+ BEGET_LOGE("Failed to execv, errno: %d", errno);
+ exit(-1);
+ }
+ if (logToKmsg) {
+ (void)close(pipeFds[1]);
+ LogToKmsg(pipeFds[0]);
+ }
+ int status = 0;
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status)) {
+ BEGET_LOGI("Execute success, status: %d, command: %s", WEXITSTATUS(status), argv[0]);
+ return WEXITSTATUS(status);
+ }
+ BEGET_LOGE("Failed to execute %s", argv[0]);
+ return -1;
+}
+
+int DoFormat(const char *devPath, const char *fsType)
+{
+ if (devPath == NULL || fsType == NULL) {
+ return -1;
+ }
+
+ if (!IsSupportedFilesystem(fsType)) {
+ BEGET_LOGE("Do not support filesystem \" %s \"", fsType);
+ return -1;
+ }
+ int ret = 0;
+ if (strcmp(fsType, "ext4") == 0) {
+ char blockSizeBuffer[BLOCK_SIZE_BUFFER] = {0};
+ const unsigned int blockSize = 4096;
+ ret = snprintf_s(blockSizeBuffer, BLOCK_SIZE_BUFFER, BLOCK_SIZE_BUFFER - 1, "%u", blockSize);
+ BEGET_ERROR_CHECK(ret != -1, return -1, "Failed to build block size buffer");
+
+ char *formatCmds[] = {
+ "/bin/mke2fs", "-F", "-t", (char *)fsType, "-b", blockSizeBuffer, (char *)devPath, NULL
+ };
+ int argc = ARRAY_LENGTH(formatCmds);
+ char **argv = (char **)formatCmds;
+ ret = ExecCommand(argc, argv);
+ } else if (IsSupportedDataType(fsType)) {
+#ifdef __MUSL__
+ char *formatCmds[] = {
+ "/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
+ "-O", "sb_checksum", (char *)devPath, NULL
+ };
+#else
+ char *formatCmds[] = {
+ "/bin/make_f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
+ "-O", "sb_checksum", (char *)devPath, NULL
+ };
+#endif
+ int argc = ARRAY_LENGTH(formatCmds);
+ char **argv = (char **)formatCmds;
+ ret = ExecCommand(argc, argv);
+ }
+ return ret;
+}
+
+MountStatus GetMountStatusForMountPoint(const char *mp)
+{
+ if (mp == NULL) {
+ return MOUNT_ERROR;
+ }
+ char buffer[FS_MANAGER_BUFFER_SIZE] = {0};
+ const int expectedItems = 6;
+ int count = 0;
+ char **mountItems = NULL;
+ MountStatus status = MOUNT_ERROR;
+ bool found = false;
+
+ FILE *fp = fopen("/proc/mounts", "r");
+ BEGET_CHECK(fp != NULL, return status);
+
+ while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
+ size_t n = strlen(buffer);
+ if (buffer[n - 1] == '\n') {
+ buffer[n - 1] = '\0';
+ }
+ mountItems = SplitStringExt(buffer, " ", &count, expectedItems);
+ if (mountItems != NULL && count == expectedItems) {
+ // Second item in /proc/mounts is mount point
+ if (strcmp(mountItems[1], mp) == 0) {
+ FreeStringVector(mountItems, count);
+ found = true;
+ break;
+ }
+ FreeStringVector(mountItems, count);
+ }
+ }
+ if (found) {
+ status = MOUNT_MOUNTED;
+ } else if (feof(fp) > 0) {
+ status = MOUNT_UMOUNTED;
+ }
+ (void)fclose(fp);
+ fp = NULL;
+ return status;
+}
+
+static int DoMountOneItem(FstabItem *item);
+#define MAX_RESIZE_PARAM_NUM 20
+static int DoResizeF2fs(FstabItem *item, const unsigned long long size)
+{
+ char *file = "/system/bin/resize.f2fs";
+ char sizeStr[RESIZE_BUFFER_SIZE] = {0};
+ char *argv[MAX_RESIZE_PARAM_NUM] = {NULL};
+ int argc = 0;
+
+ BEGET_ERROR_CHECK(NeedDoAllResize(item->fsManagerFlags), return -1, "no need do resize, bucause kdump has done");
+ BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize.f2fs is not exists.");
+
+ argv[argc++] = file;
+ if (item->fsManagerFlags & FS_MANAGER_PROJQUOTA) {
+ argv[argc++] = "-O";
+ argv[argc++] = "extra_attr,project_quota";
+ }
+ if (item->fsManagerFlags & FS_MANAGER_CASEFOLD) {
+ argv[argc++] = "-O";
+ argv[argc++] = "casefold";
+ argv[argc++] = "-C";
+ argv[argc++] = "utf8";
+ }
+ if (item->fsManagerFlags & FS_MANAGER_COMPRESSION) {
+ argv[argc++] = "-O";
+ argv[argc++] = "extra_attr,compression";
+ }
+ if (item->fsManagerFlags & FS_MANAGER_DEDUP) {
+ argv[argc++] = "-O";
+ argv[argc++] = "extra_attr,dedup";
+ }
+
+ if (size != 0) {
+ unsigned long long realSize = size *
+ ((unsigned long long)RESIZE_BUFFER_SIZE * RESIZE_BUFFER_SIZE / FS_MANAGER_BUFFER_SIZE);
+ int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%llu", realSize);
+ if (len <= 0) {
+ BEGET_LOGE("Write buffer size failed.");
+ }
+ argv[argc++] = "-t";
+ argv[argc++] = sizeStr;
+ }
+
+ argv[argc++] = (char*)(item->deviceName);
+ BEGET_ERROR_CHECK(argc <= MAX_RESIZE_PARAM_NUM, return -1, "argc: %d is too big.", argc);
+ int ret = ExecCommand(argc, argv);
+ if (ret == 0) {
+ BEGET_LOGI("resize success.");
+ return ret;
+ }
+ DoMountOneItem(item);
+ umount(item->mountPoint);
+ BEGET_LOGE("remount and resize again.");
+ return ExecCommand(argc, argv);
+}
+
+static int DoFsckF2fs(const char* device)
+{
+ char *file = "/system/bin/fsck.f2fs";
+ BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "fsck.f2fs is not exists.");
+
+ char *cmd[] = {
+ file, "-p1", (char *)device, NULL
+ };
+ int argc = ARRAY_LENGTH(cmd);
+ char **argv = (char **)cmd;
+ InitTimerControl(true);
+ int ret = ExecCommand(argc, argv);
+ InitTimerControl(false);
+ return ret;
+}
+
+static int DoResizeExt(const char* device, const unsigned long long size)
+{
+ char *file = "/system/bin/resize2fs";
+ BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize2fs is not exists.");
+
+ int ret = 0;
+ if (size == 0) {
+ char *cmd[] = {
+ file, "-f", (char *)device, NULL
+ };
+ int argc = ARRAY_LENGTH(cmd);
+ char **argv = (char **)cmd;
+ ret = ExecCommand(argc, argv);
+ } else {
+ char sizeStr[RESIZE_BUFFER_SIZE] = {0};
+ int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%lluM", size);
+ if (len <= 0) {
+ BEGET_LOGE("Write buffer size failed.");
+ }
+ char *cmd[] = {
+ file, "-f", (char *)device, sizeStr, NULL
+ };
+ int argc = ARRAY_LENGTH(cmd);
+ char **argv = (char **)cmd;
+ ret = ExecCommand(argc, argv);
+ }
+ return ret;
+}
+
+static int DoFsckExt(const char* device)
+{
+ char *file = "/system/bin/e2fsck";
+ BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "e2fsck is not exists.");
+
+ char *cmd[] = {
+ file, "-y", (char *)device, NULL
+ };
+ int argc = ARRAY_LENGTH(cmd);
+ char **argv = (char **)cmd;
+ return ExecCommand(argc, argv);
+}
+
+static int Mount(const char *source, const char *target, const char *fsType,
+ unsigned long flags, const char *data)
+{
+ struct stat st = {};
+ int rc = -1;
+
+ bool isTrue = source == NULL || target == NULL || fsType == NULL;
+ BEGET_ERROR_CHECK(!isTrue, return -1, "Invalid argument for mount.");
+
+ isTrue = stat(target, &st) != 0 && errno != ENOENT;
+ BEGET_ERROR_CHECK(!isTrue, return -1, "Cannot get stat of \" %s \", err = %d", target, errno);
+
+ BEGET_CHECK((st.st_mode & S_IFMT) != S_IFLNK, unlink(target)); // link, delete it.
+
+ if (mkdir(target, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
+ BEGET_ERROR_CHECK(errno == EEXIST, return -1, "Failed to create dir \" %s \", err = %d", target, errno);
+ }
+ errno = 0;
+ if ((rc = mount(source, target, fsType, flags, data)) != 0) {
+ BEGET_WARNING_CHECK(errno != EBUSY, rc = 0, "Mount %s to %s busy, ignore", source, target);
+ }
+ return rc;
+}
+
+static int GetSlotInfoFromCmdLine(const char *slotInfoName)
+{
+ char value[MAX_BUFFER_LEN] = {0};
+ BEGET_INFO_CHECK(GetParameterFromCmdLine(slotInfoName, value, MAX_BUFFER_LEN) == 0,
+ return -1, "Failed to get %s value from cmdline", slotInfoName);
+ return atoi(value);
+}
+
+static int GetSlotInfoFromBootctrl(off_t offset, off_t size)
+{
+ char bootctrlDev[MAX_BUFFER_LEN] = {0};
+ BEGET_ERROR_CHECK(GetBlockDevicePath("/bootctrl", bootctrlDev, MAX_BUFFER_LEN) == 0,
+ return -1, "Failed to get bootctrl device");
+ char *realPath = GetRealPath(bootctrlDev);
+ BEGET_ERROR_CHECK(realPath != NULL, return -1, "Failed to get bootctrl device real path");
+ int fd = open(realPath, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ free(realPath);
+ BEGET_ERROR_CHECK(fd >= 0, return -1, "Failed to open bootctrl device, errno %d", errno);
+ BEGET_ERROR_CHECK(lseek(fd, offset, SEEK_SET) >= 0, close(fd); return -1,
+ "Failed to lseek bootctrl device fd, errno %d", errno);
+ int slotInfo = 0;
+ BEGET_INFO_CHECK(read(fd, &slotInfo, sizeof(slotInfo)) == size, close(fd); return -1,
+ "Failed to read current slot from bootctrl, errno %d", errno);
+ close(fd);
+ return slotInfo;
+}
+
+int GetBootSlots(void)
+{
+ return GetSlotInfoFromCmdLine("bootslots");
+}
+
+int GetCurrentSlot(void)
+{
+ // get current slot from cmdline
+ int currentSlot = GetSlotInfoFromCmdLine("currentslot");
+ BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot);
+ BEGET_LOGI("No valid slot value found from cmdline, try to get it from bootctrl");
+
+ // get current slot from bootctrl
+ return GetSlotInfoFromBootctrl(PARTITION_ACTIVE_SLOT_OFFSET, PARTITION_ACTIVE_SLOT_SIZE);
+}
+
+static int DoMountOneItem(FstabItem *item)
+{
+ BEGET_LOGI("Mount device %s to %s", item->deviceName, item->mountPoint);
+ unsigned long mountFlags;
+ char fsSpecificData[FS_MANAGER_BUFFER_SIZE] = {0};
+
+ mountFlags = GetMountFlags(item->mountOptions, fsSpecificData, sizeof(fsSpecificData),
+ item->mountPoint);
+
+ int retryCount = 3;
+ int rc = 0;
+ while (retryCount-- > 0) {
+ rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData);
+ if (rc == 0) {
+ return rc;
+ }
+
+ if (FM_MANAGER_FORMATTABLE_ENABLED(item->fsManagerFlags)) {
+ BEGET_LOGI("Device is formattable");
+ int ret = DoFormat(item->deviceName, item->fsType);
+ BEGET_LOGI("End format image ret %d", ret);
+ if (ret != 0) {
+ continue;
+ }
+ rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData);
+ if (rc == 0) {
+ return rc;
+ }
+ }
+ BEGET_LOGE("Mount device %s to %s failed, err = %d, retry", item->deviceName, item->mountPoint, errno);
+ }
+ return rc;
+}
+
+#ifdef EROFS_OVERLAY
+static int MountItemByFsType(FstabItem *item)
+{
+ if (CheckIsErofs(item->deviceName)) {
+ if (strcmp(item->fsType, "erofs") == 0) {
+ if (IsOverlayEnable()) {
+ return DoMountOverlayDevice(item);
+ }
+ int rc = DoMountOneItem(item);
+ if (rc == 0 && strcmp(item->mountPoint, "/usr") == 0) {
+ SwitchRoot("/usr");
+ }
+ return rc;
+ } else {
+ BEGET_LOGI("fsType not erofs system, device [%s] skip erofs mount process", item->deviceName);
+ return 0;
+ }
+ }
+
+ if (strcmp(item->fsType, "erofs") != 0) {
+ int rc = DoMountOneItem(item);
+ if (rc == 0 && strcmp(item->mountPoint, "/usr") == 0) {
+ SwitchRoot("/usr");
+ }
+ return rc;
+ }
+
+ BEGET_LOGI("fsType is erofs system, device [%s] skip ext4 or hms mount process", item->deviceName);
+ return 0;
+}
+#endif
+
+int MountOneItem(FstabItem *item)
+{
+ if (item == NULL) {
+ return -1;
+ }
+
+ if (FM_MANAGER_WAIT_ENABLED(item->fsManagerFlags)) {
+ WaitForFile(item->deviceName, WAIT_MAX_SECOND);
+ }
+
+ if (strcmp(item->mountPoint, "/data") == 0 && IsSupportedDataType(item->fsType)) {
+ int ret = DoFsckF2fs(item->deviceName);
+ if (ret != 0) {
+ BEGET_LOGE("Failed to fsck.f2fs dir %s , ret = %d", item->deviceName, ret);
+ }
+ ret = DoResizeF2fs(item, 0);
+ if (ret != 0) {
+ BEGET_LOGE("Failed to resize.f2fs dir %s , ret = %d", item->deviceName, ret);
+ }
+ } else if (strcmp(item->fsType, "ext4") == 0 && strcmp(item->mountPoint, "/data") == 0) {
+ int ret = DoResizeExt(item->deviceName, 0);
+ if (ret != 0) {
+ BEGET_LOGE("Failed to resize2fs dir %s , ret = %d", item->deviceName, ret);
+ }
+ ret = DoFsckExt(item->deviceName);
+ if (ret != 0) {
+ BEGET_LOGE("Failed to e2fsck dir %s , ret = %d", item->deviceName, ret);
+ }
+ }
+
+ int rc = 0;
+#ifdef EROFS_OVERLAY
+ rc = MountItemByFsType(item);
+#else
+ rc = DoMountOneItem(item);
+ if (rc == 0 && (strcmp(item->mountPoint, "/usr") == 0)) {
+ SwitchRoot("/usr");
+ }
+#endif
+ InitPostMount(item->mountPoint, rc);
+ if (rc != 0) {
+ if (FM_MANAGER_NOFAIL_ENABLED(item->fsManagerFlags)) {
+ BEGET_LOGE("Mount no fail device %s to %s failed, err = %d", item->deviceName, item->mountPoint, errno);
+ } else {
+ BEGET_LOGW("Mount %s to %s failed, err = %d. Ignore failure", item->deviceName, item->mountPoint, errno);
+ rc = 0;
+ }
+ } else {
+ BEGET_LOGI("Mount %s to %s successful", item->deviceName, item->mountPoint);
+ }
+ return rc;
+}
+
+#if defined EROFS_OVERLAY && defined SUPPORT_HVB
+static bool NeedDmVerity(FstabItem *item)
+{
+ if (CheckIsErofs(item->deviceName)) {
+ if (strcmp(item->fsType, "erofs") == 0) {
+ return true;
+ }
+ } else {
+ if (strcmp(item->fsType, "erofs") != 0) {
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
+static void AdjustPartitionNameByPartitionSlot(FstabItem *item)
+{
+ BEGET_CHECK_ONLY_RETURN(strstr(item->deviceName, "/system") != NULL ||
+ strstr(item->deviceName, "/vendor") != NULL);
+ char buffer[MAX_BUFFER_LEN] = {0};
+ int slot = GetCurrentSlot();
+ BEGET_ERROR_CHECK(slot > 0 && slot <= MAX_SLOT, slot = 1, "slot value %d is invalid, set default value", slot);
+ BEGET_ERROR_CHECK(sprintf_s(buffer, sizeof(buffer), "%s_%c", item->deviceName, 'a' + slot - 1) > 0,
+ return, "Failed to format partition name suffix, use default partition name");
+ free(item->deviceName);
+ item->deviceName = strdup(buffer);
+ if (item->deviceName == NULL) {
+ BEGET_LOGE("failed dup devicename");
+ return;
+ }
+ BEGET_LOGI("partition name with slot suffix: %s", item->deviceName);
+}
+
+static int CheckRequiredAndMount(FstabItem *item, bool required)
+{
+ int rc = 0;
+ if (item == NULL) {
+ return -1;
+ }
+
+ // Mount partition during second startup.
+ if (!required) {
+ if (!FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
+ rc = MountOneItem(item);
+ }
+ return rc;
+ }
+
+ // Mount partition during one startup.
+ if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
+ int bootSlots = GetBootSlots();
+ BEGET_INFO_CHECK(bootSlots <= 1, AdjustPartitionNameByPartitionSlot(item),
+ "boot slots is %d, now adjust partition name according to current slot", bootSlots);
+#ifdef SUPPORT_HVB
+#ifdef EROFS_OVERLAY
+ if (!NeedDmVerity(item)) {
+ BEGET_LOGI("not need dm verity, do mount item %s", item->deviceName);
+ return MountOneItem(item);
+ }
+#endif
+ rc = HvbDmVeritySetUp(item);
+ if (rc != 0) {
+ BEGET_LOGE("set dm_verity err, ret = 0x%x", rc);
+ if (!FM_MANAGER_NOFAIL_ENABLED(item->fsManagerFlags)) {
+ rc = 0;
+ BEGET_LOGW("DmVeritySetUp fail for %s, ignore error and do not mount", item->deviceName);
+ } else {
+ BEGET_LOGE("DmVeritySetUp fail for no fail devices %s, error!", item->deviceName);
+ }
+ return rc;
+ }
+#endif
+ rc = MountOneItem(item);
+ }
+ return rc;
+}
+
+int MountAllWithFstab(const Fstab *fstab, bool required)
+{
+ BEGET_CHECK(fstab != NULL, return -1);
+
+ FstabItem *item = NULL;
+ int rc = -1;
+
+#ifdef SUPPORT_HVB
+ if (required) {
+ rc = HvbDmVerityinit(fstab);
+ if (rc != 0) {
+ BEGET_LOGE("set dm_verity init, ret = 0x%x", rc);
+ return rc;
+ }
+ }
+#endif
+
+ for (item = fstab->head; item != NULL; item = item->next) {
+ rc = CheckRequiredAndMount(item, required);
+ if (required && (rc < 0)) { // Init fail to mount in the first stage and exit directly.
+ break;
+ }
+ }
+
+#ifdef SUPPORT_HVB
+ if (required)
+ HvbDmVerityFinal();
+#endif
+
+ return rc;
+}
+
+int MountAllWithFstabFile(const char *fstabFile, bool required)
+{
+ bool isFile = fstabFile == NULL || *fstabFile == '\0';
+ BEGET_CHECK(!isFile, return -1);
+
+ Fstab *fstab = NULL;
+ if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) {
+ BEGET_LOGE("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile);
+ return -1;
+ }
+
+ int rc = MountAllWithFstab(fstab, required);
+ if (rc != 0) {
+ BEGET_LOGE("[startup_failed]MountAllWithFstab failed %s %d %d %d", fstabFile,
+ FSTAB_MOUNT_FAILED, required, rc);
+ }
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return rc;
+}
+
+int UmountAllWithFstabFile(const char *fstabFile)
+{
+ bool isFile = fstabFile == NULL || *fstabFile == '\0';
+ BEGET_CHECK(!isFile, return -1);
+
+ Fstab *fstab = NULL;
+ fstab = ReadFstabFromFile(fstabFile, false);
+ BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile);
+
+ FstabItem *item = NULL;
+ int rc = -1;
+ for (item = fstab->head; item != NULL; item = item->next) {
+ BEGET_LOGI("Umount %s.", item->mountPoint);
+ MountStatus status = GetMountStatusForMountPoint(item->mountPoint);
+ if (status == MOUNT_ERROR) {
+ BEGET_LOGW("Cannot get mount status of mount point \" %s \"", item->mountPoint);
+ continue; // Cannot get mount status, just ignore it and try next one.
+ } else if (status == MOUNT_UMOUNTED) {
+ BEGET_LOGI("Mount point \" %s \" already unmounted. device path: %s, fs type: %s.",
+ item->mountPoint, item->deviceName, item->fsType);
+ continue;
+ } else {
+ rc = umount(item->mountPoint);
+ if (rc == -1) {
+ BEGET_LOGE("Umount %s failed, device path: %s, fs type: %s, err = %d.",
+ item->mountPoint, item->deviceName, item->fsType, errno);
+ } else {
+ BEGET_LOGE("Umount %s successfully.", item->mountPoint);
+ }
+ }
+ }
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return rc;
+}
+
+int FsManagerDmRemoveDevice(const char *devName)
+{
+#ifdef SUPPORT_HVB
+ return FsDmRemoveDevice(devName);
+#endif
+ return 0;
+}
+
+int MountOneWithFstabFile(const char *fstabFile, const char *devName, bool required)
+{
+ bool isFile = fstabFile == NULL || *fstabFile == '\0';
+ BEGET_CHECK(!isFile, return -1);
+
+ Fstab *fstab = NULL;
+ fstab = ReadFstabFromFile(fstabFile, false);
+ BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile);
+
+ FstabItem *item = NULL;
+ int rc = -1;
+
+#ifdef SUPPORT_HVB
+ if (required) {
+ rc = HvbDmVerityinit(fstab);
+ if (rc != 0) {
+ BEGET_LOGE("set dm_verity init, ret = 0x%x", rc);
+ return rc;
+ }
+ }
+#endif
+
+ for (item = fstab->head; item != NULL; item = item->next) {
+ if (strcmp(item->mountPoint, devName) == 0) {
+ rc = CheckRequiredAndMount(item, required);
+ break;
+ }
+ }
+
+#ifdef SUPPORT_HVB
+ if (required) {
+ HvbDmVerityFinal();
+ }
+#endif
+
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return rc;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c b/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c
new file mode 100755
index 0000000000000000000000000000000000000000..10b6c49f72f4b5f094397ebe573069cc4a369f02
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include "securec.h"
+#include "beget_ext.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ueventd.h"
+#include "ueventd_socket.h"
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define DM_VERSION0 (4)
+#define DM_VERSION1 (0)
+#define DM_VERSION2 (0)
+#define DM_ALIGN_MASK (7)
+#define DM_ALIGN(x) (((x) + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
+#define DEVICE_MAPPER_PATH "/dev/mapper/control"
+#define DM_DEVICE_PATH_PREFIX "/dev/block/dm-"
+
+#define FS_DM_RETURN_ERR_IF_NULL(__ptr) \
+ do { \
+ if ((__ptr) == NULL) { \
+ BEGET_LOGE("error, %s is NULL\n", #__ptr); \
+ return -1; \
+ } \
+ } while (0)
+
+static int InitDmIo(struct dm_ioctl *io, const char *devName)
+{
+ errno_t err;
+
+ err = memset_s(io, sizeof(*io), 0, sizeof(*io));
+ if (err != EOK) {
+ BEGET_LOGE("memset io, ret=%d", err);
+ return -1;
+ }
+
+ io->version[0] = DM_VERSION0;
+ io->version[1] = DM_VERSION1;
+ io->version[2] = DM_VERSION2;
+ io->data_size = sizeof(*io);
+ io->data_start = 0;
+
+ if (devName == NULL) {
+ return 0;
+ }
+
+ err = strcpy_s(io->name, sizeof(io->name), devName);
+ if (err != EOK) {
+ BEGET_LOGE("cp devName, ret=%d", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int CreateDmDevice(int fd, const char *devName)
+{
+ int rc;
+ struct dm_ioctl io;
+
+ rc = InitDmIo(&io, devName);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ioctl(fd, DM_DEV_CREATE, &io);
+ if (rc != 0) {
+ BEGET_LOGE("error, DM_DEV_CREATE failed for %s, ret=%d", devName, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int LoadDmDeviceTable(int fd, const char *devName,
+ DmVerityTarget *target, bool needDmVerity)
+{
+ int rc;
+ errno_t err;
+ char *parasBuf = NULL;
+ size_t parasTotalSize;
+ struct dm_ioctl *io = NULL;
+ struct dm_target_spec *ts = NULL;
+ char *paras = NULL;
+
+ FS_DM_RETURN_ERR_IF_NULL(target);
+ FS_DM_RETURN_ERR_IF_NULL(target->paras);
+
+ parasTotalSize = DM_ALIGN(sizeof(*io) + sizeof(*ts) + target->paras_len + 1);
+ parasBuf = calloc(1, parasTotalSize);
+ if (parasBuf == NULL) {
+ BEGET_LOGE("error, calloc dm table fail");
+ return -1;
+ }
+
+ io = (struct dm_ioctl *)parasBuf;
+ ts = (struct dm_target_spec *)(parasBuf + sizeof(*io));
+ paras = parasBuf + sizeof(*io) + sizeof((*ts));
+
+ do {
+ rc = InitDmIo(io, devName);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, init dm io", rc);
+ break;
+ }
+
+ io->data_size = parasTotalSize;
+ io->data_start = sizeof(*io);
+ io->target_count = 1;
+ io->flags |= DM_READONLY_FLAG;
+
+ ts->status = 0;
+ ts->sector_start = target->start;
+ ts->length = target->length;
+ char *targetType = needDmVerity ? "verity" : "linear";
+ err = strcpy_s(ts->target_type, sizeof(ts->target_type), targetType);
+ if (err != EOK) {
+ rc = -1;
+ BEGET_LOGE("error 0x%x, cp target type", err);
+ break;
+ }
+
+ err = strcpy_s(paras, target->paras_len + 1, target->paras);
+ if (err != EOK) {
+ rc = -1;
+ BEGET_LOGE("error 0x%x, cp target paras", err);
+ break;
+ }
+
+ ts->next = parasTotalSize - sizeof(*io);
+
+ rc = ioctl(fd, DM_TABLE_LOAD, io);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, DM_TABLE_LOAD failed for %s", rc, devName);
+ break;
+ }
+ } while (0);
+
+ free(parasBuf);
+
+ return rc;
+}
+
+static int ActiveDmDevice(int fd, const char *devName)
+{
+ int rc;
+ struct dm_ioctl io;
+
+ rc = InitDmIo(&io, devName);
+ if (rc != 0) {
+ return rc;
+ }
+
+ io.flags |= DM_READONLY_FLAG;
+
+ rc = ioctl(fd, DM_DEV_SUSPEND, &io);
+ if (rc != 0) {
+ BEGET_LOGE("error, DM_TABLE_SUSPEND for %s, ret=%d", devName, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+int GetDmDevPath(int fd, char **dmDevPath, const char *devName)
+{
+ int rc;
+ char *path = NULL;
+ size_t path_len = strlen(DM_DEVICE_PATH_PREFIX) + 32;
+ unsigned int dev_num;
+ struct dm_ioctl io;
+
+ rc = InitDmIo(&io, devName);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, init Dm io", rc);
+ return rc;
+ }
+
+ rc = ioctl(fd, DM_DEV_STATUS, &io);
+ if (rc != 0) {
+ BEGET_LOGE("error, DM_DEV_STATUS for %s, ret=%d", devName, rc);
+ return rc;
+ }
+
+ dev_num = minor(io.dev);
+
+ path = calloc(1, path_len);
+ if (path == NULL) {
+ BEGET_LOGE("error, alloc dm dev path");
+ return -1;
+ }
+
+ rc = snprintf_s(path, path_len, path_len - 1, "%s%u", DM_DEVICE_PATH_PREFIX, dev_num);
+ if (rc < 0) {
+ BEGET_LOGE("error 0x%x, cp dm dev path", rc);
+ free(path);
+ return -1;
+ }
+
+ *dmDevPath = path;
+
+ return 0;
+}
+
+int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target)
+{
+ int rc;
+ int fd = -1;
+
+ fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH);
+ return -1;
+ }
+
+ rc = CreateDmDevice(fd, devName);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create dm device fail", rc);
+ close(fd);
+ return rc;
+ }
+
+ rc = LoadDmDeviceTable(fd, devName, target, true);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, load device table fail", rc);
+ close(fd);
+ return rc;
+ }
+
+ rc = ActiveDmDevice(fd, devName);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, active device fail", rc);
+ close(fd);
+ return rc;
+ }
+
+ rc = GetDmDevPath(fd, dmDevPath, devName);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, get dm dev fail", rc);
+ close(fd);
+ return rc;
+ }
+ close(fd);
+ return 0;
+}
+
+int FsDmInitDmDev(char *devPath, bool useSocket)
+{
+ int rc;
+ char dmDevPath[PATH_MAX] = {0};
+ char *devName = NULL;
+
+ if (devPath == NULL) {
+ BEGET_LOGE("error, devPath is NULL");
+ return -1;
+ }
+
+ devName = basename(devPath);
+
+ rc = snprintf_s(&dmDevPath[0], sizeof(dmDevPath), sizeof(dmDevPath) - 1, "%s%s", "/sys/block/", devName);
+ if (rc < 0) {
+ BEGET_LOGE("error 0x%x, format dm dev", rc);
+ return rc;
+ }
+
+ int ueventSockFd = -1;
+ if (useSocket) {
+ ueventSockFd = UeventdSocketInit();
+ if (ueventSockFd < 0) {
+ BEGET_LOGE("error, Failed to create uevent socket");
+ return -1;
+ }
+ }
+
+ RetriggerUeventByPath(ueventSockFd, &dmDevPath[0]);
+
+ close(ueventSockFd);
+
+ return 0;
+}
+
+int FsDmRemoveDevice(const char *devName)
+{
+ int rc;
+ int fd = -1;
+ struct dm_ioctl io;
+
+ fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH);
+ return -1;
+ }
+
+ rc = InitDmIo(&io, devName);
+ if (rc != 0) {
+ close(fd);
+ BEGET_LOGE("error 0x%x, init dm io", rc);
+ return -1;
+ }
+
+ io.flags |= DM_READONLY_FLAG;
+
+ rc = ioctl(fd, DM_DEV_REMOVE, &io);
+ if (rc != 0) {
+ close(fd);
+ BEGET_LOGE("error, DM_DEV_REMOVE failed for %s, ret=%d", devName, rc);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static int DmGetDeviceName(int fd, const char *devName, char *outDevName, const uint64_t outDevNameLen)
+{
+ int rc;
+ char *path = NULL;
+ size_t pathLen = strlen(DM_DEVICE_PATH_PREFIX) + 32;
+ struct dm_ioctl io;
+ rc = InitDmIo(&io, devName);
+ if (rc != 0) {
+ BEGET_LOGE("init dm io failed");
+ return rc;
+ }
+
+ rc = ioctl(fd, DM_DEV_STATUS, &io);
+ if (rc != 0) {
+ BEGET_LOGE("get DM_DEV_STATUS failed");
+ return rc;
+ }
+
+ int devNum = (io.dev & 0xff) | ((io.dev >> 12) & 0xff00);
+ path = calloc(1, pathLen);
+ if (path == NULL) {
+ BEGET_LOGE("calloc path failed");
+ return rc;
+ }
+
+ rc = snprintf_s(path, pathLen, pathLen - 1, "%s%d", DM_DEVICE_PATH_PREFIX, devNum);
+ if (rc < 0) {
+ BEGET_LOGE("copy dm path failed");
+ free(path);
+ path = NULL;
+ return rc;
+ }
+
+ rc = memcpy_s(outDevName, outDevNameLen, path, pathLen);
+ if (rc < 0) {
+ BEGET_LOGE("copy dm path failed");
+ }
+ BEGET_LOGI("dm get device outDevName %s, devNum %d", path, devNum);
+ free(path);
+ path = NULL;
+ return rc;
+}
+
+int FsDmCreateLinearDevice(const char *devName, char *dmBlkName, uint64_t dmBlkNameLen, DmVerityTarget *target)
+{
+ int rc;
+ int fd = -1;
+ fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ BEGET_LOGE("open mapper path failed");
+ return -1;
+ }
+
+ rc = CreateDmDevice(fd, devName);
+ if (rc) {
+ BEGET_LOGE("create dm device failed");
+ close(fd);
+ return -1;
+ }
+
+ rc = DmGetDeviceName(fd, devName, dmBlkName, dmBlkNameLen);
+ if (rc) {
+ BEGET_LOGE("get dm device name failed");
+ close(fd);
+ return -1;
+ }
+
+ rc = LoadDmDeviceTable(fd, devName, target, false);
+ if (rc) {
+ BEGET_LOGE("load dm device name failed");
+ close(fd);
+ return -1;
+ }
+
+ rc = ActiveDmDevice(fd, devName);
+ if (rc) {
+ BEGET_LOGE("active dm device name failed");
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ BEGET_LOGI("fs create rofs linear device success, dev is [%s]", devName);
+ return 0;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/interfaces/innerkits/fs_manager/libfs_dm/include/fs_dm.h b/interfaces/innerkits/fs_manager/libfs_dm/include/fs_dm.h
new file mode 100755
index 0000000000000000000000000000000000000000..368275a0ef0272f8af3baebb1448962bbc4cb342
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/libfs_dm/include/fs_dm.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2023 Huawei Device Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STARTUP_LIBFS_DM_H
+#define STARTUP_LIBFS_DM_H
+
+#include
+#include
+#include
+#include "fs_manager.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+typedef struct {
+ uint64_t start;
+ uint64_t length;
+ char *paras;
+ uint64_t paras_len;
+} DmVerityTarget;
+
+int FsDmInitDmDev(char *devPath, bool useSocket);
+int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target);
+int FsDmRemoveDevice(const char *devName);
+int FsDmCreateLinearDevice(const char *devName, char *dmBlkName, uint64_t dmBlkNameLen, DmVerityTarget *target);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // STARTUP_LIBFS_DM_H
diff --git a/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c b/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c
new file mode 100755
index 0000000000000000000000000000000000000000..aa72376df947813f5ca9587015d55fc054f78e6f
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c
@@ -0,0 +1,857 @@
+/*
+ * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fs_hvb.h"
+#include "fs_dm.h"
+#include "securec.h"
+#include "fs_manager/ext4_super_block.h"
+#include "fs_manager/erofs_super_block.h"
+#include
+#include "beget_ext.h"
+#include "init_utils.h"
+#include
+#include
+#include "hvb_sm2.h"
+#include "hvb_sm3.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define FS_HVB_VERITY_TARGET_MAX 512
+#define FS_HVB_BLANK_SPACE_ASCII 32
+#define FS_HVB_SECTOR_BYTES 512
+#define FS_HVB_UINT64_MAX_LENGTH 64
+#define FS_HVB_HASH_ALG_STR_MAX 32
+
+#define FS_HVB_DIGEST_SHA256_BYTES 32
+#define FS_HVB_DIGEST_SHA512_BYTES 64
+#define FS_HVB_DIGEST_SM3_BYTES 32
+#define FS_HVB_DIGEST_MAX_BYTES FS_HVB_DIGEST_SHA512_BYTES
+#define FS_HVB_DIGEST_STR_MAX_BYTES 128
+#define FS_HVB_DEVPATH_MAX_LEN 128
+#define FS_HVB_RVT_PARTITION_NAME "rvt"
+#define FS_HVB_EXT_RVT_PARTITION_NAME "ext_rvt"
+#define FS_HVB_CMDLINE_PATH "/proc/cmdline"
+#define FS_HVB_PARTITION_PREFIX "/dev/block/by-name/"
+#define HVB_CMDLINE_EXT_CERT_DIGEST "ohos.boot.hvb.ext_rvt"
+
+#define HASH_ALGO_SHA256 0
+#define HASH_ALGO_SHA256_STR "sha256"
+#define HASH_ALGO_SHA512 2
+#define HASH_ALGO_SHA512_STR "sha512"
+#define HASH_ALGO_SM3 3
+#define HASH_ALGO_SM3_STR "sm3"
+
+#define FS_HVB_RETURN_ERR_IF_NULL(__ptr) \
+ do { \
+ if ((__ptr) == NULL) { \
+ BEGET_LOGE("error, %s is NULL\n", #__ptr); \
+ return -1; \
+ } \
+ } while (0)
+
+static struct hvb_verified_data *g_vd = NULL;
+static struct hvb_verified_data *g_extVd = NULL;
+
+static enum hvb_errno GetCurrVerifiedData(InitHvbType hvbType, struct hvb_verified_data ***currVd)
+{
+ if (currVd == NULL) {
+ BEGET_LOGE("error, invalid input");
+ return HVB_ERROR_INVALID_ARGUMENT;
+ }
+ if (hvbType == MAIN_HVB) {
+ *currVd = &g_vd;
+ } else if (hvbType == EXT_HVB) {
+ *currVd = &g_extVd;
+ } else {
+ BEGET_LOGE("error, invalid hvb type");
+ return HVB_ERROR_INVALID_ARGUMENT;
+ }
+
+ return HVB_OK;
+}
+
+static char FsHvbBinToHexChar(char octet)
+{
+ return octet < 10 ? '0' + octet : 'a' + (octet - 10);
+}
+
+static char FsHvbHexCharToBin(char hex)
+{
+ return '0' <= hex && hex <= '9' ? hex - '0' : 10 + (hex - 'a');
+}
+
+static int FsHvbGetHashStr(char *str, size_t size, InitHvbType hvbType)
+{
+ if (hvbType == MAIN_HVB) {
+ return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_HASH_ALG);
+ }
+
+ if (hvbType == EXT_HVB) {
+ if (memcpy_s(str, size, HASH_ALGO_SHA256_STR, strlen(HASH_ALGO_SHA256_STR)) != 0) {
+ BEGET_LOGE("fail to copy hvb hash str");
+ return -1;
+ }
+ return 0;
+ }
+
+ BEGET_LOGE("error, invalid hvbType");
+ return -1;
+}
+
+static int FsHvbGetCertDigstStr(char *str, size_t size, InitHvbType hvbType)
+{
+ if (hvbType == MAIN_HVB) {
+ return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_CERT_DIGEST);
+ }
+
+ if (hvbType == EXT_HVB) {
+ return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_EXT_CERT_DIGEST);
+ }
+
+ BEGET_LOGE("error, invalid hvbType");
+ return -1;
+}
+
+static int FsHvbComputeSha256(char *digest, uint32_t size, struct hvb_cert_data *certs, uint64_t num_certs)
+{
+ int ret;
+ uint64_t n;
+ struct hash_ctx_t ctx = {0};
+
+ if (size < FS_HVB_DIGEST_SHA256_BYTES) {
+ BEGET_LOGE("error, size=%zu", size);
+ return -1;
+ }
+
+ ret = hash_ctx_init(&ctx, HASH_ALG_SHA256);
+ if (ret != HASH_OK) {
+ BEGET_LOGE("error 0x%x, sha256 init", ret);
+ return -1;
+ }
+
+ for (n = 0; n < num_certs; n++) {
+ ret = hash_calc_update(&ctx, certs[n].data.addr, certs[n].data.size);
+ if (ret != HASH_OK) {
+ BEGET_LOGE("error 0x%x, sha256 update", ret);
+ return -1;
+ }
+ }
+
+ ret = hash_calc_do_final(&ctx, NULL, 0, (uint8_t *)digest, size);
+ if (ret != HASH_OK) {
+ BEGET_LOGE("error 0x%x, sha256 final", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int FsHvbComputeSM3Hash(char *digest, uint32_t *size, struct hvb_cert_data *certs, uint64_t num_certs)
+{
+ BEGET_CHECK(digest != NULL && certs != NULL && size != NULL, return -1);
+ int ret;
+ uint64_t n;
+ struct sm3_ctx_t ctx = {0};
+
+ if (*size < FS_HVB_DIGEST_SM3_BYTES) {
+ BEGET_LOGE("error, size=%zu", *size);
+ return -1;
+ }
+
+ ret = hvb_sm3_init(&ctx);
+ if (ret != SM3_OK) {
+ BEGET_LOGE("error 0x%x, sm3 init", ret);
+ return -1;
+ }
+
+ for (n = 0; n < num_certs; n++) {
+ ret = hvb_sm3_update(&ctx, certs[n].data.addr, certs[n].data.size);
+ if (ret != SM3_OK) {
+ BEGET_LOGE("error 0x%x, sm3 update", ret);
+ return -1;
+ }
+ }
+
+ ret = hvb_sm3_final(&ctx, (uint8_t *)digest, size);
+ if (ret != SM3_OK) {
+ BEGET_LOGE("error 0x%x, sha256 final", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int FsHvbHexStrToBin(char *bin, size_t bin_size, char *str, size_t str_size)
+{
+ size_t i;
+
+ if ((str_size & 0x1) != 0 || bin_size < (str_size >> 1)) {
+ BEGET_LOGE("error, bin_size %zu str_size %zu", bin_size, str_size);
+ return -1;
+ }
+
+ for (i = 0; i < (str_size >> 1); i++) {
+ bin[i] = (FsHvbHexCharToBin(str[2 * i]) << 4) | FsHvbHexCharToBin(str[2 * i + 1]);
+ }
+
+ return 0;
+}
+
+static int FsHvbCheckCertChainDigest(struct hvb_cert_data *certs, uint64_t num_certs, InitHvbType hvbType)
+{
+ int ret;
+ size_t digest_len = 0;
+ char hashAlg[FS_HVB_HASH_ALG_STR_MAX] = {0};
+ char certDigest[FS_HVB_DIGEST_MAX_BYTES] = {0};
+ char computeDigest[FS_HVB_DIGEST_MAX_BYTES] = {0};
+ char certDigestStr[FS_HVB_DIGEST_STR_MAX_BYTES + 1] = {0};
+ uint32_t computeDigestLen = FS_HVB_DIGEST_MAX_BYTES;
+
+ ret = FsHvbGetHashStr(&hashAlg[0], sizeof(hashAlg), hvbType);
+ if (ret != 0) {
+ BEGET_LOGE("error 0x%x, get hash val from cmdline", ret);
+ return ret;
+ }
+
+ ret = FsHvbGetCertDigstStr(&certDigestStr[0], sizeof(certDigestStr), hvbType);
+ if (ret != 0) {
+ BEGET_LOGE("error 0x%x, get digest val from cmdline", ret);
+ return ret;
+ }
+
+ ret = FsHvbHexStrToBin(&certDigest[0], sizeof(certDigest), &certDigestStr[0], strlen(certDigestStr));
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (strcmp(&hashAlg[0], "sha256") == 0) {
+ digest_len = FS_HVB_DIGEST_SHA256_BYTES;
+ ret = FsHvbComputeSha256(computeDigest, computeDigestLen, certs, num_certs);
+ } else if (strcmp(&hashAlg[0], "sm3") == 0) {
+ digest_len = FS_HVB_DIGEST_SM3_BYTES;
+ ret = FsHvbComputeSM3Hash(computeDigest, &computeDigestLen, certs, num_certs);
+ } else {
+ BEGET_LOGE("error, not support alg %s", &hashAlg[0]);
+ return -1;
+ }
+
+ if (ret != 0) {
+ BEGET_LOGE("error 0x%x, compute hash", ret);
+ return -1;
+ }
+
+ ret = memcmp(&certDigest[0], &computeDigest[0], digest_len);
+ if (ret != 0) {
+ BEGET_LOGE("error, cert digest not match with cmdline");
+ return -1;
+ }
+
+ return 0;
+}
+
+int FsHvbInit(InitHvbType hvbType)
+{
+ enum hvb_errno rc;
+ struct hvb_verified_data **currVd = NULL;
+ char *rootPartitionName = NULL;
+ rc = GetCurrVerifiedData(hvbType, &currVd);
+ if (rc != HVB_OK) {
+ BEGET_LOGE("error 0x%x, GetCurrVerifiedData", rc);
+ return rc;
+ }
+
+ // return ok if the hvb is already initialized
+ if (*currVd != NULL) {
+ BEGET_LOGI("Hvb has already been inited");
+ return 0;
+ }
+
+ if (hvbType == MAIN_HVB) {
+ rootPartitionName = FS_HVB_RVT_PARTITION_NAME;
+ } else {
+ rootPartitionName = FS_HVB_EXT_RVT_PARTITION_NAME;
+ }
+
+ rc = hvb_chain_verify(FsHvbGetOps(), rootPartitionName, NULL, currVd);
+ if (*currVd == NULL) {
+ BEGET_LOGE("error 0x%x, hvb chain verify, vd is NULL", rc);
+ return rc;
+ }
+
+ if (rc != HVB_OK) {
+ BEGET_LOGE("error 0x%x, hvb chain verify", rc);
+ hvb_chain_verify_data_free(*currVd);
+ *currVd = NULL;
+ return rc;
+ }
+
+ rc = FsHvbCheckCertChainDigest((*currVd)->certs, (*currVd)->num_loaded_certs, hvbType);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, cert chain hash", rc);
+ hvb_chain_verify_data_free(*currVd);
+ *currVd = NULL;
+ return rc;
+ }
+
+ BEGET_LOGI("hvb type %d verify succ in init", hvbType);
+
+ return 0;
+}
+
+static int FsHvbGetCert(struct hvb_cert *cert, const char *devName, struct hvb_verified_data *vd)
+{
+ enum hvb_errno hr;
+ size_t devNameLen = strlen(devName);
+ struct hvb_cert_data *p = vd->certs;
+ struct hvb_cert_data *end = p + vd->num_loaded_certs;
+
+ for (; p < end; p++) {
+ if (devNameLen != strlen(p->partition_name)) {
+ continue;
+ }
+
+ if (memcmp(p->partition_name, devName, devNameLen) == 0) {
+ break;
+ }
+ }
+
+ if (p == end) {
+ BEGET_LOGE("error, can't found %s partition", devName);
+ return -1;
+ }
+
+ hr = hvb_cert_parser(cert, &p->data);
+ if (hr != HVB_OK) {
+ BEGET_LOGE("error 0x%x, parser hvb cert", hr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int FsHvbVerityTargetAppendString(char **p, char *end, char *str, size_t len)
+{
+ errno_t err;
+
+ // check range for append string
+ if (*p + len >= end || *p + len < *p) {
+ BEGET_LOGE("error, append string overflow");
+ return -1;
+ }
+ // append string
+ err = memcpy_s(*p, end - *p, str, len);
+ if (err != EOK) {
+ BEGET_LOGE("error 0x%x, cp string fail", err);
+ return -1;
+ }
+ *p += len;
+
+ // check range for append blank space
+ if (*p + 1 >= end || *p + 1 < *p) {
+ BEGET_LOGE("error, append blank space overflow");
+ return -1;
+ }
+ // append blank space
+ **p = FS_HVB_BLANK_SPACE_ASCII;
+ *p += 1;
+
+ BEGET_LOGI("append string %s", str);
+
+ return 0;
+}
+
+static int FsHvbVerityTargetAppendOctets(char **p, char *end, char *octs, size_t octs_len)
+{
+ size_t i;
+ int rc;
+ char *str = NULL;
+ size_t str_len = octs_len * 2;
+
+ str = calloc(1, str_len + 1);
+ if (str == NULL) {
+ BEGET_LOGE("error, calloc str fail");
+ return -1;
+ }
+
+ for (i = 0; i < octs_len; i++) {
+ str[2 * i] = FsHvbBinToHexChar((octs[i] >> 4) & 0xf);
+ str[2 * i + 1] = FsHvbBinToHexChar(octs[i] & 0xf);
+ }
+
+ rc = FsHvbVerityTargetAppendString(p, end, str, str_len);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, append str fail", rc);
+ }
+ free(str);
+
+ return rc;
+}
+
+static int FsHvbVerityTargetAppendNum(char **p, char *end, uint64_t num)
+{
+ int rc;
+ char num_str[FS_HVB_UINT64_MAX_LENGTH] = {0};
+
+ rc = sprintf_s(&num_str[0], sizeof(num_str), "%llu", num);
+ if (rc < 0) {
+ BEGET_LOGE("error 0x%x, calloc num_str", rc);
+ return rc;
+ }
+
+ rc = FsHvbVerityTargetAppendString(p, end, num_str, strlen(&num_str[0]));
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, append num_str fail", rc);
+ }
+
+ return rc;
+}
+
+#define RETURN_ERR_IF_APPEND_STRING_ERR(p, end, str, str_len) \
+ do { \
+ int __ret = FsHvbVerityTargetAppendString(p, end, str, str_len); \
+ if (__ret != 0) \
+ return __ret; \
+ } while (0)
+
+#define RETURN_ERR_IF_APPEND_OCTETS_ERR(p, end, octs, octs_len) \
+ do { \
+ int __ret = FsHvbVerityTargetAppendOctets(p, end, octs, octs_len); \
+ if (__ret != 0) \
+ return __ret; \
+ } while (0)
+
+#define RETURN_ERR_IF_APPEND_DIGIT_ERR(p, end, num) \
+ do { \
+ int __ret = FsHvbVerityTargetAppendNum(p, end, num); \
+ if (__ret != 0) \
+ return __ret; \
+ } while (0)
+
+static char *FsHvbGetHashAlgStr(unsigned int hash_algo)
+{
+ char *alg = NULL;
+
+ switch (hash_algo) {
+ case HASH_ALGO_SHA256:
+ alg = HASH_ALGO_SHA256_STR;
+ break;
+
+ case HASH_ALGO_SHA512:
+ alg = HASH_ALGO_SHA512_STR;
+ break;
+
+ case HASH_ALGO_SM3:
+ alg = HASH_ALGO_SM3_STR;
+ break;
+
+ default:
+ alg = NULL;
+ break;
+ }
+
+ return alg;
+}
+
+/*
+ * add optional fec data if supported, format as below;
+ *
+ */
+static int FsHvbVerityTargetAddFecArgs(struct hvb_cert *cert, char *devPath, char **str, char *end)
+{
+ FS_HVB_RETURN_ERR_IF_NULL(cert);
+ FS_HVB_RETURN_ERR_IF_NULL(devPath);
+ FS_HVB_RETURN_ERR_IF_NULL(str);
+ FS_HVB_RETURN_ERR_IF_NULL(end);
+
+ // append
+ RETURN_ERR_IF_APPEND_STRING_ERR(str, end, USE_FEC_FROM_DEVICE, strlen(USE_FEC_FROM_DEVICE));
+ RETURN_ERR_IF_APPEND_STRING_ERR(str, end, &devPath[0], strlen(devPath));
+
+ // append
+ RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_ROOTS, strlen(FEC_ROOTS));
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_num_roots);
+
+ if (cert->data_block_size == 0 || cert->hash_block_size == 0) {
+ BEGET_LOGE("error, block size is zero");
+ return -1;
+ }
+ // append
+ RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_BLOCKS, strlen(FEC_BLOCKS));
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_offset / cert->hash_block_size);
+
+ // append
+ RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_START, strlen(FEC_START));
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_offset / cert->data_block_size);
+
+ return 0;
+}
+
+/*
+ * target->paras is verity table target, format as below;
+ *
+ *
+ * [<#opt_params>]
+ * exp: 1 /dev/sda1 /dev/sda1 4096 4096 262144 262144 sha256 \
+ xxxxx
+ xxxxx
+ */
+
+int FsHvbConstructVerityTarget(DmVerityTarget *target, const char *devName, struct hvb_cert *cert)
+{
+ char *p = NULL;
+ char *end = NULL;
+ char *hashALgo = NULL;
+ char devPath[FS_HVB_DEVPATH_MAX_LEN] = {0};
+
+ FS_HVB_RETURN_ERR_IF_NULL(target);
+ FS_HVB_RETURN_ERR_IF_NULL(devName);
+ FS_HVB_RETURN_ERR_IF_NULL(cert);
+
+ target->start = 0;
+ target->length = cert->image_len / FS_HVB_SECTOR_BYTES;
+ target->paras = calloc(1, FS_HVB_VERITY_TARGET_MAX); // simple it, just calloc a big mem
+ if (target->paras == NULL) {
+ BEGET_LOGE("error, alloc target paras");
+ return -1;
+ }
+
+ if (snprintf_s(&devPath[0], sizeof(devPath), sizeof(devPath) - 1, "%s%s",
+ ((strchr(devName, '/') == NULL) ? FS_HVB_PARTITION_PREFIX : ""), devName) == -1) {
+ BEGET_LOGE("error, snprintf_s devPath");
+ return -1;
+ }
+
+ p = target->paras;
+ end = p + FS_HVB_VERITY_TARGET_MAX;
+
+ // append
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, 1);
+ // append
+ RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, &devPath[0], strlen(devPath));
+ // append
+ RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, &devPath[0], strlen(devPath));
+
+ if (cert->data_block_size == 0 || cert->hash_block_size == 0) {
+ BEGET_LOGE("error, block size is zero");
+ return -1;
+ }
+ // append
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->data_block_size);
+ // append
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->hash_block_size);
+ // append
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->image_len / cert->data_block_size);
+ // append
+ RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->hashtree_offset / cert->hash_block_size);
+
+ // append
+ hashALgo = FsHvbGetHashAlgStr(cert->hash_algo);
+ if (hashALgo == NULL) {
+ BEGET_LOGE("error, hash alg %d is invalid", cert->hash_algo);
+ return -1;
+ }
+ RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, hashALgo, strlen(hashALgo));
+
+ // append
+ RETURN_ERR_IF_APPEND_OCTETS_ERR(&p, end, (char *)cert->hash_payload.digest, cert->digest_size);
+
+ // append
+ RETURN_ERR_IF_APPEND_OCTETS_ERR(&p, end, (char *)cert->hash_payload.salt, cert->salt_size);
+
+ if (cert->fec_size > 0) {
+ if (FsHvbVerityTargetAddFecArgs(cert, devPath, &p, end) != 0) {
+ return -1;
+ }
+ }
+
+ // remove last blank
+ *(p - 1) = '\0';
+
+ target->paras_len = strlen(target->paras);
+
+ return 0;
+}
+
+static int FsHvbCreateVerityTarget(DmVerityTarget *target, char *devName, struct hvb_verified_data *vd)
+{
+ int rc;
+ struct hvb_cert cert = {0};
+
+ rc = FsHvbGetCert(&cert, devName, vd);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = FsHvbConstructVerityTarget(target, devName, &cert);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, can't construct verity target", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+static int FsExtHvbCreateVerityTarget(DmVerityTarget *target, const char *devName,
+ const char *partition, struct hvb_verified_data *vd)
+{
+ int rc;
+ struct hvb_cert cert = {0};
+
+ rc = FsHvbGetCert(&cert, partition, vd);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = FsHvbConstructVerityTarget(target, devName, &cert);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, can't construct verity target", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+void FsHvbDestoryVerityTarget(DmVerityTarget *target)
+{
+ if (target != NULL && target->paras != NULL) {
+ free(target->paras);
+ target->paras = NULL;
+ }
+}
+
+int FsHvbSetupHashtree(FstabItem *fsItem)
+{
+ int rc;
+ DmVerityTarget target = {0};
+ char *dmDevPath = NULL;
+ char *devName = NULL;
+
+ FS_HVB_RETURN_ERR_IF_NULL(fsItem);
+ FS_HVB_RETURN_ERR_IF_NULL(g_vd);
+
+ // fsItem->deviceName is like /dev/block/platform/xxx/by-name/system
+ // we just basename system
+ devName = basename(fsItem->deviceName);
+ if (devName == NULL) {
+ BEGET_LOGE("error, get basename");
+ return -1;
+ }
+
+ rc = FsHvbCreateVerityTarget(&target, devName, g_vd);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create verity-table", rc);
+ goto exit;
+ }
+
+ rc = FsDmCreateDevice(&dmDevPath, devName, &target);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create dm-verity", rc);
+ goto exit;
+ }
+
+ rc = FsDmInitDmDev(dmDevPath, true);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create init dm dev", rc);
+ goto exit;
+ }
+
+ free(fsItem->deviceName);
+ fsItem->deviceName = dmDevPath;
+
+exit:
+ FsHvbDestoryVerityTarget(&target);
+
+ return rc;
+}
+
+static int FsExtHvbSetupHashtree(const char *devName, const char *partition, char **outPath)
+{
+ int rc;
+ DmVerityTarget target = {0};
+ char *tmpDevName = NULL;
+ char *dmDevPath = NULL;
+ size_t devLen;
+
+ FS_HVB_RETURN_ERR_IF_NULL(g_extVd);
+
+ devLen = strnlen(devName, FS_HVB_MAX_PATH_LEN);
+ if (devLen >= FS_HVB_MAX_PATH_LEN) {
+ BEGET_LOGE("error, invalid devName");
+ return -1;
+ }
+ tmpDevName = malloc(devLen + 1);
+ if (tmpDevName == NULL) {
+ BEGET_LOGE("error, fail to malloc");
+ return -1;
+ }
+
+ (void)memset_s(tmpDevName, devLen + 1, 0, devLen + 1);
+ if (memcpy_s(tmpDevName, devLen + 1, devName, devLen) != 0) {
+ free(tmpDevName);
+ BEGET_LOGE("error, fail to copy");
+ return -1;
+ }
+
+ rc = FsExtHvbCreateVerityTarget(&target, tmpDevName, partition, g_extVd);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create verity-table", rc);
+ goto exit;
+ }
+
+ rc = FsDmCreateDevice(&dmDevPath, basename(tmpDevName), &target);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create dm-verity", rc);
+ goto exit;
+ }
+
+ rc = FsDmInitDmDev(dmDevPath, true);
+ if (rc != 0) {
+ BEGET_LOGE("error 0x%x, create init dm dev", rc);
+ goto exit;
+ }
+
+ *outPath = dmDevPath;
+
+exit:
+ FsHvbDestoryVerityTarget(&target);
+ free(tmpDevName);
+ return rc;
+}
+
+int FsHvbFinal(InitHvbType hvbType)
+{
+ struct hvb_verified_data **currVd = NULL;
+
+ if (GetCurrVerifiedData(hvbType, &currVd) != HVB_OK) {
+ BEGET_LOGE("error GetCurrVerifiedData");
+ return -1;
+ }
+ if (*currVd != NULL) {
+ hvb_chain_verify_data_free(*currVd);
+ *currVd = NULL;
+ }
+
+ return 0;
+}
+
+int FsHvbGetValueFromCmdLine(char *val, size_t size, const char *key)
+{
+ FS_HVB_RETURN_ERR_IF_NULL(val);
+ FS_HVB_RETURN_ERR_IF_NULL(key);
+
+ return GetExactParameterFromCmdLine(key, val, size, EMPTY_VALUE);
+}
+
+int VerifyExtHvbImage(const char *devPath, const char *partition, char **outPath)
+{
+ int rc;
+ FS_HVB_RETURN_ERR_IF_NULL(devPath);
+ FS_HVB_RETURN_ERR_IF_NULL(partition);
+ FS_HVB_RETURN_ERR_IF_NULL(outPath);
+
+ rc = FsHvbInit(EXT_HVB);
+ if (rc != 0) {
+ BEGET_LOGE("ext hvb error, ret=%d", rc);
+ goto exit;
+ }
+
+ rc = FsExtHvbSetupHashtree(devPath, partition, outPath);
+ if (rc != 0) {
+ BEGET_LOGE("error, setup hashtree fail, ret=%d", rc);
+ }
+
+exit:
+ if (FsHvbFinal(EXT_HVB) != 0) {
+ BEGET_LOGE("final ext hvb error, ret=%d", rc);
+ return -1;
+ }
+ return rc;
+}
+
+bool CheckAndGetExt4Size(const char *headerBuf, uint64_t *imageSize, const char* image)
+{
+ ext4_super_block *superBlock = (ext4_super_block *)headerBuf;
+
+ if (headerBuf == NULL || imageSize == NULL || image == NULL) {
+ BEGET_LOGE("param is error");
+ return false;
+ }
+
+ if (superBlock->s_magic == EXT4_SUPER_MAGIC) {
+ *imageSize = (uint64_t)superBlock->s_blocks_count_lo * BLOCK_SIZE_UNIT;
+ BEGET_LOGI("%s is ext4:[block cout]: %d, [size]: 0x%lx", image,
+ superBlock->s_blocks_count_lo, *imageSize);
+ return true;
+ }
+ return false;
+}
+
+bool CheckAndGetErofsSize(const char *headerBuf, uint64_t *imageSize, const char* image)
+{
+ struct erofs_super_block *superBlock = (struct erofs_super_block *)headerBuf;
+
+ if (headerBuf == NULL || imageSize == NULL || image == NULL) {
+ BEGET_LOGE("param is error");
+ return false;
+ }
+
+ if (superBlock->magic == EROFS_SUPER_MAGIC) {
+ *imageSize = (uint64_t)superBlock->blocks * BLOCK_SIZE_UINT;
+ BEGET_LOGI("%s is erofs:[block cout]: %d, [size]: 0x%lx", image,
+ superBlock->blocks, *imageSize);
+ return true;
+ }
+ return false;
+}
+
+bool CheckAndGetExtheaderSize(const int fd, uint64_t offset,
+ uint64_t *imageSize, const char* image)
+{
+ ExtheaderV1 header;
+ ssize_t nbytes;
+ if (fd < 0 || imageSize == NULL || image == NULL) {
+ BEGET_LOGE("param is error");
+ return false;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ BEGET_LOGE("lseek %s failed for offset 0x%lx", image, offset);
+ return false;
+ }
+
+ nbytes = read(fd, &header, sizeof(header));
+ if (nbytes != sizeof(header)) {
+ BEGET_LOGE("read %s failed.", image);
+ return false;
+ }
+
+ if (header.magicNumber != EXTHDR_MAGIC) {
+ BEGET_LOGW("%s extheader doesnt match, magic is 0x%lx", image, header.magicNumber);
+ return false;
+ }
+
+ *imageSize = header.partSize;
+ return true;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c b/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c
new file mode 100755
index 0000000000000000000000000000000000000000..9fe9a838de88758f2555e59510cd9b1b90078a7f
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "beget_ext.h"
+#include "fs_dm.h"
+#include "fs_hvb.h"
+#include "securec.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define PARTITION_PATH_PREFIX "/dev/block/by-name/"
+#define MAX_EXT_HVB_PARTITION_NUM 1
+
+static const ExtHvbVerifiedDev g_extVerifiedDev[] = {
+ {
+ .partitionName = "module_update",
+ .pathName = "/data/module_update/active/ModuleTrain/module.img"
+ },
+};
+
+static int64_t GetImageSizeForHVB(const int fd, const char* image)
+{
+ char headerBuf[SZ_2KB] = {0};
+ ssize_t nbytes;
+ uint64_t fileSysSize;
+ uint64_t realFileSize;
+
+ if (fd < 0) {
+ BEGET_LOGE("param is error");
+ return -1;
+ }
+
+ lseek64(fd, 0, SEEK_SET);
+ nbytes = read(fd, &headerBuf, sizeof(headerBuf));
+ if (nbytes != sizeof(headerBuf)) {
+ BEGET_LOGE("read file system header fail");
+ return -1;
+ }
+
+ if (CheckAndGetErofsSize(&headerBuf[SZ_1KB], &fileSysSize, image) &&
+ CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) {
+ BEGET_LOGI("get %s size from erofs and extheader, size=0x%lx", image, realFileSize);
+ return realFileSize;
+ } else if (CheckAndGetExt4Size(&headerBuf[SZ_1KB], &fileSysSize, image) &&
+ CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) {
+ BEGET_LOGI("get %s size from ext4 and extheader, size=0x%lx", image, realFileSize);
+ return realFileSize;
+ } else {
+ BEGET_LOGI("read %s file extheader fail, use the actual img size", image);
+ }
+
+ return lseek64(fd, 0, SEEK_END);
+}
+
+static bool IsExtHvbVerifiedPtn(const char *ptn, size_t ptnLen, size_t *outIndex)
+{
+ int index;
+ if (ptn == NULL || outIndex == NULL) {
+ BEGET_LOGE("error, invalid ptn");
+ return false;
+ }
+
+ for (index = 0; index < MAX_EXT_HVB_PARTITION_NUM; index++) {
+ if (strncmp(g_extVerifiedDev[index].partitionName, ptn, ptnLen) == 0) {
+ *outIndex = index;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static char *GetExtHvbVerifiedPath(size_t index)
+{
+ char *tmpPath = NULL;
+
+ if (index >= MAX_EXT_HVB_PARTITION_NUM) {
+ BEGET_LOGE("error, invalid index");
+ return NULL;
+ }
+
+ size_t pathLen = strnlen(g_extVerifiedDev[index].pathName, FS_HVB_MAX_PATH_LEN);
+ if (pathLen >= FS_HVB_MAX_PATH_LEN) {
+ BEGET_LOGE("error, invalid path");
+ return tmpPath;
+ }
+ tmpPath = malloc(pathLen + 1);
+ if (tmpPath == NULL) {
+ BEGET_LOGE("error, fail to malloc");
+ return NULL;
+ }
+
+ (void)memset_s(tmpPath, pathLen + 1, 0, pathLen + 1);
+ if (memcpy_s(tmpPath, pathLen + 1, g_extVerifiedDev[index].pathName, pathLen) != 0) {
+ free(tmpPath);
+ BEGET_LOGE("error, fail to copy");
+ return NULL;
+ }
+ return tmpPath;
+}
+
+static char *HvbGetPartitionPath(const char *partition)
+{
+ int rc;
+ size_t pathLen;
+ char *path = NULL;
+ size_t index;
+ size_t ptnLen = strnlen(partition, HVB_MAX_PARTITION_NAME_LEN);
+ if (ptnLen >= HVB_MAX_PARTITION_NAME_LEN) {
+ BEGET_LOGE("error, invalid ptn name");
+ return NULL;
+ }
+ if (IsExtHvbVerifiedPtn(partition, ptnLen, &index)) {
+ return GetExtHvbVerifiedPath(index);
+ }
+
+ pathLen = strlen(PARTITION_PATH_PREFIX) + ptnLen;
+ path = calloc(1, pathLen + 1);
+ if (path == NULL) {
+ BEGET_LOGE("error, calloc fail");
+ return NULL;
+ }
+ rc = snprintf_s(path, pathLen + 1, pathLen, "%s%s", PARTITION_PATH_PREFIX,
+ partition);
+ if (rc < 0) {
+ BEGET_LOGE("error, snprintf_s fail, ret = %d", rc);
+ free(path);
+ return NULL;
+ }
+ return path;
+}
+
+static enum hvb_io_errno HvbReadFromPartition(struct hvb_ops* ops,
+ const char* partition,
+ int64_t offset, uint64_t numBytes,
+ void* buf, uint64_t* outNumRead)
+{
+ int fd = -1;
+ char *path = NULL;
+ enum hvb_io_errno ret = HVB_IO_ERROR_IO;
+
+ if (ops == NULL || partition == NULL ||
+ buf == NULL || outNumRead == NULL) {
+ BEGET_LOGE("error, invalid parameter");
+ return HVB_IO_ERROR_IO;
+ }
+
+ /* get and malloc img path */
+ path = HvbGetPartitionPath(partition);
+ if (path == NULL) {
+ BEGET_LOGE("error, get partition path");
+ ret = HVB_IO_ERROR_OOM;
+ goto exit;
+ }
+
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ BEGET_LOGE("error, Failed to open %s, errno = %d", path, errno);
+ ret = HVB_IO_ERROR_IO;
+ goto exit;
+ }
+
+ if (offset < 0) {
+ int64_t total_size = GetImageSizeForHVB(fd, partition);
+ if (total_size == -1) {
+ BEGET_LOGE("Failed to get the size of the partition %s", partition);
+ ret = HVB_IO_ERROR_IO;
+ goto exit;
+ }
+ offset = total_size + offset;
+ }
+
+ lseek64(fd, offset, SEEK_SET);
+
+ ssize_t numRead = read(fd, buf, numBytes);
+ if (numRead < 0 || (size_t)numRead != numBytes) {
+ BEGET_LOGE("Failed to read %lld bytes from %s offset %lld", numBytes,
+ path, offset);
+ ret = HVB_IO_ERROR_IO;
+ goto exit;
+ }
+
+ *outNumRead = numRead;
+
+ ret = HVB_IO_OK;
+
+exit:
+
+ if (path != NULL) {
+ free(path);
+ }
+
+ if (fd >= 0) {
+ close(fd);
+ }
+ return ret;
+}
+
+static enum hvb_io_errno HvbWriteToPartition(struct hvb_ops* ops,
+ const char* partition,
+ int64_t offset, uint64_t numBytes,
+ const void* buf)
+{
+ return HVB_IO_OK;
+}
+
+static enum hvb_io_errno HvbInvaldateKey(struct hvb_ops* ops,
+ const uint8_t* publicKeyData,
+ uint64_t publicKeyLength,
+ const uint8_t* publicKeyMetadata,
+ uint64_t publicKeyMetadataLength,
+ bool* outIsTrusted)
+{
+ if (outIsTrusted == NULL) {
+ return HVB_IO_ERROR_IO;
+ }
+
+ *outIsTrusted = true;
+
+ return HVB_IO_OK;
+}
+
+static enum hvb_io_errno HvbReadRollbackIdx(struct hvb_ops* ops,
+ uint64_t rollBackIndexLocation,
+ uint64_t* outRollbackIndex)
+{
+ if (outRollbackIndex == NULL) {
+ return HVB_IO_ERROR_IO;
+ }
+
+ // return 0 as we only need to set up HVB HASHTREE partitions
+ *outRollbackIndex = 0;
+
+ return HVB_IO_OK;
+}
+
+static enum hvb_io_errno HvbWriteRollbackIdx(struct hvb_ops* ops,
+ uint64_t rollBackIndexLocation,
+ uint64_t rollbackIndex)
+{
+ return HVB_IO_OK;
+}
+
+static enum hvb_io_errno HvbReadLockState(struct hvb_ops* ops,
+ bool* lock_state)
+{
+ return HVB_IO_OK;
+}
+
+static enum hvb_io_errno HvbGetSizeOfPartition(struct hvb_ops* ops,
+ const char* partition,
+ uint64_t* size)
+{
+ if (size == NULL) {
+ return HVB_IO_ERROR_IO;
+ }
+
+ // The function is for bootloader to load entire content of HVB HASH
+ // partitions. In user-space, return 0 as we only need to set up HVB
+ // HASHTREE partitions.
+ *size = 0;
+ return HVB_IO_OK;
+}
+
+static struct hvb_ops g_hvb_ops = {
+ .user_data = &g_hvb_ops,
+ .read_partition = HvbReadFromPartition,
+ .write_partition = HvbWriteToPartition,
+ .valid_rvt_key = HvbInvaldateKey,
+ .read_rollback = HvbReadRollbackIdx,
+ .write_rollback = HvbWriteRollbackIdx,
+ .read_lock_state = HvbReadLockState,
+ .get_partiton_size = HvbGetSizeOfPartition,
+};
+
+struct hvb_ops* FsHvbGetOps(void)
+{
+ return &g_hvb_ops;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/interfaces/innerkits/fs_manager/libfs_hvb/include/fs_hvb.h b/interfaces/innerkits/fs_manager/libfs_hvb/include/fs_hvb.h
new file mode 100755
index 0000000000000000000000000000000000000000..b5c76cd9fe5f2666faaa04adfd1941c2ba5227e8
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/libfs_hvb/include/fs_hvb.h
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2023 Huawei Device Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STARTUP_LIBFS_HVB_H
+#define STARTUP_LIBFS_HVB_H
+
+#include
+#include
+#include
+#include
+#include
+#include "fs_dm.h"
+#include "fs_manager.h"
+#include "ext4_super_block.h"
+#include "erofs_super_block.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define USE_FEC_FROM_DEVICE "use_fec_from_device"
+#define FEC_ROOTS "fec_roots"
+#define FEC_BLOCKS "fec_blocks"
+#define FEC_START "fec_start"
+#define BLOCK_SIZE_UINT 4096
+#define EXTHDR_MAGIC 0xFEEDBEEF
+#define EXTHDR_BLKSIZ 4096
+#define SZ_1KB (0x1 << 10)
+#define SZ_1MB (0x1 << 20)
+#define SZ_1GB (0x1 << 30)
+
+#define SZ_2KB (2 * SZ_1KB)
+#define SZ_4KB (4 * SZ_1KB)
+#define FS_HVB_MAX_PATH_LEN 128
+
+typedef struct {
+ uint32_t magicNumber;
+ uint16_t exthdrSize;
+ uint16_t bcc16;
+ uint64_t partSize;
+} ExtheaderV1;
+
+typedef enum InitHvbType {
+ MAIN_HVB = 0,
+ EXT_HVB
+} InitHvbType;
+
+typedef struct {
+ char *partitionName;
+ char *pathName;
+} ExtHvbVerifiedDev;
+
+int FsHvbInit(InitHvbType hvbType);
+int FsHvbSetupHashtree(FstabItem *fsItem);
+int FsHvbFinal(InitHvbType hvbType);
+struct hvb_ops *FsHvbGetOps(void);
+int FsHvbGetValueFromCmdLine(char *val, size_t size, const char *key);
+int FsHvbConstructVerityTarget(DmVerityTarget *target, const char *devName, struct hvb_cert *cert);
+void FsHvbDestoryVerityTarget(DmVerityTarget *target);
+int VerifyExtHvbImage(const char *dev_path, const char *partition, char **out_path);
+
+bool CheckAndGetExt4Size(const char *headerBuf, uint64_t *imageSize, const char* image);
+bool CheckAndGetErofsSize(const char *headerBuf, uint64_t *imageSize, const char* image);
+bool CheckAndGetExtheaderSize(const int fd, uint64_t offset, uint64_t *imageSize, const char* image);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // STARTUP_LIBFS_HVB_H
diff --git a/services/include/init_capability.h b/interfaces/innerkits/fs_manager/switch_root/include/switch_root.h
similarity index 78%
rename from services/include/init_capability.h
rename to interfaces/innerkits/fs_manager/switch_root/include/switch_root.h
index 842959e73e0cc043949640656e435d7aa01e8d26..d8e7b46f9229b7a76949f52fdab254e02ed9ac63 100644
--- a/services/include/init_capability.h
+++ b/interfaces/innerkits/fs_manager/switch_root/include/switch_root.h
@@ -13,13 +13,9 @@
* limitations under the License.
*/
-#ifndef INIT_CAPABILITY_H
-#define INIT_CAPABILITY_H
+#ifndef INIT_SWITCH_ROOT_H
+#define INIT_SWITCH_ROOT_H
-#include "cJSON.h"
-#include "init_service.h"
-
-int GetServiceCaps(const cJSON* curArrItem, Service* curServ);
-
-#endif
+int SwitchRoot(const char *newRoot);
+#endif // INIT_SWITCH_ROOT_H
\ No newline at end of file
diff --git a/interfaces/innerkits/fs_manager/switch_root/switch_root.c b/interfaces/innerkits/fs_manager/switch_root/switch_root.c
new file mode 100644
index 0000000000000000000000000000000000000000..0855ff785495dde668fb10e03fb77afd72b4c730
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/switch_root/switch_root.c
@@ -0,0 +1,193 @@
+/*
+ * 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 "switch_root.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "init_log.h"
+#include "fs_manager/fs_manager.h"
+#include "securec.h"
+#include "init_utils.h"
+
+static void FreeOldRoot(DIR *dir, dev_t dev)
+{
+ if (dir == NULL) {
+ return;
+ }
+ int dfd = dirfd(dir);
+ bool isDir = false;
+ struct dirent *de = NULL;
+ while ((de = readdir(dir)) != NULL) {
+ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) {
+ continue;
+ }
+ isDir = false;
+ if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
+ struct stat st = {};
+ if (fstatat(dfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
+ INIT_LOGE("Failed to get stat of %s", de->d_name);
+ continue;
+ }
+
+ if (st.st_dev != dev) {
+ continue; // Not the same device, ignore.
+ }
+ if (!S_ISDIR(st.st_mode)) {
+ continue;
+ }
+ int fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+ isDir = true;
+ if (fd < 0) {
+ continue;
+ }
+ DIR *subDir = fdopendir(fd);
+ if (subDir != NULL) {
+ FreeOldRoot(subDir, dev);
+ closedir(subDir);
+ } else {
+ close(fd);
+ }
+ }
+ if (unlinkat(dfd, de->d_name, isDir ? AT_REMOVEDIR : 0) < 0) {
+ INIT_LOGE("Failed to unlink %s, err = %d", de->d_name, errno);
+ }
+ }
+}
+
+// For sub mountpoint under /dev, /sys, /proc
+// There is no need to move them individually
+// We will find a better solution to take care of
+// all sub mount tree in the future.
+static bool UnderBasicMountPoint(const char *path)
+{
+ unsigned int i;
+ if (path == NULL || *path == '\0') {
+ return false;
+ }
+ const char *basicMountPoint[] = {"/dev/", "/sys/", "/proc/"};
+ for (i = 0; i < ARRAY_LENGTH(basicMountPoint); i++) {
+ if (strncmp(path, basicMountPoint[i], strlen(basicMountPoint[i])) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static int MountToNewTarget(const char *target)
+{
+ if (target == NULL || *target == '\0') {
+ return -1;
+ }
+ Fstab *fstab = ReadFstabFromFile("/proc/mounts", true);
+ if (fstab == NULL) {
+ INIT_LOGE("Fatal error. Read mounts info from \" /proc/mounts \" failed");
+ return -1;
+ }
+
+ for (FstabItem *item = fstab->head; item != NULL; item = item->next) {
+ const char *mountPoint = item->mountPoint;
+ if (mountPoint == NULL || strcmp(mountPoint, "/") == 0 ||
+ strcmp(mountPoint, target) == 0) {
+ continue;
+ }
+ char newMountPoint[PATH_MAX] = {0};
+ if (snprintf_s(newMountPoint, PATH_MAX, PATH_MAX - 1, "%s%s", target, mountPoint) == -1) {
+ INIT_LOGW("Cannot build new mount point for old mount point \" %s \"", mountPoint);
+ // Just ignore this one or return error?
+ continue;
+ }
+ INIT_LOGV("new mount point is: %s", newMountPoint);
+ if (!UnderBasicMountPoint(mountPoint)) {
+ INIT_LOGV("Move mount %s to %s", mountPoint, newMountPoint);
+ if (mount(mountPoint, newMountPoint, NULL, MS_MOVE, NULL) < 0) {
+ INIT_LOGE("Failed to mount moving %s to %s, err = %d", mountPoint, newMountPoint, errno);
+ // If one mount entry cannot move to new mountpoint, umount it.
+ umount2(mountPoint, MNT_FORCE);
+ continue;
+ }
+ }
+ }
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return 0;
+}
+
+static void FreeRootDir(DIR *oldRoot, dev_t dev)
+{
+ if (oldRoot != NULL) {
+ FreeOldRoot(oldRoot, dev);
+ closedir(oldRoot);
+ }
+}
+
+// Switch root from ramdisk to system
+int SwitchRoot(const char *newRoot)
+{
+ if (newRoot == NULL || *newRoot == '\0') {
+ errno = EINVAL;
+ INIT_LOGE("Fatal error. Try to switch to new root with invalid new mount point");
+ return -1;
+ }
+
+ struct stat oldRootStat = {};
+ INIT_ERROR_CHECK(stat("/", &oldRootStat) == 0, return -1, "Failed to get old root \"/\" stat");
+ DIR *oldRoot = opendir("/");
+ INIT_ERROR_CHECK(oldRoot != NULL, return -1, "Failed to open root dir \"/\"");
+ struct stat newRootStat = {};
+ if (stat(newRoot, &newRootStat) != 0) {
+ INIT_LOGE("Failed to get new root \" %s \" stat", newRoot);
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ return -1;
+ }
+
+ if (oldRootStat.st_dev == newRootStat.st_dev) {
+ INIT_LOGW("Try to switch root in same device, skip switching root");
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ return 0;
+ }
+ if (MountToNewTarget(newRoot) < 0) {
+ INIT_LOGE("Failed to move mount to new root \" %s \" stat", newRoot);
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ return -1;
+ }
+ // OK, we've done move mount.
+ // Now mount new root.
+ if (chdir(newRoot) < 0) {
+ INIT_LOGE("Failed to change directory to %s, err = %d", newRoot, errno);
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ return -1;
+ }
+
+ if (mount(newRoot, "/", NULL, MS_MOVE, NULL) < 0) {
+ INIT_LOGE("Failed to mount moving %s to %s, err = %d", newRoot, "/", errno);
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ return -1;
+ }
+
+ if (chroot(".") < 0) {
+ INIT_LOGE("Failed to change root directory");
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ return -1;
+ }
+ FreeRootDir(oldRoot, oldRootStat.st_dev);
+ INIT_LOGI("SwitchRoot to %s finish", newRoot);
+ return 0;
+}
diff --git a/interfaces/innerkits/hookmgr/hookmgr.c b/interfaces/innerkits/hookmgr/hookmgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..5776f4df0fa113250a587b7d3e9e31495da1a45c
--- /dev/null
+++ b/interfaces/innerkits/hookmgr/hookmgr.c
@@ -0,0 +1,390 @@
+/*
+ * 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 "list.h"
+#include "beget_ext.h"
+#include "hookmgr.h"
+
+// Forward declaration
+typedef struct tagHOOK_STAGE HOOK_STAGE;
+
+/*
+ * Internal HOOK Item with priorities
+ */
+typedef struct tagHOOK_ITEM {
+ ListNode node;
+ HOOK_INFO info;
+ HOOK_STAGE *stage;
+} HOOK_ITEM;
+
+/*
+ * Internal HOOK Stage in the same stage
+ */
+struct tagHOOK_STAGE {
+ ListNode node;
+ int stage;
+ ListNode hooks;
+};
+
+/*
+ * HookManager is consist of different hook stages
+ */
+struct tagHOOK_MGR {
+ const char *name;
+ ListNode stages;
+};
+
+/*
+ * Default HookManager is created automatically for HookMgrAddHook
+ */
+static HOOK_MGR *defaultHookMgr = NULL;
+
+static HOOK_MGR *getHookMgr(HOOK_MGR *hookMgr, int autoCreate)
+{
+ BEGET_CHECK(hookMgr == NULL, return hookMgr);
+ // Use default HOOK_MGR if possible
+ BEGET_CHECK(defaultHookMgr == NULL, return defaultHookMgr);
+
+ BEGET_CHECK(autoCreate, return NULL);
+
+ // Create default HOOK_MGR if not created
+ defaultHookMgr = HookMgrCreate("default");
+ return defaultHookMgr;
+}
+
+static int hookStageCompare(ListNode *node, void *data)
+{
+ const HOOK_STAGE *stage;
+ int compareStage = *((int *)data);
+
+ stage = (const HOOK_STAGE *)node;
+ return (stage->stage - compareStage);
+}
+
+static void hookStageDestroy(ListNode *node)
+{
+ HOOK_STAGE *stage;
+
+ BEGET_CHECK(node != NULL, return);
+
+ stage = (HOOK_STAGE *)node;
+ OH_ListRemoveAll(&(stage->hooks), NULL);
+ free((void *)stage);
+}
+
+// Get HOOK_STAGE if found, otherwise create it
+static HOOK_STAGE *getHookStage(HOOK_MGR *hookMgr, int stage, int createIfNotFound)
+{
+ HOOK_STAGE *stageItem;
+
+ stageItem = (HOOK_STAGE *)OH_ListFind(&(hookMgr->stages), (void *)(&stage), hookStageCompare);
+ BEGET_CHECK(stageItem == NULL, return stageItem);
+
+ BEGET_CHECK(createIfNotFound, return NULL);
+
+ // Not found, create it
+ stageItem = (HOOK_STAGE *)malloc(sizeof(HOOK_STAGE));
+ BEGET_CHECK(stageItem != NULL, return NULL);
+ stageItem->stage = stage;
+ OH_ListInit(&(stageItem->hooks));
+ OH_ListAddTail(&(hookMgr->stages), (ListNode *)stageItem);
+ return stageItem;
+}
+
+static int hookItemCompare(ListNode *node, ListNode *newNode)
+{
+ const HOOK_ITEM *hookItem;
+ const HOOK_ITEM *newItem;
+
+ hookItem = (const HOOK_ITEM *)node;
+ newItem = (const HOOK_ITEM *)newNode;
+ return (hookItem->info.prio - newItem->info.prio);
+}
+
+struct HOOKITEM_COMPARE_VAL {
+ int prio;
+ OhosHook hook;
+ void *hookCookie;
+};
+
+static int hookItemCompareValue(ListNode *node, void *data)
+{
+ const HOOK_ITEM *hookItem;
+ struct HOOKITEM_COMPARE_VAL *compareVal = (struct HOOKITEM_COMPARE_VAL *)data;
+
+ hookItem = (const HOOK_ITEM *)node;
+ BEGET_CHECK(hookItem->info.prio == compareVal->prio, return (hookItem->info.prio - compareVal->prio));
+ if (hookItem->info.hook == compareVal->hook && hookItem->info.hookCookie == compareVal->hookCookie) {
+ return 0;
+ }
+ return -1;
+}
+
+// Add hook to stage list with prio ordered
+static int addHookToStage(HOOK_STAGE *hookStage, int prio, OhosHook hook, void *hookCookie)
+{
+ HOOK_ITEM *hookItem;
+ struct HOOKITEM_COMPARE_VAL compareVal;
+
+ // Check if exists
+ compareVal.prio = prio;
+ compareVal.hook = hook;
+ compareVal.hookCookie = hookCookie;
+ hookItem = (HOOK_ITEM *)OH_ListFind(&(hookStage->hooks), (void *)(&compareVal), hookItemCompareValue);
+ BEGET_CHECK(hookItem == NULL, return 0);
+
+ // Create new item
+ hookItem = (HOOK_ITEM *)malloc(sizeof(HOOK_ITEM));
+ BEGET_CHECK(hookItem != NULL, return -1);
+ hookItem->info.stage = hookStage->stage;
+ hookItem->info.prio = prio;
+ hookItem->info.hook = hook;
+ hookItem->info.hookCookie = hookCookie;
+ hookItem->stage = hookStage;
+
+ // Insert with order
+ OH_ListAddWithOrder(&(hookStage->hooks), (ListNode *)hookItem, hookItemCompare);
+ return 0;
+}
+
+int HookMgrAddEx(HOOK_MGR *hookMgr, const HOOK_INFO *hookInfo)
+{
+ HOOK_STAGE *stageItem;
+ BEGET_CHECK(hookInfo != NULL, return -1);
+ BEGET_CHECK(hookInfo->hook != NULL, return -1);
+
+ // Get HOOK_MGR
+ hookMgr = getHookMgr(hookMgr, true);
+ BEGET_CHECK(hookMgr != NULL, return -1);
+
+ // Get HOOK_STAGE list
+ stageItem = getHookStage(hookMgr, hookInfo->stage, true);
+ BEGET_CHECK(stageItem != NULL, return -1);
+
+ // Add hook to stage
+ return addHookToStage(stageItem, hookInfo->prio, hookInfo->hook, hookInfo->hookCookie);
+}
+
+int HookMgrAdd(HOOK_MGR *hookMgr, int stage, int prio, OhosHook hook)
+{
+ HOOK_INFO info;
+ info.stage = stage;
+ info.prio = prio;
+ info.hook = hook;
+ info.hookCookie = NULL;
+ return HookMgrAddEx(hookMgr, &info);
+}
+
+static int hookTraversalDelProc(ListNode *node, void *cookie)
+{
+ HOOK_ITEM *hookItem = (HOOK_ITEM *)node;
+
+ // Not equal, just return
+ BEGET_CHECK((void *)hookItem->info.hook == cookie, return 0);
+
+ // Remove from the list
+ OH_ListRemove(node);
+ // Destroy myself
+ free((void *)node);
+
+ return 0;
+}
+
+/*
+ * 删除钩子函数
+ * hook为NULL,表示删除该stage上的所有hooks
+ */
+void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook)
+{
+ HOOK_STAGE *stageItem;
+
+ // Get HOOK_MGR
+ hookMgr = getHookMgr(hookMgr, 0);
+ BEGET_CHECK(hookMgr != NULL, return);
+
+ // Get HOOK_STAGE list
+ stageItem = getHookStage(hookMgr, stage, false);
+ BEGET_CHECK(stageItem != NULL, return);
+
+ if (hook != NULL) {
+ OH_ListTraversal(&(stageItem->hooks), hook, hookTraversalDelProc, 0);
+ return;
+ }
+
+ // Remove from list
+ OH_ListRemove((ListNode *)stageItem);
+
+ // Destroy stage item
+ hookStageDestroy((ListNode *)stageItem);
+}
+
+typedef struct tagHOOK_EXECUTION_ARGS {
+ void *executionContext;
+ const HOOK_EXEC_OPTIONS *options;
+} HOOK_EXECUTION_ARGS;
+
+static int hookExecutionProc(ListNode *node, void *cookie)
+{
+ int ret;
+ HOOK_ITEM *hookItem = (HOOK_ITEM *)node;
+ HOOK_EXECUTION_ARGS *args = (HOOK_EXECUTION_ARGS *)cookie;
+
+ if ((args->options != NULL) && (args->options->preHook != NULL)) {
+ args->options->preHook(&hookItem->info, args->executionContext);
+ }
+ ret = hookItem->info.hook(&hookItem->info, args->executionContext);
+ if ((args->options != NULL) && (args->options->postHook != NULL)) {
+ args->options->postHook(&hookItem->info, args->executionContext, ret);
+ }
+
+ return ret;
+}
+
+/*
+ * 执行钩子函数
+ */
+int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *options)
+{
+ unsigned int flags;
+ HOOK_STAGE *stageItem;
+ HOOK_EXECUTION_ARGS args;
+
+ // Get HOOK_MGR
+ hookMgr = getHookMgr(hookMgr, 0);
+ BEGET_CHECK(hookMgr != NULL, return -1)
+
+ // Get HOOK_STAGE list
+ stageItem = getHookStage(hookMgr, stage, false);
+ BEGET_CHECK(stageItem != NULL, return ERR_NO_HOOK_STAGE);
+
+ flags = 0;
+ if (options != NULL) {
+ flags = (unsigned int)(options->flags);
+ }
+
+ args.executionContext = executionContext;
+ args.options = options;
+
+ // Traversal all hooks in the specified stage
+ return OH_ListTraversal(&(stageItem->hooks), (void *)(&args), hookExecutionProc, flags);
+}
+
+HOOK_MGR *HookMgrCreate(const char *name)
+{
+ HOOK_MGR *ret;
+
+ BEGET_CHECK(name != NULL, return NULL);
+ ret = (HOOK_MGR *)malloc(sizeof(HOOK_MGR));
+ BEGET_CHECK(ret != NULL, return NULL);
+
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ free((void *)ret);
+ return NULL;
+ }
+ OH_ListInit(&(ret->stages));
+ return ret;
+}
+
+void HookMgrDestroy(HOOK_MGR *hookMgr)
+{
+ hookMgr = getHookMgr(hookMgr, 0);
+ BEGET_CHECK(hookMgr != NULL, return);
+
+ OH_ListRemoveAll(&(hookMgr->stages), hookStageDestroy);
+
+ if (hookMgr == defaultHookMgr) {
+ defaultHookMgr = NULL;
+ }
+ if (hookMgr->name != NULL) {
+ free((void *)hookMgr->name);
+ }
+ free((void *)hookMgr);
+}
+
+typedef struct tagHOOK_TRAVERSAL_ARGS {
+ void *traversalCookie;
+ OhosHookTraversal traversal;
+} HOOK_TRAVERSAL_ARGS;
+
+static int hookItemTraversal(ListNode *node, void *data)
+{
+ HOOK_ITEM *hookItem;
+ HOOK_TRAVERSAL_ARGS *stageArgs;
+
+ hookItem = (HOOK_ITEM *)node;
+ stageArgs = (HOOK_TRAVERSAL_ARGS *)data;
+
+ stageArgs->traversal(&(hookItem->info), stageArgs->traversalCookie);
+ return 0;
+}
+
+static int hookStageTraversal(ListNode *node, void *data)
+{
+ HOOK_STAGE *stageItem = (HOOK_STAGE *)node;
+ OH_ListTraversal(&(stageItem->hooks), data, hookItemTraversal, 0);
+ return 0;
+}
+
+/*
+ * 遍历所有的hooks
+ */
+void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal)
+{
+ HOOK_TRAVERSAL_ARGS stageArgs;
+
+ BEGET_CHECK(traversal != NULL, return);
+
+ hookMgr = getHookMgr(hookMgr, 0);
+ BEGET_CHECK(hookMgr != NULL, return);
+
+ // Prepare common args
+ stageArgs.traversalCookie = traversalCookie;
+ stageArgs.traversal = traversal;
+ OH_ListTraversal(&(hookMgr->stages), (void *)(&stageArgs), hookStageTraversal, 0);
+}
+
+/*
+ * 获取指定stage中hooks的个数
+ */
+int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage)
+{
+ HOOK_STAGE *stageItem;
+
+ hookMgr = getHookMgr(hookMgr, 0);
+ BEGET_CHECK(hookMgr != NULL, return 0);
+
+ // Get HOOK_STAGE list
+ stageItem = getHookStage(hookMgr, stage, false);
+ BEGET_CHECK(stageItem != NULL, return 0);
+
+ return OH_ListGetCnt(&(stageItem->hooks));
+}
+
+/*
+ * 获取指定stage中hooks的个数
+ */
+int HookMgrGetStagesCnt(HOOK_MGR *hookMgr)
+{
+ hookMgr = getHookMgr(hookMgr, 0);
+ BEGET_CHECK(hookMgr != NULL, return 0);
+
+ return OH_ListGetCnt(&(hookMgr->stages));
+}
diff --git a/interfaces/innerkits/include/beget_ext.h b/interfaces/innerkits/include/beget_ext.h
new file mode 100644
index 0000000000000000000000000000000000000000..e85a757055c4cf1238ca5ac17aa40ef4312cff55
--- /dev/null
+++ b/interfaces/innerkits/include/beget_ext.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BEGET_EXT_API_H
+#define BEGET_EXT_API_H
+#include
+#include
+#include
+#ifdef __LITEOS_M__
+#include "hilog_lite/hiview_log.h"
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define INIT_DEBUG_LEVEL "persist.init.debug.loglevel"
+
+#ifndef INIT_LOG_PATH
+#define INIT_LOG_PATH STARTUP_INIT_UT_PATH"/data/init_agent/"
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+ #define INIT_PUBLIC_API __attribute__((visibility ("default")))
+ #define INIT_INNER_API __attribute__((visibility ("default")))
+ #define INIT_LOCAL_API __attribute__((visibility("hidden")))
+#else
+ #define INIT_PUBLIC_API
+ #define INIT_INNER_API
+ #define INIT_LOCAL_API
+#endif
+
+typedef enum InitLogLevel {
+ INIT_DEBUG = 0,
+ INIT_INFO,
+ INIT_WARN,
+ INIT_ERROR,
+ INIT_FATAL
+} InitLogLevel;
+
+typedef enum {
+ FSTAB_MOUNT_FAILED = 0,
+ SYS_PARAM_INIT_FAILED,
+ INIT_GOLBALY_KEY_FAILED,
+ CORE_PROCESS_FAILED
+} StartupInitErrno;
+
+#if (defined(STARTUP_INIT_TEST) || defined(APPSPAWN_TEST))
+#define STARTUP_FILE_NAME (__FILE_NAME__)
+#define STATIC
+#else
+#define STARTUP_FILE_NAME (strrchr((__FILE_NAME__), '/') ? strrchr((__FILE_NAME__), '/') + 1 : (__FILE_NAME__))
+#define STATIC static
+#endif
+
+#ifndef STARTUP_INIT_UT_PATH
+#ifdef STARTUP_INIT_TEST // ut
+#define STARTUP_INIT_UT_PATH "/data/init_ut"
+#else
+#define STARTUP_INIT_UT_PATH ""
+#endif
+#endif
+
+INIT_PUBLIC_API void StartupLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...);
+INIT_PUBLIC_API void SetInitLogLevel(InitLogLevel level);
+INIT_PUBLIC_API InitLogLevel GetInitLogLevel(void);
+
+#if defined(INIT_NO_LOG)
+#define STARTUP_LOGV(domain, tag, fmt, ...)
+#define STARTUP_LOGI(domain, tag, fmt, ...)
+#define STARTUP_LOGW(domain, tag, fmt, ...)
+#define STARTUP_LOGE(domain, tag, fmt, ...)
+#define STARTUP_LOGF(domain, tag, fmt, ...)
+#else
+#ifndef __LITEOS_M__
+#define STARTUP_LOGV(domain, tag, fmt, ...) \
+ StartupLog(INIT_DEBUG, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__)
+#define STARTUP_LOGI(domain, tag, fmt, ...) \
+ StartupLog(INIT_INFO, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__)
+#define STARTUP_LOGW(domain, tag, fmt, ...) \
+ StartupLog(INIT_WARN, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__)
+#define STARTUP_LOGE(domain, tag, fmt, ...) \
+ StartupLog(INIT_ERROR, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__)
+#define STARTUP_LOGF(domain, tag, fmt, ...) \
+ StartupLog(INIT_FATAL, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__)
+#else
+#define STARTUP_LOGV(domain, tag, fmt, ...) \
+ HILOG_DEBUG(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__)
+#define STARTUP_LOGI(domain, tag, fmt, ...) \
+ HILOG_INFO(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__)
+#define STARTUP_LOGW(domain, tag, fmt, ...) \
+ HILOG_WARN(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__)
+#define STARTUP_LOGE(domain, tag, fmt, ...) \
+ HILOG_ERROR(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__)
+#define STARTUP_LOGF(domain, tag, fmt, ...) \
+ HILOG_FATAL(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__)
+#endif
+#endif
+
+#define BASE_DOMAIN 0xD002C00
+#ifndef BEGET_DOMAIN
+#define BEGET_DOMAIN (BASE_DOMAIN + 0xb)
+#endif
+#define BEGET_LABEL "BEGET"
+#define BEGET_LOGI(fmt, ...) STARTUP_LOGI(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__)
+#define BEGET_LOGE(fmt, ...) STARTUP_LOGE(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__)
+#define BEGET_LOGV(fmt, ...) STARTUP_LOGV(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__)
+#define BEGET_LOGW(fmt, ...) STARTUP_LOGW(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__)
+
+#define InitLogPrint(outFileName, logLevel, kLevel, fmt, ...) \
+ StartupLog(logLevel, BEGET_DOMAIN, kLevel, fmt, ##__VA_ARGS__)
+
+#define BEGET_ERROR_CHECK(ret, statement, format, ...) \
+ if (!(ret)) { \
+ BEGET_LOGE(format, ##__VA_ARGS__); \
+ statement; \
+ } \
+
+#define BEGET_INFO_CHECK(ret, statement, format, ...) \
+ if (!(ret)) { \
+ BEGET_LOGI(format, ##__VA_ARGS__); \
+ statement; \
+ } \
+
+#define BEGET_WARNING_CHECK(ret, statement, format, ...) \
+ if (!(ret)) { \
+ BEGET_LOGW(format, ##__VA_ARGS__); \
+ statement; \
+ } \
+
+#define BEGET_CHECK(ret, statement) \
+ if (!(ret)) { \
+ statement; \
+ } \
+
+#define BEGET_CHECK_RETURN_VALUE(ret, result) \
+ do { \
+ if (!(ret)) { \
+ return result; \
+ } \
+ } while (0)
+
+#define BEGET_CHECK_ONLY_RETURN(ret) \
+ do { \
+ if (!(ret)) { \
+ return; \
+ } \
+ } while (0)
+
+#define BEGET_CHECK_ONLY_ELOG(ret, format, ...) \
+ do { \
+ if (!(ret)) { \
+ BEGET_LOGE(format, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/services/param/cmd/param_get.c b/interfaces/innerkits/include/fd_holder.h
similarity index 31%
rename from services/param/cmd/param_get.c
rename to interfaces/innerkits/include/fd_holder.h
index 1435dab09c2f2f1b263f9d30fd99537e0577323f..c979fe3b550185468f3941f452ac2738635c1501 100644
--- a/services/param/cmd/param_get.c
+++ b/interfaces/innerkits/include/fd_holder.h
@@ -1,59 +1,39 @@
-/*
-* 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 "sys_param.h"
-
-#define HELP_PARAM "--help"
-#define BUFFER_SIZE 256
-
-static void ProcessParam(ParamHandle handle, void* cookie)
-{
- if (cookie == NULL) {
- printf("ProcessParam cookie is NULL\n");
- return;
- }
- SystemGetParameterName(handle, (char*)cookie, BUFFER_SIZE);
- u_int32_t size = BUFFER_SIZE;
- SystemGetParameterValue(handle, ((char*)cookie) + BUFFER_SIZE, &size);
- printf("\t%s = %s \n", (char*)cookie, ((char*)cookie) + BUFFER_SIZE);
-}
-
-int main(int argc, char* argv[])
-{
- if (argc == 1) { // 显示所有的记录
- char value[BUFFER_SIZE + BUFFER_SIZE] = {0};
- SystemTraversalParameter(ProcessParam, (void*)value);
- return 0;
- }
- if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) { // 显示帮助
- printf("usage: getparam NAME VALUE\n");
- return 0;
- }
- if (argc != 2) {
- printf("usage: getparam NAME VALUE\n");
- return 0;
- }
- char value[BUFFER_SIZE] = {0};
- u_int32_t size = BUFFER_SIZE;
- int ret = SystemGetParameter(argv[1], value, &size);
- if (ret == 0) {
- printf("%s \n", value);
- } else {
- printf("getparam %s %s fail\n", argv[1], value);
- }
-
-}
+/*
+* 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 BASE_STARTUP_INITLITE_FD_HOLDER_H
+#define BASE_STARTUP_INITLITE_FD_HOLDER_H
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// fds stored in allocated memory, do not forget to release the memory when not use anymore
+int *ServiceGetFd(const char *serviceName, size_t *fdCount);
+
+// Let init poll the fd for service
+// This function will not take responsibility to close these fds
+// Caller need to handle them.
+int ServiceSaveFdWithPoll(const char *serviceName, int *fds, int fdCount);
+
+// Init only save the fd for service
+// This function will not take responsibility to close these fds
+// Caller need to handle them.
+int ServiceSaveFd(const char *serviceName, int *fds, int fdCount);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BASE_STARTUP_INITLITE_FD_HOLDER_H
diff --git a/interfaces/innerkits/include/fs_manager/erofs_super_block.h b/interfaces/innerkits/include/fs_manager/erofs_super_block.h
new file mode 100644
index 0000000000000000000000000000000000000000..16798ad5f63e9adadf938a332efc74898ef06610
--- /dev/null
+++ b/interfaces/innerkits/include/fs_manager/erofs_super_block.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024-2024 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 EROFS_H
+#define EROFS_H
+
+#include
+
+#define EROFS_SUPER_MAGIC 0xE0F5E1E2
+#define EROFS_SUPER_BLOCK_START_POSITION 1024
+
+struct erofs_super_block {
+ __le32 magic;
+ __le32 checksum;
+ __le32 feature_compat;
+ __u8 blkszbits;
+ __u8 reserved;
+
+ __le16 root_nid;
+ __le64 inos;
+
+ __le64 build_time;
+ __le32 build_time_nsec;
+ __le32 blocks;
+ __le32 meta_blkaddr;
+ __le32 xattr_blkaddr;
+ __u8 uuid[16];
+ __u8 volume_name[16];
+ __le32 feature_incompat;
+ __u8 reserved2[44];
+} __attribute((packed)); /* 128 byte */
+
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/fs_manager/ext4_super_block.h b/interfaces/innerkits/include/fs_manager/ext4_super_block.h
new file mode 100644
index 0000000000000000000000000000000000000000..3305052d5b1c5ee7ec8e10f3fdfa5048a5dc6991
--- /dev/null
+++ b/interfaces/innerkits/include/fs_manager/ext4_super_block.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2024-2024 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 EXT4_H
+#define EXT4_H
+
+#include
+
+#define EXT4_SUPER_MAGIC 0xEF53
+#define EXT4_SUPER_BLOCK_START_POSITION 0x400
+#define BLOCK_SIZE_UNIT 4096
+
+typedef struct ext4_super_block {
+__le32 s_inodes_count;
+__le32 s_blocks_count_lo;
+__le32 s_r_blocks_count_lo;
+__le32 s_free_blocks_count_lo;
+__le32 s_free_inodes_count;
+__le32 s_first_data_block;
+__le32 s_log_block_size;
+__le32 s_log_cluster_size;
+__le32 s_blocks_per_group;
+__le32 s_clusters_per_group;
+__le32 s_inodes_per_group;
+__le32 s_mtime;
+__le32 s_wtime;
+__le16 s_mnt_count;
+__le16 s_max_mnt_count;
+__le16 s_magic;
+__le16 s_state;
+__le16 s_errors;
+__le16 s_minor_rev_level;
+__le32 s_lastcheck;
+__le32 s_checkinterval;
+__le32 s_creator_os;
+__le32 s_rev_level;
+__le16 s_def_resuid;
+__le16 s_def_resgid;
+
+__le32 s_first_ino;
+__le16 s_inode_size;
+__le16 s_block_group_nr;
+__le32 s_feature_compat;
+__le32 s_feature_incompat;
+__le32 s_feature_ro_compat;
+__u8 s_uuid[16];
+char s_volume_name[16];
+char s_last_mounted[64];
+__le32 s_algorithm_usage_bitmap;
+
+__u8 s_prealloc_blocks;
+__u8 s_prealloc_dir_blocks;
+__le16 s_reserved_gdt_blocks;
+
+__u8 s_journal_uuid[16];
+__le32 s_journal_inum;
+__le32 s_journal_dev;
+__le32 s_last_orphan;
+__le32 s_hash_seed[4];
+__u8 s_def_hash_version;
+__u8 s_jnl_backup_type;
+__le16 s_desc_size;
+__le32 s_default_mount_opts;
+__le32 s_first_meta_bg;
+__le32 s_mkfs_time;
+__le32 s_jnl_blocks[17];
+
+__le32 s_blocks_count_hi;
+__le32 s_r_blocks_count_hi;
+__le32 s_free_blocks_count_hi;
+__le16 s_min_extra_isize;
+__le16 s_want_extra_isize;
+__le32 s_flags;
+__le16 s_raid_stride;
+__le16 s_mmp_interval;
+__le64 s_mmp_block;
+__le32 s_raid_stripe_width;
+__u8 s_log_groups_per_flex;
+__u8 s_checksum_type;
+__le16 s_reserved_pad;
+__le64 s_kbytes_written;
+__le32 s_snapshot_inum;
+__le32 s_snapshot_id;
+__le64 s_snapshot_r_blocks_count;
+__le32 s_snapshot_list;
+__le32 s_error_count;
+__le32 s_first_error_time;
+__le32 s_first_error_ino;
+__le64 s_first_error_block;
+__u8 s_first_error_func[32];
+__le32 s_first_error_line;
+__le32 s_last_error_time;
+__le32 s_last_error_ino;
+__le32 s_last_error_line;
+__le64 s_last_error_block;
+__u8 s_last_error_func[32];
+__u8 s_mount_opts[64];
+__le32 s_usr_quota_inum;
+__le32 s_grp_quota_inum;
+__le32 s_overhead_blocks;
+__le32 s_backup_bgs[2];
+__u8 s_encrypt_algos[4];
+__u8 s_encrypt_pw_salt[16];
+__le32 s_lpf_ino;
+__le32 s_prj_quota_inum;
+__le32 s_checksum_seed;
+__le32 s_reserved[98];
+__le32 s_checksum;
+} ext4_super_block; /* 1024 byte */
+
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/fs_manager/fs_manager.h b/interfaces/innerkits/include/fs_manager/fs_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..de7d021bb7c64f6dacad18ef21d9ec08ea9d3be5
--- /dev/null
+++ b/interfaces/innerkits/include/fs_manager/fs_manager.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STARTUP_FS_MANAGER_H
+#define STARTUP_FS_MANAGER_H
+
+#include
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+/* Fs manager flags definition */
+#define FS_MANAGER_CHECK 0x00000001
+#define FS_MANAGER_WAIT 0x00000002
+#define FS_MANAGER_REQUIRED 0x00000004
+#define FS_MANAGER_NOFAIL 0x00000008
+#define FS_MANAGER_HVB 0x00000010
+#define FS_MANAGER_PROJQUOTA 0x00000020
+#define FS_MANAGER_CASEFOLD 0x00000040
+#define FS_MANAGER_COMPRESSION 0x00000080
+#define FS_MANAGER_DEDUP 0x00000100
+#define FS_MANAGER_FORMATTABLE 0x00000200
+#define NAME_SIZE 32
+#define MAX_SLOT 2
+
+#define VALID_FS_MANAGER_FLAGS (FS_MANAGER_CHECK | FS_MANAGER_WAIT | FS_MANAGER_REQUIRED)
+#define FS_MANAGER_FLAGS_ENABLED(fsMgrFlags, flag) (((fsMgrFlags) & FS_MANAGER_##flag) != 0)
+
+#define FM_MANAGER_CHECK_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), CHECK)
+#define FM_MANAGER_WAIT_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), WAIT)
+#define FM_MANAGER_REQUIRED_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), REQUIRED)
+#define FM_MANAGER_NOFAIL_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), NOFAIL)
+#define FM_MANAGER_FORMATTABLE_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), FORMATTABLE)
+
+typedef enum MountStatus {
+ MOUNT_ERROR = -1,
+ MOUNT_UMOUNTED = 0,
+ MOUNT_MOUNTED = 1,
+} MountStatus;
+
+typedef struct FstabItem {
+ char *deviceName; // Block device name
+ char *mountPoint; // Mount point
+ char *fsType; // File system type
+ char *mountOptions; // File system mount options. readonly, rw, remount etc.
+ unsigned int fsManagerFlags; // flags defined by fs manager.
+ struct FstabItem *next;
+} FstabItem;
+
+typedef struct {
+ struct FstabItem *head;
+ struct FstabItem *tail;
+} Fstab;
+
+typedef enum SlotFlag {
+ UNBOOT = 0,
+ ACTIVE = 1,
+} SlotFlag;
+
+typedef struct SlotInfo {
+ int slotName;
+ char *slotSuffix;
+ SlotFlag slotFlag;
+ unsigned int retryCount;
+ unsigned int reserved;
+} SlotInfo;
+
+Fstab* LoadFstabFromCommandLine(void);
+int GetBootSlots(void);
+int GetCurrentSlot(void);
+void ReleaseFstab(Fstab *fstab);
+Fstab *ReadFstabFromFile(const char *file, bool procMounts);
+FstabItem *FindFstabItemForPath(Fstab fstab, const char *path);
+FstabItem* FindFstabItemForMountPoint(Fstab fstab, const char *mp);
+int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator);
+
+int GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char *deviceName, int nameLen);
+int GetBlockDeviceByName(const char *deviceName, const Fstab *fstab, char* miscDev, size_t size);
+bool IsSupportedFilesystem(const char *fsType);
+int DoFormat(const char *devPath, const char *fsType);
+int MountOneItem(FstabItem *item);
+MountStatus GetMountStatusForMountPoint(const char *mp);
+int MountAllWithFstabFile(const char *fstabFile, bool required);
+int MountAllWithFstab(const Fstab *fstab, bool required);
+int UmountAllWithFstabFile(const char *file);
+int MountOneWithFstabFile(const char *fstabFile, const char *devName, bool required);
+int FsManagerDmRemoveDevice(const char *devName);
+unsigned long GetMountFlags(char *mountFlag, char *fsSpecificFlags, size_t fsSpecificFlagSize,
+ const char *mountPoint);
+
+int GetBlockDevicePath(const char *partName, char *path, size_t size);
+
+// Get fscrypt policy if exist
+int LoadFscryptPolicy(char *buf, size_t size);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // STARTUP_FS_MANAGER_H
diff --git a/interfaces/innerkits/include/hookmgr.h b/interfaces/innerkits/include/hookmgr.h
new file mode 100755
index 0000000000000000000000000000000000000000..c752272cd07922a59c37609c2ed81ebab768318e
--- /dev/null
+++ b/interfaces/innerkits/include/hookmgr.h
@@ -0,0 +1,231 @@
+/*
+ * 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 OHOS_HOOK_MANAGER_H__
+#define OHOS_HOOK_MANAGER_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+/**
+ * @brief A Hook is a means of executing custom code (function) for existing running code.
+ *
+ * For a running process, it may consists of several stages.
+ * HookManager can help to add hooks to different stages with different priorities.
+ * The relationships for HookManager, HookStage and HookItem are shown as below:
+ *
+ * | ̄ ̄ ̄ ̄ ̄ ̄|
+ * | HookMgr |
+ * |__________|
+ * |
+ * | |▔▔▔▔▔▔▔▔▔▔▔| |▔▔▔▔▔▔▔▔▔▔▔|
+ * └--->| HookStage |--->| HookStage | ...
+ * |___________| |___________|
+ * |
+ * | |▔▔▔▔▔▔▔▔▔▔| |▔▔▔▔▔▔▔▔▔▔|
+ * └--->| HookItem |--->| HookItem | ...
+ * |__________| |__________|
+ *
+ * Usage example:
+ *
+ * For an existing module with several stages as below:
+ * ExistingStage1(...);
+ * ExistingStage2(...);
+ * ExistingStage3(...);
+ * We can add hooks capability to it as below:
+ * HookMgrExecute(hookMgr, PRE_STAGE1, ...);
+ * ExistingStage1(...);
+ * HookMgrExecute(hookMgr, PRE_STAGE2, ...);
+ * ExistingStage2(...);
+ * HookMgrExecute(hookMgr, PRE_STAGE3, ...);
+ * ExistingStage3(...);
+ * HookMgrExecute(hookMgr, POST_STAGE3, ...);
+ *
+ * For extending modules, we can add hooks without changing the existing module as below:
+ * int sampleHook() {
+ * ...
+ * }
+ * HookMgrAdd(hookMgr, PRE_STAGE1, priority, sampleHook);
+ */
+
+/* Forward declaration for HookManager */
+typedef struct tagHOOK_MGR HOOK_MGR;
+
+/* Forward declaration for HOOK_INFO */
+typedef struct tagHOOK_INFO HOOK_INFO;
+
+/**
+ * @brief Hook function prototype
+ *
+ * @param hookInfo hook information
+ * @param executionContext input arguments for running the hook execution context
+ * @return return 0 if succeed; other values if failed.
+ */
+typedef int (*OhosHook)(const HOOK_INFO *hookInfo, void *executionContext);
+
+struct tagHOOK_INFO {
+ int stage; /* hook stage */
+ int prio; /* hook priority */
+ OhosHook hook; /* hook function */
+ void *hookCookie; /* hook function cookie, for current hook only */
+};
+
+/**
+ * @brief Add a hook function
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param stage hook stage
+ * @param prio hook priority
+ * @param hook hook function pointer
+ * @return return 0 if succeed; other values if failed.
+ */
+int HookMgrAdd(HOOK_MGR *hookMgr, int stage, int prio, OhosHook hook);
+
+/**
+ * @brief Add a hook function with full hook information
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param hookInfo full hook information
+ * @return return 0 if succeed; other values if failed.
+ */
+int HookMgrAddEx(HOOK_MGR *hookMgr, const HOOK_INFO *hookInfo);
+
+/**
+ * @brief Delete hook function
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param stage hook stage
+ * @param hook hook function pointer
+ * If hook is NULL, it will delete all hooks in the stage
+ * @return None
+ */
+void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook);
+
+/**
+ * @brief preHook function prototype for HookMgrExecute each hook
+ *
+ * @param hookInfo HOOK_INFO for the each hook.
+ * @param executionContext input arguments for running the hook execution context.
+ * @return None
+ */
+typedef void (*OhosHookPreExecution)(const HOOK_INFO *hookInfo, void *executionContext);
+
+/**
+ * @brief postHook function prototype for HookMgrExecute each hook
+ *
+ * @param hookInfo HOOK_INFO for the each hook.
+ * @param executionContext input arguments for running the hook execution context.
+ * @param executionRetVal return value for running the hook.
+ * @return None
+ */
+typedef void (*OhosHookPostExecution)(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal);
+
+/* Executing hooks in descending priority order */
+#define HOOK_EXEC_REVERSE_ORDER 0x01
+/* Stop executing hooks when error returned for each hook */
+#define HOOK_EXEC_EXIT_WHEN_ERROR 0x02
+
+/**
+ * @brief Extra execution arguments for HookMgrExecute
+ */
+typedef struct tagHOOK_EXEC_OPTIONS {
+ /* Executing flags */
+ int flags;
+ /* preHook for before executing each hook */
+ OhosHookPreExecution preHook;
+ /* postHook for before executing each hook */
+ OhosHookPostExecution postHook;
+} HOOK_EXEC_OPTIONS;
+
+/**
+ * @brief Executing each hooks in specified stages
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param stage hook stage
+ * @param extraArgs HOOK_EXEC_ARGS for executing each hook.
+ * @return return 0 if succeed; other values if failed.
+ */
+int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *extraArgs);
+
+/**
+ * @brief Create a HookManager handle
+ *
+ * @param name HookManager name.
+ * @return return HookManager handle; NULL if failed.
+ */
+HOOK_MGR *HookMgrCreate(const char *name);
+
+/**
+ * @brief Destroy HookManager
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @return None.
+ */
+void HookMgrDestroy(HOOK_MGR *hookMgr);
+
+/**
+ * @brief Hook traversal function prototype
+ *
+ * @param hookInfo HOOK_INFO for traversing each hook.
+ * @return None
+ */
+typedef void (*OhosHookTraversal)(const HOOK_INFO *hookInfo, void *traversalCookie);
+
+/**
+ * @brief Traversing all hooks in the HookManager
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param traversalCookie traversal cookie.
+ * @param traversal traversal function.
+ * @return None.
+ */
+void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal);
+
+/**
+ * @brief Get number of hooks in specified stage
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param stage hook stage.
+ * @return number of hooks, return 0 if none
+ */
+int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage);
+
+/**
+ * @brief Get number of stages in the HookManager
+ *
+ * @param hookMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @return number of stages, return 0 if none
+ */
+int HookMgrGetStagesCnt(HOOK_MGR *hookMgr);
+
+#define HOOK_OK = 0
+#define ERR_NO_HOOK_STAGE (-1000)
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/include/init_error.h b/interfaces/innerkits/include/init_error.h
new file mode 100644
index 0000000000000000000000000000000000000000..5eb8bbc7f15ead6a5339386963875e5f9ef77aee
--- /dev/null
+++ b/interfaces/innerkits/include/init_error.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INIT_ERROR_H
+#define INIT_ERROR_H
+
+#include "beget_ext.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+/* Expand this list if necessary. */
+#define INIT_ERRNO_MAP(XX) \
+ XX(EPARAMETER, "Invalid parameter") \
+ XX(EFORMAT, "Format string fail") \
+ XX(ECFG, "cfg error") \
+ XX(EPATH, "Invalid path") \
+ XX(EFORK, "Fork fail") \
+ XX(ESANDBOX, "Create sandbox fail") \
+ XX(EACCESSTOKEN, "Set access token fail") \
+ XX(ESOCKET, "Create socket fail") \
+ XX(EFILE, "Create file fail") \
+ XX(ECONSOLE, "Open console fail") \
+ XX(EHOLDER, "Publish holder fail") \
+ XX(EBINDCORE, "Bind core fail") \
+ XX(EKEEPCAP, "Set keep capability fail") \
+ XX(EGIDSET, "Set gid fail") \
+ XX(ESECCOMP, "Set SECCOMP fail") \
+ XX(EUIDSET, "Set uid fail") \
+ XX(ECAP, "Set capability fail") \
+ XX(EWRITEPID, "Write pid fail") \
+ XX(ECONTENT, "Set sub content fail") \
+ XX(EPRIORITY, "Set priority fail") \
+ XX(EEXEC_CONTENT, "Set exec content fail") \
+ XX(EEXEC, "Exec fail")
+
+typedef enum {
+ INIT_OK,
+#define XX(code, _) INIT_ ## code,
+ INIT_ERRNO_MAP(XX)
+#undef XX
+} InitErrno;
+
+struct InitErrMap {
+ int code;
+ const char *info;
+} ;
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif // INIT_UTILS_H
diff --git a/interfaces/innerkits/include/init_file.h b/interfaces/innerkits/include/init_file.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4ca848f41d055415a49f7a173f0f3315d4ce799
--- /dev/null
+++ b/interfaces/innerkits/include/init_file.h
@@ -0,0 +1,34 @@
+/*
+ * 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 INIT_FILE_API_H
+#define INIT_FILE_API_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define OHOS_FILE_ENV_PREFIX "OHOS_FILE_"
+
+int GetControlFile(const char *name);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/include/init_hashmap.h b/interfaces/innerkits/include/init_hashmap.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b016b4bcbf19f632fe8b729baa09d02d9988ef9
--- /dev/null
+++ b/interfaces/innerkits/include/init_hashmap.h
@@ -0,0 +1,69 @@
+/*
+ * 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 INIT_HASH_MAP_
+#define INIT_HASH_MAP_
+#include
+#include
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define HASH_TAB_BUCKET_MAX 1024
+#define HASH_TAB_BUCKET_MIN 16
+
+typedef struct HashNode_ {
+ struct HashNode_ *next;
+} HashNode;
+
+#define HASHMAP_ENTRY(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
+#define HASHMAPInitNode(node) (node)->next = NULL
+
+typedef int (*HashNodeCompare)(const HashNode *node1, const HashNode *node2);
+typedef int (*HashKeyCompare)(const HashNode *node1, const void *key);
+typedef int (*HashNodeFunction)(const HashNode *node);
+typedef int (*HashKeyFunction)(const void *key);
+typedef void (*HashNodeOnFree)(const HashNode *node, void *context);
+
+typedef struct {
+ HashNodeCompare nodeCompare;
+ HashKeyCompare keyCompare;
+ HashNodeFunction nodeHash;
+ HashKeyFunction keyHash;
+ HashNodeOnFree nodeFree;
+ int maxBucket;
+} HashInfo;
+
+typedef void *HashMapHandle;
+
+int OH_HashMapIsEmpty(HashMapHandle handle);
+int32_t OH_HashMapCreate(HashMapHandle *handle, const HashInfo *info);
+void OH_HashMapDestory(HashMapHandle handle, void *context);
+int32_t OH_HashMapAdd(HashMapHandle handle, HashNode *hashNode);
+void OH_HashMapRemove(HashMapHandle handle, const void *key);
+HashNode *OH_HashMapGet(HashMapHandle handle, const void *key);
+HashNode *OH_HashMapFind(HashMapHandle handle,
+ int hashCode, const void *key, HashKeyCompare keyCompare);
+void OH_HashMapTraverse(HashMapHandle handle, void (*hashNodeTraverse)(const HashNode *node, const void *context),
+ const void *context);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/init_reboot.h b/interfaces/innerkits/include/init_reboot.h
old mode 100755
new mode 100644
index 61034d9d8e4260d824806cbe6166e5c7248694d2..8157e5759de8aedce904ea2d28b7e5e11124ef8e
--- a/interfaces/innerkits/include/init_reboot.h
+++ b/interfaces/innerkits/include/init_reboot.h
@@ -16,7 +16,43 @@
#ifndef INIT_REBOOT_API_H
#define INIT_REBOOT_API_H
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define STARTUP_DEVICE_CTL "startup.device.ctl"
+#define DEVICE_CMD_STOP "stop"
+#define DEVICE_CMD_SUSPEND "suspend"
+#define DEVICE_CMD_RESUME "resume"
+#define DEVICE_CMD_FREEZE "freeze"
+#define DEVICE_CMD_RESTORE "restore"
+
+/**
+ * @brief reboot system
+ *
+ * @param option format is: mode[:info]
+ * mode : command sub key, example: updater, shutdown ...
+ * info : extend info
+ * @return int
+ */
int DoReboot(const char *cmdContent);
+/**
+ * @brief reboot system
+ *
+ * @param mode command sub key, example: updater, shutdown ...
+ * @param option extend info
+ *
+ * @return int
+ */
+int DoRebootExt(const char *mode, const char *option);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
#endif
+#endif
diff --git a/interfaces/innerkits/include/init_socket.h b/interfaces/innerkits/include/init_socket.h
old mode 100755
new mode 100644
index 420264d147bf965ee58dc44f2b2a07dd856af2a8..786774858b28dfbfa54312f23bd6e3ffb930cfd9
--- a/interfaces/innerkits/include/init_socket.h
+++ b/interfaces/innerkits/include/init_socket.h
@@ -18,7 +18,16 @@
#define OHOS_SOCKET_DIR "/dev/unix/socket"
#define OHOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_"
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
// parameter is service name
int GetControlSocket(const char *name);
-
-#endif
\ No newline at end of file
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/include/init_utils.h b/interfaces/innerkits/include/init_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce6449630e7ba047d1484def83dfcd793bbbf045
--- /dev/null
+++ b/interfaces/innerkits/include/init_utils.h
@@ -0,0 +1,213 @@
+/*
+ * 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 INIT_UTILS_H
+#define INIT_UTILS_H
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "beget_ext.h"
+
+#ifndef STARTUP_INIT_TEST
+#ifndef INIT_STATIC
+#define INIT_STATIC static
+#endif
+#else
+#ifndef INIT_STATIC
+#define INIT_STATIC
+#endif
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+typedef struct {
+ char *name;
+ int value;
+} InitArgInfo;
+
+#define BASE_MS_UNIT 1000
+#define MAX_INT_LEN 20
+#define HEX_BASE 16
+#define BINARY_BASE 2
+#define OCTAL_BASE 8
+#define DECIMAL_BASE 10
+#define WAIT_MAX_SECOND 5
+#define MAX_BUFFER_LEN 256
+#define CMDLINE_VALUE_LEN_MAX 512
+#define STDERR_HANDLE 2
+#define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0]))
+#define BOOT_CMD_LINE STARTUP_INIT_UT_PATH"/proc/cmdline"
+
+#define FIRST_VALUE "First_Value" // 取第一个匹配值
+#define LAST_VALUE "Last_Value" // 取最后一个匹配值
+#define EMPTY_VALUE "EMPTY_VALUE" // 不取任何一个
+
+uid_t DecodeUid(const char *name);
+gid_t DecodeGid(const char *name);
+char *ReadFileToBuf(const char *configFile);
+int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length);
+char *ReadFileData(const char *fileName);
+
+typedef struct INIT_TIMING_STAT {
+ struct timespec startTime;
+ struct timespec endTime;
+} INIT_TIMING_STAT;
+
+typedef struct NameValuePair {
+ const char *name;
+ const char *nameEnd;
+ const char *value;
+ const char *valueEnd;
+} NAME_VALUE_PAIR;
+int IterateNameValuePairs(const char *src, void (*iterator)(const NAME_VALUE_PAIR *nv, void *context), void *context);
+
+int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum);
+long long InitDiffTime(INIT_TIMING_STAT *stat);
+void WaitForFile(const char *source, unsigned int maxSecond);
+size_t WriteAll(int fd, const char *buffer, size_t size);
+char *GetRealPath(const char *source);
+int StringToInt(const char *str, int defaultValue);
+int StringToUint(const char *name, unsigned int *value);
+int MakeDirRecursive(const char *dir, mode_t mode);
+void CheckAndCreateDir(const char *fileName);
+int CheckAndCreatFile(const char *file, mode_t mode);
+int MakeDir(const char *dir, mode_t mode);
+int ReadFileInDir(const char *dirPath, const char *includeExt,
+ int (*processFile)(const char *fileName, void *context), void *context);
+char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount);
+void FreeStringVector(char **vector, int count);
+int InUpdaterMode(void);
+int InRescueMode(void);
+int StringReplaceChr(char *strl, char oldChr, char newChr);
+
+int OpenConsole(void);
+int OpenKmsg(void);
+void TrimTail(char *str, char c);
+char *TrimHead(char *str, char c);
+
+INIT_LOCAL_API uint32_t IntervalTime(struct timespec *startTime, struct timespec *endTime);
+
+INIT_LOCAL_API int StringToULL(const char *str, unsigned long long int *out);
+INIT_LOCAL_API int StringToLL(const char *str, long long int *out);
+void CloseStdio(void);
+
+int GetServiceGroupIdByPid(pid_t pid, gid_t *gids, uint32_t gidSize);
+int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen);
+
+/**
+ * @brief Get param value from /proc/cmdline by exact match
+ *
+ * @param paramName the name of param
+ * @param value the array to receive the value of paramName
+ * @param valueLen the length of value
+ * @param conflictStrategy the strategy of conflicts, here are some options available
+ * FIRST_VALUE: select the first value
+ * LAST_VALUE: select the last value
+ * EMPTY_VALUE: return empty value
+ * "A
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+/**
+ * @brief Double linked list structure is show as below:
+ *
+ * | ̄ ̄ ̄ ̄ ̄|-----------------------------------------------|
+ * |->| head | |
+ * | |________|<-------------------------------------------| |
+ * | | | |
+ * | └-next->|▔▔▔▔▔▔|-next->|▔▔▔▔▔▔|-next->|▔▔▔▔▔▔|-next--| |
+ * └------prev-| node |<-prev-| node |<-prev-| node |<-prev----|
+ * |------| |------| |------|
+ * | extra| | extra| | extra|
+ * |______| |______| |______|
+ *
+ * Usage Example:
+ * 1. Define structure for each item in the list
+ * typedef struct tagTEST_LIST_ITEM {
+ * ListNode node;
+ * int value;
+ * } TEST_LIST_ITEM;
+ *
+ * 2. Define a list and init list by OH_ListAddTail
+ * ListNode testList;
+ * c(&testList);
+ *
+ * 3. Define a list item instance
+ * TEST_LIST_ITEM item;
+ * item.value = 0;
+ *
+ * 4. Add list item to list
+ * OH_ListAddTail(&testList, (ListNode *)(&item));
+ *
+ * 5. Advanced usage: add with order
+ * // Ordering compare function
+ * static int TestListItemCompareProc(ListNode *node, ListNode *newNode)
+ * {
+ * TEST_LIST_ITEM *left = (TEST_LIST_ITEM *)node;
+ * TEST_LIST_ITEM *right = (TEST_LIST_ITEM *)newNode;
+ * return left->value - right->value;
+ * }
+ * OH_ListAddWithOrder(&testList, (ListNode *)(&item))
+ */
+
+/**
+ * @brief Double linked list node
+ */
+typedef struct ListNode {
+ struct ListNode *next;
+ struct ListNode *prev;
+} ListNode, ListHead;
+
+#define ListEmpty(node) ((node).next == &(node) && (node).prev == &(node))
+#define ListEntry(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
+#define ForEachListEntry(list, node) for (node = (list)->next; node != (list); node = node->next)
+
+/**
+ * @brief Initialize a double-linked list head
+ *
+ * All other list API should be initialized by this function.\n
+ *
+ * @param head list head, make sure head is valid pointer
+ * @return None
+ */
+void OH_ListInit(struct ListNode *list);
+
+/**
+ * @brief Add a node to the end of the list
+ *
+ * @param head list head, make sure head is valid pointer
+ * @param item new node to be added
+ * @return None
+ */
+void OH_ListAddTail(struct ListNode *list, struct ListNode *item);
+
+/**
+ * @brief Remove a node from the list
+ *
+ * @param item the node to be removed from the list.
+ * This function does not free any memory within item.
+ * @return None
+ */
+void OH_ListRemove(struct ListNode *item);
+
+/**
+ * @brief ListNode comparison function prototype
+ *
+ * @param node ListNode to be compared.
+ * @param newNode new ListNode to be compared.
+ * @return
+ * <0 if node < newNode
+ * =0 if node = newNode
+ * >0 if Node > newNode
+ */
+typedef int (*ListCompareProc)(ListNode *node, ListNode *newNode);
+
+/**
+ * @brief Add a node to the list with order
+ *
+ * @param head list head, make sure head is valid pointer
+ * @param item new node to be added
+ * @param compareProc comparison function for adding node
+ * if it is ascending order, this function should return an integer less than,
+ * equal to, or greater than zero if the first argument is considered to be
+ * respectively less than, equal to, or greater than the second.
+ * @return None
+ */
+void OH_ListAddWithOrder(struct ListNode *head, struct ListNode *item, ListCompareProc compareProc);
+
+/**
+ * @brief ListNode traversing and find function prototype
+ *
+ * @param node ListNode to be compared.
+ * @param data value for traversing
+ * @return
+ * return 0 if node value equals data for OH_ListFind
+ */
+typedef int (*ListTraversalProc)(ListNode *node, void *data);
+
+/**
+ * @brief Find a node by traversing the list
+ *
+ * @param head list head, make sure head is valid pointer.
+ * @param data comparing data.
+ * @param compareProc comparing function, return 0 if matched.
+ * @return the found node; return NULL if none is found.
+ */
+ListNode *OH_ListFind(const ListNode *head, void *data, ListTraversalProc compareProc);
+
+/* Traversing from end to start */
+#define TRAVERSE_REVERSE_ORDER 0x1
+/* Stop traversing when error returned */
+#define TRAVERSE_STOP_WHEN_ERROR 0x2
+
+/**
+ * @brief Traversal the list with specified function
+ *
+ * @param head list head, make sure head is valid pointer.
+ * @param cookie optional traversing data.
+ * @param traversalProc comparing function, return 0 if matched.
+ * @param flags optional traversing flags:
+ * TRAVERSE_REVERSE_ORDER: traversing from last node to first node;
+ * default behaviour is from first node to last node
+ * TRAVERSE_STOP_WHEN_ERROR: stop traversing if traversalProc return non-zero
+ * default behaviour will ignore traversalProc return values
+ * @return return -1 for invalid input arguments.
+ * when TRAVERSE_STOP_WHEN_ERROR is specified, it will return errors from traversalProc
+ */
+int OH_ListTraversal(ListNode *head, void *data, ListTraversalProc traversalProc, unsigned int flags);
+
+/**
+ * @brief ListNode destroy function prototype
+ *
+ * @param node ListNode to be destroyed.
+ * @return None
+ */
+typedef void (*ListDestroyProc)(ListNode *node);
+
+/**
+ * @brief Find a node by traversing the list
+ *
+ * @param head list head, make sure head is valid pointer.
+ * @param destroyProc destroy function; if NULL, it will free each node by default.
+ * @return None
+ */
+void OH_ListRemoveAll(ListNode *head, ListDestroyProc destroyProc);
+
+/**
+ * @brief Get list count
+ *
+ * @param head list head, make sure head is valid pointer.
+ * @return the count of nodes in the list; return 0 if error
+ */
+int OH_ListGetCnt(const ListNode *head);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // BASE_STARTUP_INITLITE_LIST_H
diff --git a/interfaces/innerkits/include/loop_event.h b/interfaces/innerkits/include/loop_event.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd67675024682ee3b6b45135a67afc4d821f12d8
--- /dev/null
+++ b/interfaces/innerkits/include/loop_event.h
@@ -0,0 +1,241 @@
+/*
+ * 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 LOOP_EVENT_H
+#define LOOP_EVENT_H
+#include
+#include
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+// 配置
+#define LOOP_EVENT_USE_EPOLL 1
+#define LOOP_DEFAULT_BUFFER (1024 * 5)
+#define LOOP_MAX_BUFFER (1024 * 64)
+
+#define LOOP_MAX_CLIENT 1024
+#define LOOP_MAX_SOCKET 1024
+#define DEFAULT_TIMEOUT 1000
+
+typedef enum {
+ EVENT_READ = (0x0001),
+ EVENT_WRITE = (0x0002),
+ EVENT_ERROR = (0x0004),
+ EVENT_FREE = (0x0008),
+ EVENT_TIMEOUT = (0x0010),
+ EVENT_SIGNAL = (0x0020),
+} EventOper;
+
+typedef enum {
+ LE_SUCCESS = 0,
+ LE_FAILURE = 10000,
+ LE_INVALID_PARAM,
+ LE_NO_MEMORY,
+ LE_DIS_CONNECTED,
+ LE_INVALID_TASK
+} LE_STATUS;
+
+typedef struct {
+ uint32_t flags;
+} LoopBase;
+
+typedef LoopBase *LoopHandle;
+typedef LoopBase *TaskHandle;
+typedef LoopBase *TimerHandle;
+typedef LoopBase *SignalHandle;
+typedef LoopBase *WatcherHandle;
+typedef void *BufferHandle;
+
+LoopHandle LE_GetDefaultLoop(void);
+LE_STATUS LE_CreateLoop(LoopHandle *loopHandle);
+void LE_RunLoop(const LoopHandle loopHandle);
+void LE_CloseLoop(const LoopHandle loopHandle);
+void LE_StopLoop(const LoopHandle loopHandle);
+void LE_CloseTask(const LoopHandle loopHandle, const TaskHandle taskHandle);
+
+/**
+ * 申请一个buffer,用于消息的发送和接收
+ */
+BufferHandle LE_CreateBuffer(const LoopHandle loopHandle, uint32_t bufferSize);
+void LE_FreeBuffer(const LoopHandle loopHandle, const TaskHandle taskHandle, const BufferHandle handle);
+uint8_t *LE_GetBufferInfo(const BufferHandle handle, uint32_t *dataSize, uint32_t *buffSize);
+void *LE_GetUserData(const TaskHandle handle);
+int32_t LE_GetSendResult(const BufferHandle handle);
+
+typedef void (*LE_Close)(const TaskHandle taskHandle);
+typedef struct {
+ uint32_t flags;
+ LE_Close close;
+ uint16_t userDataSize;
+} LE_BaseInfo;
+
+/**
+ * 数据流服务,可以指定使用pipe或者普通的tcp
+ */
+#define TASK_STREAM 0x01
+#define TASK_TCP (0x01 << 8)
+#define TASK_PIPE (0x02 << 8)
+#define TASK_SERVER (0x01 << 16)
+#define TASK_CONNECT (0x02 << 16)
+#define TASK_TEST (0x01 << 24)
+#define TASK_PUBLIC (0x01 << 25) // If the socket can be publicly connected
+typedef void (*LE_DisConnectComplete)(const TaskHandle client);
+typedef void (*LE_ConnectComplete)(const TaskHandle client);
+typedef void (*LE_SendMessageComplete)(const TaskHandle taskHandle, BufferHandle handle);
+typedef void (*LE_RecvMessage)(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen);
+typedef int (*LE_IncommingConnect)(const LoopHandle loopHandle, const TaskHandle serverTask);
+typedef int (*LE_HandleRecvMsg)(const TaskHandle taskHandle, uint8_t* buffer, int bufferSize, int flags);
+typedef struct {
+ LE_BaseInfo baseInfo;
+ char *server;
+ int socketId;
+ LE_DisConnectComplete disConnectComplete;
+ LE_IncommingConnect incommingConnect;
+ LE_SendMessageComplete sendMessageComplete;
+ LE_RecvMessage recvMessage;
+} LE_StreamServerInfo;
+
+typedef struct {
+ LE_BaseInfo baseInfo;
+ char *server;
+ LE_DisConnectComplete disConnectComplete;
+ LE_ConnectComplete connectComplete;
+ LE_SendMessageComplete sendMessageComplete;
+ LE_RecvMessage recvMessage;
+ LE_HandleRecvMsg handleRecvMsg;
+} LE_StreamInfo;
+
+LE_STATUS LE_CreateStreamServer(const LoopHandle loopHandle,
+ TaskHandle *taskHandle, const LE_StreamServerInfo *info);
+LE_STATUS LE_CreateStreamClient(const LoopHandle loopHandle,
+ TaskHandle *taskHandle, const LE_StreamInfo *info);
+LE_STATUS LE_AcceptStreamClient(const LoopHandle loopHandle,
+ const TaskHandle serverTask, TaskHandle *taskHandle, const LE_StreamInfo *info);
+LE_STATUS LE_Send(const LoopHandle loopHandle,
+ const TaskHandle taskHandle, const BufferHandle handle, uint32_t buffLen);
+void LE_CloseStreamTask(const LoopHandle loopHandle, const TaskHandle taskHandle);
+int LE_GetSocketFd(const TaskHandle taskHandle);
+
+/**
+ * 异步事件服务
+ */
+typedef void (*LE_ProcessAsyncEvent)(const TaskHandle taskHandle,
+ uint64_t eventId, const uint8_t *buffer, uint32_t buffLen);
+#define TASK_EVENT 0x02
+#define TASK_ASYNC_EVENT (0x01 << 8)
+LE_STATUS LE_CreateAsyncTask(const LoopHandle loopHandle,
+ TaskHandle *taskHandle, LE_ProcessAsyncEvent processAsyncEvent);
+LE_STATUS LE_StartAsyncEvent(const LoopHandle loopHandle,
+ const TaskHandle taskHandle, uint64_t eventId, const uint8_t *data, uint32_t buffLen);
+void LE_StopAsyncTask(const LoopHandle loopHandle, const TaskHandle taskHandle);
+#ifdef STARTUP_INIT_TEST
+void LE_DoAsyncEvent(const LoopHandle loopHandle, const TaskHandle taskHandle);
+#endif
+
+/**
+ * 定时器处理
+ */
+#define TASK_TIME 0x04
+typedef void (*LE_ProcessTimer)(const TimerHandle taskHandle, void *context);
+
+LE_STATUS LE_CreateTimer(const LoopHandle loopHandle, TimerHandle *timer,
+ LE_ProcessTimer processTimer, void *context);
+LE_STATUS LE_StartTimer(const LoopHandle loopHandle,
+ const TimerHandle timer, uint64_t timeout, uint64_t repeat);
+void LE_StopTimer(const LoopHandle loopHandle, const TimerHandle timer);
+
+#define TASK_SIGNAL 0x08
+typedef void (*LE_ProcessSignal)(const struct signalfd_siginfo *siginfo);
+LE_STATUS LE_CreateSignalTask(const LoopHandle loopHandle,
+ SignalHandle *signalHandle, LE_ProcessSignal processSignal);
+LE_STATUS LE_AddSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal);
+LE_STATUS LE_RemoveSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal);
+void LE_CloseSignalTask(const LoopHandle loopHandle, const SignalHandle signalHandle);
+
+/**
+ * 监控句柄变化
+ */
+#define TASK_WATCHER 0x10
+#define WATCHER_ONCE 0x0100
+typedef void (*ProcessWatchEvent)(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context);
+typedef struct {
+ int fd;
+ uint32_t flags;
+ uint32_t events;
+ LE_Close close;
+ ProcessWatchEvent processEvent;
+} LE_WatchInfo;
+LE_STATUS LE_StartWatcher(const LoopHandle loopHandle,
+ WatcherHandle *watcherHandle, const LE_WatchInfo *info, const void *context);
+void LE_RemoveWatcher(const LoopHandle loopHandle, const WatcherHandle watcherHandle);
+
+/**
+ * Idle Processing:Idle handlers will be called for every loop
+ */
+
+/* Idle Handler */
+typedef void *IdleHandle;
+
+/**
+ * @brief Idle process function prototype
+ *
+ * @param taskHandle idle handler
+ * @param context idle function context
+ * @return None
+ */
+typedef void (*LE_ProcessIdle)(const IdleHandle taskHandle, void *context);
+
+/**
+ * @brief Add a new idle handler
+ *
+ * @param loopHandle the running loop this idle will be attached
+ * @param idle optional output parameter for the created idle handler
+ * @param processIdle the idle handler function
+ * @param context optional idle handler context
+ * @param repeat if the idle function will be repeated forevent (non zero) or once (zero)
+ * @return status code, 0 means succeed
+ */
+LE_STATUS LE_AddIdle(const LoopHandle loopHandle, IdleHandle *idle,
+ LE_ProcessIdle processIdle, void *context, int repeat);
+
+/**
+ * @brief Delete an idle handler
+ *
+ * @param idle idle handler
+ * @return None
+ */
+void LE_DelIdle(IdleHandle idle);
+
+/**
+ * @brief Execute an function once in the next loop
+ *
+ * @param loopHandle the running loop this idle will be attached
+ * @param idle the function to be executed
+ * @param context optional idle handler context
+ * @return status code, 0 means succeed
+ */
+int LE_DelayProc(const LoopHandle loopHandle, LE_ProcessIdle idle, void *context);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/modulemgr.h b/interfaces/innerkits/include/modulemgr.h
new file mode 100755
index 0000000000000000000000000000000000000000..2f2967c9f747f9bda62b3d84040f00c053268b08
--- /dev/null
+++ b/interfaces/innerkits/include/modulemgr.h
@@ -0,0 +1,163 @@
+/*
+ * 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 OHOS_MODULES_MANAGER_H__
+#define OHOS_MODULES_MANAGER_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+/**
+ * @brief Module constructor function
+ *
+ * For static modules, this code is executed before main().
+ * For dynamic modules, this code is executed when ModuleMgrInstall().
+ *
+ * Usage example:
+ * MODULE_CONSTRUCTOR(void)
+ * {
+ * ...
+ * }
+ */
+#define MODULE_CONSTRUCTOR(void) static void _init(void) __attribute__((constructor)); static void _init(void)
+
+/**
+ * @brief Module destructor function
+ *
+ * For static modules, this code will not be executed.
+ * For dynamic modules, this code is executed when ModuleMgrUninstall().
+ *
+ * Usage example:
+ * MODULE_DESTRUCTOR(void)
+ * {
+ * ...
+ * }
+ */
+#define MODULE_DESTRUCTOR(void) static void _destroy(void) __attribute__((destructor)); static void _destroy(void)
+
+// Forward declaration
+typedef struct tagMODULE_MGR MODULE_MGR;
+
+/**
+ * @brief Create dynamic module manager
+ *
+ * This dynamic module manager will manager modules
+ * in the directory: /system/lib/{name}/
+ * @param name module manager name
+ * @return return module manager handle if succeed; return NULL if failed.
+ */
+MODULE_MGR *ModuleMgrCreate(const char *name);
+
+/**
+ * @brief Destroy dynamic module manager
+ *
+ * It will uninstall all modules managed by this moduleMgr
+ * @param moduleMgr module manager handle
+ * @return None
+ */
+void ModuleMgrDestroy(MODULE_MGR *moduleMgr);
+
+/**
+ * @brief Install a module
+ *
+ * The final module path is: /system/lib/{moduleMgrPath}/{moduleName}.z.so
+ *
+ * @param moduleMgr module manager handle
+ * @param moduleName module name
+ * @param argc argument counts for installing
+ * @param argv arguments for installing, the last argument is NULL.
+ * @return module handle returned by dlopen
+ */
+int ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName,
+ int argc, const char *argv[]);
+
+/**
+ * @brief Module install arguments
+ */
+typedef struct {
+ int argc;
+ const char **argv;
+} MODULE_INSTALL_ARGS;
+
+/**
+ * @brief Get module install arguments
+ *
+ * This function is available only in MODULE_CONSTRUCTOR.
+ *
+ * @return install args if succeed; return NULL if failed.
+ */
+const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void);
+
+/**
+ * @brief Scan and install all modules in specified directory
+ *
+ * @param modulePath path for modules to be installed
+ * @return install args if succeed; return NULL if failed.
+ */
+MODULE_MGR *ModuleMgrScan(const char *modulePath);
+
+/**
+ * @brief Uninstall module
+ *
+ * @param moduleMgr module manager handle
+ * @param name module name. If name is NULL, it will uninstall all modules.
+ * @return install args if succeed; return NULL if failed.
+ */
+void ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name);
+
+/**
+ * @brief Get number of modules in module manager
+ *
+ * @param hookMgr module manager handle
+ * @return number of modules, return 0 if none
+ */
+int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr);
+
+/**
+ * @brief Module information for traversing modules
+ */
+typedef struct tagMODULE_INFO {
+ const char *name; /* module name */
+ void *handle; /* module handler */
+ void *cookie; /* hook execution cookie */
+} MODULE_INFO;
+
+/**
+ * @brief Module traversal function prototype
+ *
+ * @param moduleInfo MODULE_INFO for traversing each module.
+ * @return None
+ */
+typedef void (*OhosModuleTraversal)(const MODULE_INFO *moduleInfo);
+
+/**
+ * @brief Traversing all modules in the ModuleManager
+ *
+ * @param moduleMgr module manager handle
+ * @param cookie traversal cookie.
+ * @param traversal traversal function.
+ * @return None.
+ */
+void ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/include/param/init_param.h b/interfaces/innerkits/include/param/init_param.h
new file mode 100644
index 0000000000000000000000000000000000000000..de5fe5abf24471ff19559b91d154ac9d86334b43
--- /dev/null
+++ b/interfaces/innerkits/include/param/init_param.h
@@ -0,0 +1,222 @@
+/*
+ * 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 BASE_STARTUP_INIT_PARAM_H
+#define BASE_STARTUP_INIT_PARAM_H
+#include
+#include
+#ifdef PARAM_SUPPORT_TRIGGER
+#include "cJSON.h"
+#endif
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define DEFAULT_PARAM_WAIT_TIMEOUT 30 // 30s
+#define DEFAULT_PARAM_SET_TIMEOUT 10 // 10s
+
+#ifndef PARAM_NAME_LEN_MAX
+#define PARAM_CONST_VALUE_LEN_MAX 4096
+#define PARAM_VALUE_LEN_MAX 96
+#define PARAM_NAME_LEN_MAX 96
+#endif
+
+typedef enum {
+ PARAM_CODE_ERROR = -1,
+ PARAM_CODE_SUCCESS = 0,
+ PARAM_CODE_INVALID_PARAM = 100,
+ PARAM_CODE_INVALID_NAME,
+ PARAM_CODE_INVALID_VALUE,
+ PARAM_CODE_REACHED_MAX,
+ PARAM_CODE_NOT_SUPPORT,
+ PARAM_CODE_TIMEOUT,
+ PARAM_CODE_NOT_FOUND,
+ PARAM_CODE_READ_ONLY,
+ PARAM_CODE_IPC_ERROR,
+ PARAM_CODE_NODE_EXIST,
+ PARAM_WATCHER_CALLBACK_EXIST,
+ PARAM_WATCHER_GET_SERVICE_FAILED,
+ PARAM_CODE_MEMORY_MAP_FAILED,
+ PARAM_WORKSPACE_NOT_INIT,
+ PARAM_CODE_FAIL_CONNECT,
+ PARAM_CODE_MEMORY_NOT_ENOUGH,
+ PARAM_CODE_PERMISSION_DENIED,
+ PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH,
+ DAC_RESULT_INVALID_PARAM = 1000,
+ DAC_RESULT_FORBIDED,
+ SELINUX_RESULT_FORBIDED,
+ PARAM_CODE_MAX
+} PARAM_CODE;
+
+typedef enum {
+ EVENT_TRIGGER_PARAM,
+ EVENT_TRIGGER_BOOT,
+ EVENT_TRIGGER_PARAM_WAIT,
+ EVENT_TRIGGER_PARAM_WATCH
+} EventType;
+
+#define LOAD_PARAM_NORMAL 0x00
+#define LOAD_PARAM_ONLY_ADD 0x01
+#define LOAD_PARAM_PERSIST 0x02
+
+typedef uint32_t ParamHandle;
+
+/**
+ * Init 接口
+ * 初始化参数服务
+ *
+ */
+int InitParamService(void);
+void LoadSpecialParam(void);
+
+/**
+ * Init 接口
+ * 启动参数服务,在main启动的最后调用,阻赛当前线程
+ *
+ */
+int StartParamService(void);
+
+/**
+ * Init 接口
+ * 停止参数服务
+ *
+ */
+void StopParamService(void);
+
+/**
+ * Init 接口
+ * 加载默认的参数值
+ *
+ */
+int LoadDefaultParams(const char *fileName, uint32_t mode);
+
+/**
+ * Init 接口
+ * 加载持久化参数。
+ *
+ */
+int LoadPersistParams(void);
+
+/**
+ * Init 接口
+ * 加载加密目录下持久化参数。
+ *
+ */
+int LoadPrivatePersistParams(void);
+
+/**
+ * Init 接口
+ * 设置参数,主要用于其他进程使用,通过管道修改参数
+ *
+ */
+int SystemWriteParam(const char *name, const char *value);
+
+#ifdef PARAM_SUPPORT_TRIGGER
+/**
+ * 对外接口
+ * 触发一个trigger操作。
+ *
+ */
+void PostTrigger(EventType type, const char *content, uint32_t contentLen);
+
+/**
+ * 对外接口
+ * 解析trigger文件。
+ *
+ */
+int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName), void *context);
+
+/**
+ * 对外接口
+ * 按名字执行对应的trigger。
+ *
+ */
+void DoTriggerExec(const char *triggerName);
+void DoJobExecNow(const char *triggerName);
+
+/**
+ * 对外接口
+ * 按名字添加一个job,用于group支持。
+ *
+ */
+int AddCompleteJob(const char *name, const char *condition, const char *cmdContent);
+
+void RegisterBootStateChange(void (*bootStateChange)(int start, const char *));
+
+/**
+ * 对外接口
+ * dump 参数和trigger信息
+ *
+ */
+void SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...));
+#endif
+
+/**
+ * 对外接口
+ * 设置参数,主要用于其他进程使用,通过管道修改参数。
+ *
+ */
+int SystemSetParameter(const char *name, const char *value);
+
+/**
+ * 对外接口
+ * 保存共享内存中的所有持久化参数
+ *
+*/
+int SystemSaveParameters(void);
+
+/**
+ * Init 接口
+ * 查询参数。
+ *
+ */
+int SystemReadParam(const char *name, char *value, uint32_t *len);
+
+/**
+ * 对外接口
+ * 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。
+ * 如果 value == null,获取value的长度
+ * 否则value的大小认为是len
+ *
+ */
+#define SystemGetParameter SystemReadParam
+
+
+/**
+ * 外部接口
+ * 等待某个参数值被修改,阻塞直到参数值被修改或超时
+ *
+ */
+int SystemWaitParameter(const char *name, const char *value, int32_t timeout);
+
+typedef void (*ParameterChangePtr)(const char *key, const char *value, void *context);
+int SystemWatchParameter(const char *keyprefix, ParameterChangePtr change, void *context);
+
+int SystemCheckParamExist(const char *name);
+
+void SystemDumpParameters(int verbose, int index, int (*dump)(const char *fmt, ...));
+
+int WatchParamCheck(const char *keyprefix);
+
+void ResetParamSecurityLabel(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/param/sys_param.h b/interfaces/innerkits/include/param/sys_param.h
new file mode 100644
index 0000000000000000000000000000000000000000..07e4d347046e1a6081875f14f84703fcf89a9377
--- /dev/null
+++ b/interfaces/innerkits/include/param/sys_param.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_STARTUP_INIT_SYS_PARAM_H
+#define BASE_STARTUP_INIT_SYS_PARAM_H
+
+#include
+#ifndef __LITEOS_M__
+#include
+#endif
+
+#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
+#include
+#endif
+
+#ifndef __LITEOS_A__
+#if defined FUTEX_WAIT || defined FUTEX_WAKE
+#include
+#endif
+#endif
+
+#define MEMORY_ORDER_ACQUIRE 2
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#ifdef __LITEOS_M__
+#define ATOMIC_UINT32 uint32_t
+#define ATOMIC_LLONG long long
+#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) *(commitId)
+
+#else
+#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
+#define ATOMIC_UINT32 atomic_uint
+#define ATOMIC_LLONG atomic_llong
+#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order)
+
+#else
+#ifndef STARTUP_INIT_TEST
+#define ATOMIC_UINT32 uint32_t
+#define ATOMIC_LLONG int64_t
+static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order)
+{
+ return *((volatile ATOMIC_LLONG *)ptr);
+}
+#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order)
+#endif
+#endif
+#endif
+
+#ifdef __LITEOS_M__
+typedef struct {
+ uint32_t mutex;
+} ParamRWMutex;
+
+typedef struct {
+ uint32_t mutex;
+} ParamMutex;
+#endif
+
+// support mutex
+#ifndef STARTUP_INIT_TEST
+typedef struct {
+ pthread_rwlock_t rwlock;
+} ParamRWMutex;
+
+typedef struct {
+ pthread_mutex_t mutex;
+} ParamMutex;
+#endif
+
+#ifndef STARTUP_INIT_TEST
+typedef struct {
+ int shmid;
+} MemHandle;
+
+typedef struct {
+ ATOMIC_LLONG commitId;
+ ATOMIC_LLONG commitPersistId;
+ uint32_t trieNodeCount;
+ uint32_t paramNodeCount;
+ uint32_t securityNodeCount;
+ uint32_t currOffset;
+ uint32_t spaceSizeOffset;
+ uint32_t firstNode;
+ uint32_t dataSize;
+ char data[0];
+} ParamTrieHeader;
+
+typedef struct WorkSpace_ {
+ unsigned int flags;
+ MemHandle memHandle;
+ ParamTrieHeader *area;
+ ATOMIC_UINT32 rwSpaceLock;
+ uint32_t spaceSize;
+ uint32_t spaceIndex;
+ ParamRWMutex rwlock;
+ char fileName[0];
+} WorkSpace;
+
+typedef struct CachedParameter_ {
+ struct WorkSpace_ *workspace;
+ const char *(*cachedParameterCheck)(struct CachedParameter_ *param, int *changed);
+ long long spaceCommitId;
+ uint32_t dataCommitId;
+ uint32_t dataIndex;
+ uint32_t bufferLen;
+ uint32_t nameLen;
+ char *paramValue;
+ char data[0];
+} CachedParameter;
+
+typedef void *CachedHandle;
+#endif
+/**
+ * parameter client init
+ */
+void InitParameterClient(void);
+
+/**
+ * by name and default value,save parameter info in handle。
+ *
+ */
+CachedHandle CachedParameterCreate(const char *name, const char *defValue);
+
+/**
+ * destroy handle
+ *
+ */
+void CachedParameterDestroy(CachedHandle handle);
+
+/**
+ * if name exist,return value else return default value
+ *
+ */
+static inline const char *CachedParameterGet(CachedHandle handle)
+{
+ struct CachedParameter_ *param = (struct CachedParameter_ *)handle;
+ if (param == NULL) {
+ return NULL;
+ }
+
+ // no change, do not to find
+ long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(¶m->workspace->area->commitId, MEMORY_ORDER_ACQUIRE);
+ if (param->spaceCommitId == spaceCommitId) {
+ return param->paramValue;
+ }
+ param->spaceCommitId = spaceCommitId;
+ int changed = 0;
+ if (param->cachedParameterCheck == NULL) {
+ return param->paramValue;
+ }
+ return param->cachedParameterCheck(param, &changed);
+}
+
+static inline const char *CachedParameterGetChanged(CachedHandle handle, int *changed)
+{
+ struct CachedParameter_ *param = (struct CachedParameter_ *)handle;
+ if (param == NULL) {
+ return NULL;
+ }
+ // no change, do not to find
+ long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(¶m->workspace->area->commitId, MEMORY_ORDER_ACQUIRE);
+ if (param->spaceCommitId == spaceCommitId) {
+ return param->paramValue;
+ }
+ param->spaceCommitId = spaceCommitId;
+ if ((changed == NULL) || (param->cachedParameterCheck == NULL)) {
+ return param->paramValue;
+ }
+ return param->cachedParameterCheck(param, changed);
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/service_control.h b/interfaces/innerkits/include/service_control.h
new file mode 100644
index 0000000000000000000000000000000000000000..ada09cbf0cc6174ef4c94652f224f5b961883266
--- /dev/null
+++ b/interfaces/innerkits/include/service_control.h
@@ -0,0 +1,60 @@
+/*
+ * 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 BEGET_UTILS_API_H
+#define BEGET_UTILS_API_H
+
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define STARTUP_SERVICE_CTL "startup.service.ctl"
+
+typedef enum {
+ SERVICE_IDLE = 0, // service add
+ SERVICE_STARTING, // service start
+ SERVICE_STARTED, // 2 service ok running
+ SERVICE_READY, // 3 service ok running
+ SERVICE_STOPPING,
+ SERVICE_STOPPED, // 5
+ SERVICE_ERROR,
+ SERVICE_SUSPENDED,
+ SERVICE_FREEZED,
+ SERVICE_DISABLED,
+ SERVICE_CRITICAL
+} ServiceStatus;
+
+enum ServiceAction {
+ START = 0,
+ STOP = 1,
+ RESTART = 2,
+};
+
+int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc);
+int ServiceControl(const char *serviceName, int action);
+int ServiceWaitForStatus(const char *serviceName, ServiceStatus status, int waitTimeout);
+int ServiceSetReady(const char *serviceName);
+int StartServiceByTimer(const char *serviceName, uint64_t timeout);
+int StopServiceTimer(const char *serviceName);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/services/param/include/trigger_processor.h b/interfaces/innerkits/include/service_watcher.h
similarity index 64%
rename from services/param/include/trigger_processor.h
rename to interfaces/innerkits/include/service_watcher.h
index fc9a5e89e29a3dfcba0aae7918e1397b59a3e3b5..bae424886d50250bdbd366489af46016315f6504 100644
--- a/services/param/include/trigger_processor.h
+++ b/interfaces/innerkits/include/service_watcher.h
@@ -1,49 +1,44 @@
-/*
- * 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 BASE_STARTUP_EVENT_MANAGER_H
-#define BASE_STARTUP_EVENT_MANAGER_H
-
-#include
-
-#include "sys_param.h"
-#include "init_param.h"
-#include "trigger_manager.h"
-#include "uv.h"
-
-#ifdef __cplusplus
-#if __cplusplus
-extern "C" {
-#endif
-#endif
-
-typedef struct TriggerEvent {
- uv_work_t request;
- EventType type;
-} TriggerEvent;
-
-typedef struct {
- uv_work_t request;
- EventType type;
- u_int32_t contentSize;
- char content[0];
-} TriggerDataEvent;
-
-#ifdef __cplusplus
-#if __cplusplus
-}
-#endif
-#endif
-#endif
\ No newline at end of file
+/*
+ * 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 SERVICE_WATCH_API_H
+#define SERVICE_WATCH_API_H
+
+#include
+#include "init_param.h"
+#include "service_control.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define INVALID_PID 0
+
+typedef struct {
+ ServiceStatus status;
+ pid_t pid;
+} ServiceInfo;
+
+typedef void (*ServiceStatusChangePtr)(const char *key, const ServiceInfo *serviceInfo);
+int ServiceWatchForStatus(const char *serviceName, ServiceStatusChangePtr changeCallback);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/include/syspara/param_wrapper.h b/interfaces/innerkits/include/syspara/param_wrapper.h
new file mode 100755
index 0000000000000000000000000000000000000000..c9b197f00d0b65a8c5c9720c4e2bddafdd5e0c14
--- /dev/null
+++ b/interfaces/innerkits/include/syspara/param_wrapper.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PARAM_WRAPPER_H
+#define PARAM_WRAPPER_H
+
+#include
+
+namespace OHOS {
+namespace system {
+int GetStringParameter(const std::string &key, std::string &value, const std::string def = "");
+int GetIntParameter(const std::string &key, int def);
+}
+}
+
+#endif // PARAM_WRAPPER_H
diff --git a/interfaces/innerkits/include/syspara/parameter.h b/interfaces/innerkits/include/syspara/parameter.h
new file mode 100644
index 0000000000000000000000000000000000000000..c99f39f811e0fd1799c7ff6f514f95bf68a7f74c
--- /dev/null
+++ b/interfaces/innerkits/include/syspara/parameter.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STARTUP_SYSPARAM_PARAMETER_API_H
+#define STARTUP_SYSPARAM_PARAMETER_API_H
+#include
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+#define PARAM_CONST_VALUE_LEN_MAX 4096
+#define PARAM_VALUE_LEN_MAX 96
+#define PARAM_NAME_LEN_MAX 96
+#define OS_FULL_NAME_LEN 128
+#define VERSION_ID_MAX_LEN 256
+#define PARAM_BUFFER_MAX (0x01 << 16)
+
+static const char EMPTY_STR[] = { "" };
+
+/**
+ * @brief Obtains a system parameter matching the specified key.
+ *
+ * If no system parameter is found, the def parameter will be returned.\n
+ *
+ * @param key Indicates the key for the system parameter to query.
+ * The value can contain lowercase letters, digits, underscores (_), and dots (.).
+ * Its length cannot exceed 32 bytes (including the end-of-text character in the string).
+ * @param def Indicates the default value to return when no query result is found.
+ * This parameter is specified by the caller.
+ * @param value Indicates the data buffer that stores the query result.
+ * This parameter is applied for and released by the caller and can be used as an output parameter.
+ * @param len Indicates the length of the data in the buffer.
+ * @return Returns the number of bytes of the system parameter if the operation is successful;
+ * returns -9 if a parameter is incorrect; returns -1 in other scenarios.
+ * @since 1
+ * @version 1
+ */
+int GetParameter(const char *key, const char *def, char *value, uint32_t len);
+
+/**
+ * @brief Sets or updates a system parameter.
+ *
+ * You can use this function to set a system parameter that matches key as value.\n
+ *
+ * @param key Indicates the key for the parameter to set or update.
+ * The value can contain lowercase letters, digits, underscores (_), and dots (.).
+ * Its length cannot exceed 32 bytes (including the end-of-text character in the string).
+ * @param value Indicates the system parameter value.
+ * Its length cannot exceed 128 bytes (including the end-of-text character in the string).
+ * @return Returns 0 if the operation is successful;
+ * returns -9 if a parameter is incorrect; returns -1 in other scenarios.
+ * @since 1
+ * @version 1
+ */
+int SetParameter(const char *key, const char *value);
+
+/**
+ * @brief Wait for a system parameter with specified value.
+ *
+ * You can use this function to wait a system parameter that matches key as value.\n
+ *
+ * @param key Indicates the key for the parameter to wait.
+ * The value can contain lowercase letters, digits, underscores (_), and dots (.).
+ * Its length cannot exceed 96 bytes (including the end-of-text character in the string).
+ * @param value Indicates the system parameter value.
+ * Its length cannot exceed 96 bytes (including the end-of-text character in the string).
+ * value can use "*" to do arbitrary match.
+ * @param timeout Indicates the timeout value, in seconds.
+ * <=0 means wait for ever.
+ * >0 means wait for specified seconds
+ * @return Returns 0 if the operation is successful;
+ * returns -10 if timeout; returns -1 in other scenarios.
+ * @since 1.1
+ * @version 1.1
+ */
+int WaitParameter(const char *key, const char *value, int timeout);
+
+/**
+ * @brief Watch for system parameter values.
+ *
+ * You can use this function to watch system parameter values.\n
+ *
+ * @param keyPrefix Indicates the key prefix for the parameter to be watched.
+ * If keyPrefix is not a full name, "A.B." for example, it means to watch for all parameter started with "A.B.".
+ * @param callback Indicates value change callback.
+ * If callback is NULL, it means to cancel the watch.
+ * @return Returns 0 if the operation is successful;
+ * returns -1 in other scenarios.
+ * @since 1.1
+ * @version 1.1
+ */
+typedef void (*ParameterChgPtr)(const char *key, const char *value, void *context);
+int WatchParameter(const char *keyPrefix, ParameterChgPtr callback, void *context);
+
+/**
+ * @brief Remove parameter watcher.
+ *
+ * You can use this function to remove system parameter watcher.\n
+ *
+ * @param keyPrefix Indicates the key prefix for the parameter to be watched.
+ * If keyPrefix is not a full name, "A.B." for example, it means to watch for all parameter started with "A.B.".
+ * @param callback Indicates value change callback.
+ * If callback is NULL, it means to cancel the watch.
+ * @return Returns 0 if the operation is successful;
+ * returns -1 in other scenarios.
+ * @since 1.1
+ * @version 1.1
+ */
+int RemoveParameterWatcher(const char *keyPrefix, ParameterChgPtr callback, void *context);
+
+/**
+ * @brief Synchronize saving persistent parameters.
+ *
+ * You can use this function to save system parameter in shared memory immediately.\n
+ *
+ * @return Returns 0 if the operation is successful;
+ * returns -1 in other scenarios.
+ * @since 4.1
+ * @version 4.1
+*/
+int SaveParameters(void);
+const char *GetSecurityPatchTag(void);
+const char *GetOSFullName(void);
+const char *GetVersionId(void);
+const char *GetBuildRootHash(void);
+const char *GetOsReleaseType(void);
+int GetSdkApiVersion(void);
+
+const char *GetDeviceType(void);
+const char *GetProductModel(void);
+const char *GetProductModelAlias(void);
+const char *GetManufacture(void);
+const char *GetBrand(void);
+const char *GetMarketName(void);
+const char *GetProductSeries(void);
+const char *GetSoftwareModel(void);
+const char *GetHardwareModel(void);
+const char *GetHardwareProfile(void);
+const char *GetSerial(void);
+const char *GetAbiList(void);
+const char *GetDisplayVersion(void);
+const char *GetIncrementalVersion(void);
+const char *GetBootloaderVersion(void);
+const char *GetBuildType(void);
+const char *GetBuildUser(void);
+const char *GetBuildHost(void);
+const char *GetBuildTime(void);
+int GetFirstApiVersion(void);
+int GetDevUdid(char *udid, int size);
+
+const char *AclGetSerial(void);
+int AclGetDevUdid(char *udid, int size);
+
+/**
+ * @brief Obtains a system parameter matching the specified key.
+ *
+ * If no system parameter is found, return -1.\n
+ *
+ * @param key Indicates the key for the system parameter to find.
+ * @return Returns the index for parameter;
+ * returns handle if a parameter is correct; returns -1 in other scenarios.
+ * @since 1
+ * @version 1
+ */
+uint32_t FindParameter(const char *key);
+uint32_t GetParameterCommitId(uint32_t handle);
+int GetParameterName(uint32_t handle, char *key, uint32_t len);
+int GetParameterValue(uint32_t handle, char *value, uint32_t len);
+long long GetSystemCommitId(void);
+
+int32_t GetIntParameter(const char *key, int32_t def);
+uint32_t GetUintParameter(const char *key, uint32_t def);
+
+const char *GetDistributionOSName(void);
+const char *GetDistributionOSVersion(void);
+int GetDistributionOSApiVersion(void);
+const char *GetDistributionOSApiName(void);
+const char *GetDistributionOSReleaseType(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif // STARTUP_SYSPARAM_PARAMETER_API_H
diff --git a/interfaces/innerkits/include/syspara/parameters.h b/interfaces/innerkits/include/syspara/parameters.h
new file mode 100755
index 0000000000000000000000000000000000000000..9aa0a68011321355d7112d3ea2358eb89b969d06
--- /dev/null
+++ b/interfaces/innerkits/include/syspara/parameters.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PARAMETERS_H
+#define SYSTEM_PARAMETERS_H
+
+#include
+#include
+
+namespace OHOS {
+namespace system {
+/*
+ * Returns the current value of the system parameter `key`.
+ * If the parameter is empty or doesn't exist, `def` will be returned.
+ */
+std::string GetParameter(const std::string& key, const std::string& def);
+
+/*
+ * Returns true if the system parameter `key` has the value "1", "y", "yes", "on", or "true",
+ * false for "0", "n", "no", "off", or "false", or `def` otherwise.
+ */
+bool GetBoolParameter(const std::string& key, bool def);
+
+/*
+ * Returns the signed integer corresponding to the system parameter `key`.
+ * If the parameter is empty, doesn't exist, doesn't have an integer value, or is outside
+ * the optional bounds, returns `def`.
+ */
+template
+T GetIntParameter(const std::string& key, T def, T min = std::numeric_limits::min(),
+ T max = std::numeric_limits::max());
+
+/*
+ * Returns the unsigned integer corresponding to the system parameter `key`.
+ * If the parameter is empty, doesn't exist, doesn't have an integer value, or is outside
+ * the optional bound, returns `def`.
+ */
+template
+T GetUintParameter(const std::string& key, T def, T max = std::numeric_limits::max());
+
+/*
+ * Sets the system parameter `key` to `value`.
+ * Note that system parameter setting is inherently asynchronous so a return value of `true`
+ * isn't particularly meaningful, and immediately reading back the value won't necessarily
+ * tell you whether or not your call succeeded. A `false` return value definitely means failure.
+ */
+bool SetParameter(const std::string& key, const std::string& value);
+
+/*
+ * Obtains the device type of your product represented by a string.
+ */
+std::string GetDeviceType(void);
+} // namespace system
+} // namespace OHOS
+
+#endif // SYSTEM_PARAMETERS_H
\ No newline at end of file
diff --git a/interfaces/innerkits/include/syspara/sysparam_errno.h b/interfaces/innerkits/include/syspara/sysparam_errno.h
new file mode 100755
index 0000000000000000000000000000000000000000..54fd08ae3c0438ffde0234b384925d04b6f3cefd
--- /dev/null
+++ b/interfaces/innerkits/include/syspara/sysparam_errno.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OHOS_STARTUP_SYSPARAM_ERRNO_H
+#define OHOS_STARTUP_SYSPARAM_ERRNO_H
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+/* --------------------------------------------------------------------------------------------*
+ * Definition of error code. The error codes are applicable to both the application and kernel
+ * -------------------------------------------------------------------------------------------- */
+enum OHOSStartUpSysParamErrorCode {
+ EC_SUCCESS = 0, /* OK or No error */
+ EC_FAILURE = -1, /* Execution failed */
+ EC_INVALID = -9, /* Invalid argument */
+ EC_SYSTEM_ERR = -10, /* system error */
+
+ SYSPARAM_INVALID_INPUT = -401, /* Input parameter is missing or invalid */
+ SYSPARAM_NOT_FOUND = -14700101, /* System parameter can not be found. */
+ SYSPARAM_INVALID_VALUE = -14700102, /* System parameter value is invalid */
+ SYSPARAM_PERMISSION_DENIED = -14700103, /* System permission operation permission denied */
+ SYSPARAM_SYSTEM_ERROR = -14700104, /* System internal error including out of memory, deadlock etc. */
+ SYSPARAM_WAIT_TIMEOUT = -14700105, /* System wait parameter value change time out. */
+};
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+#endif // OHOS_STARTUP_SYSPARAM_ERRNO_H
diff --git a/interfaces/innerkits/include/syspara/sysversion.h b/interfaces/innerkits/include/syspara/sysversion.h
new file mode 100755
index 0000000000000000000000000000000000000000..c2153abf9447766de6fb65bfd1a8bae2db86915b
--- /dev/null
+++ b/interfaces/innerkits/include/syspara/sysversion.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STARTUP_SYSVERSION_API_H
+#define STARTUP_SYSVERSION_API_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+int GetMajorVersion(void);
+int GetSeniorVersion(void);
+int GetFeatureVersion(void);
+int GetBuildVersion(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif // STARTUP_SYSVERSION_API_H
diff --git a/interfaces/innerkits/include/systemcapability.h b/interfaces/innerkits/include/systemcapability.h
new file mode 100644
index 0000000000000000000000000000000000000000..b8d5fb0c86066cadb2329df1f50234180294722b
--- /dev/null
+++ b/interfaces/innerkits/include/systemcapability.h
@@ -0,0 +1,35 @@
+/*
+ * 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 INIT_SYSCAP_API_H
+#define INIT_SYSCAP_API_H
+
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+
+bool HasSystemCapability(const char *cap);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/include/token/token.h b/interfaces/innerkits/include/token/token.h
new file mode 100755
index 0000000000000000000000000000000000000000..152953611fe5d72c04c19a4466b042d7e6ff7c8e
--- /dev/null
+++ b/interfaces/innerkits/include/token/token.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2020 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 TOKEN_H
+#define TOKEN_H
+
+#include
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+/**
+ * @brief Read token value form device.
+ *
+ * @param token The token value, len The token len.
+ * @returns 0 if it succeeds and get the update area token,
+ * 1 if it succeeds and get the pre-made token,
+ * -1 if it fails, -2 if it no pre-made token.
+ */
+int ReadToken(char *token, unsigned int len);
+
+/**
+ * @brief Write token value to device.
+ *
+ * @param token The token value, len The token len.
+ * @returns 0 if it succeeds, -1 if it fails.
+ */
+int WriteToken(const char *token, unsigned int len);
+
+/**
+ * @brief Get AcKey value form device.
+ *
+ * @param acKey The acKey value, len The acKey len.
+ * @returns 0 if it succeeds, -1 if it fails.
+ */
+int GetAcKey(char *acKey, unsigned int len);
+
+/**
+ * @brief Get ProdId value form device.
+ *
+ * @param productId The productId value, len The productId len.
+ * @returns 0 if it succeeds, -1 if it fails.
+ */
+int GetProdId(char *productId, unsigned int len);
+
+/**
+ * @brief Get ProdKey value form device.
+ *
+ * @param productKey The productKey value, len The productKey len.
+ * @returns 0 if it succeeds, -1 if it fails.
+ */
+int GetProdKey(char *productKey, unsigned int len);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif // TOKEN_H
\ No newline at end of file
diff --git a/interfaces/innerkits/init_module_engine/BUILD.gn b/interfaces/innerkits/init_module_engine/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..da4f9db69cf4c7d93b4369ff34509f19f80ce720
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/BUILD.gn
@@ -0,0 +1,103 @@
+# 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.
+
+if (defined(ohos_lite)) {
+ group("libinit_module_engine") {
+ }
+} else {
+ import("//build/ohos.gni")
+ import("//build/ohos/native_stub/native_stub.gni")
+
+ #
+ # exported include directories
+ #
+ config("init_module_engine_exported_config") {
+ visibility = [ ":*" ]
+ visibility += [ "./../../../services/*" ]
+ include_dirs = [
+ "include/",
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/services/init/include",
+ "//base/startup/init/services/log",
+ ]
+ if (ohos_indep_compiler_enable) {
+ include_dirs +=
+ [ "//binarys/third_party/cJSON/innerapis/cjson_static/includes" ]
+ } else {
+ include_dirs += [ "//third_party/cJSON" ]
+ }
+ }
+
+ #
+ # innerkits for module development
+ #
+ ohos_native_stub_library("libinit_module_engine") {
+ cflags = [ "-fstack-protector-all" ]
+ output_extension = "so"
+ public_configs = [ ":init_module_engine_exported_config" ]
+ stub_description_file = "./stub/libinit.stub.json"
+ }
+
+ #
+ # For init linking,
+ # export symbols defined in this json files only
+ #
+ ohos_native_stub_versionscript("libinit_stub_versionscript") {
+ stub_description_file = "./stub/libinit.stub.json"
+ }
+
+ #
+ # Generate empty library with symlink name to satisfy init loading required libraries
+ #
+ ohos_native_stub_library("libinit_stub_empty") {
+ cflags = [ "-fstack-protector-all" ]
+ output_extension = "so"
+ stub_description_file = "./stub/libinit.stub.empty.json"
+ part_name = "init"
+ subsystem_name = "startup"
+ install_enable = true
+ install_images = [
+ "system",
+ "updater",
+ "ramdisk",
+ ]
+ symlink_target_name = [ "libinit_module_engine.so" ]
+ }
+
+ config("init_module_engine_sources_config") {
+ include_dirs = [
+ "//base/startup/init/interfaces/innerkits/init_module_engine/include",
+ "//base/startup/init/interfaces/innerkits/include",
+ "//base/startup/init/services/loopevent/include",
+ "//base/startup/init/services/log",
+ ]
+ }
+
+ ohos_source_set("init_module_engine_sources") {
+ sources = [ "init_modulemgr.c" ]
+ public_configs = [ ":init_module_engine_sources_config" ]
+ external_deps = [ "cJSON:cjson" ]
+ }
+}
+
+#
+# init module engine all modules
+#
+group("modulegroup") {
+ if (!defined(ohos_lite)) {
+ deps = [
+ ":libinit_module_engine",
+ ":libinit_stub_empty",
+ ]
+ }
+}
diff --git a/interfaces/innerkits/init_module_engine/include/bootstage.h b/interfaces/innerkits/init_module_engine/include/bootstage.h
new file mode 100755
index 0000000000000000000000000000000000000000..98ec2787713138e685e6d354a15e14ec1c16d0ef
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/include/bootstage.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_STARTUP_BOOTSTAGE_H
+#define BASE_STARTUP_BOOTSTAGE_H
+
+#include "hookmgr.h"
+#include "cJSON.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+enum INIT_BOOTSTAGE {
+ INIT_GLOBAL_INIT = 0,
+ INIT_FIRST_STAGE = 1,
+ INIT_MOUNT_STAGE = 3,
+ INIT_RESTORECON = 4,
+ INIT_POST_DATA_UNENCRYPT = 5,
+ INIT_PRE_PARAM_SERVICE = 10,
+ INIT_PRE_PARAM_LOAD = 20,
+ INIT_PARAM_LOAD_FILTER = 25,
+ INIT_PRE_CFG_LOAD = 30,
+ INIT_SERVICE_PARSE = 35,
+ INIT_POST_PERSIST_PARAM_LOAD = 40,
+ INIT_POST_CFG_LOAD = 50,
+ INIT_CMD_RECORD = 51,
+ INIT_REBOOT = 55,
+ INIT_SERVICE_CLEAR = 56,
+ INIT_SERVICE_DUMP = 57,
+ INIT_SERVICE_FORK_BEFORE = 58,
+ INIT_SERVICE_SET_PERMS_BEFORE = 59,
+ INIT_SERVICE_SET_PERMS = 60,
+ INIT_SERVICE_FORK_AFTER = 61,
+ INIT_SERVICE_BOOTEVENT = 62,
+ INIT_SERVICE_REAP = 65,
+ INIT_SHUT_DETECTOR = 66,
+ INIT_ALL_SERVICES_REAP = 67,
+ INIT_SERVICE_RESTART = 71,
+ INIT_JOB_PARSE = 70,
+ INIT_BOOT_COMPLETE = 100,
+};
+
+HOOK_MGR *GetBootStageHookMgr();
+
+__attribute__((always_inline)) inline int InitAddGlobalInitHook(int prio, OhosHook hook)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_GLOBAL_INIT, prio, hook);
+}
+
+__attribute__((always_inline)) inline int InitAddPreParamServiceHook(int prio, OhosHook hook)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, prio, hook);
+}
+
+__attribute__((always_inline)) inline int InitAddPreParamLoadHook(int prio, OhosHook hook)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, prio, hook);
+}
+
+/**
+ * @brief Parameter load filter context
+ */
+typedef struct tagPARAM_LOAD_FILTER_CTX {
+ const char *name; /* Parameter name */
+ const char *value; /* Parameter value */
+ int ignored; /* Ignore this parameter or not */
+} PARAM_LOAD_FILTER_CTX;
+
+/**
+ * @brief Parameter Load Hook function prototype
+ *
+ * @param hookInfo hook information
+ * @param filter filter information context
+ * @return return 0 if succeed; other values if failed.
+ */
+typedef int (*ParamLoadFilter)(const HOOK_INFO *hookInfo, PARAM_LOAD_FILTER_CTX *filter);
+
+__attribute__((always_inline)) inline int InitAddParamLoadFilterHook(int prio, ParamLoadFilter filter)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, prio, (OhosHook)filter);
+}
+
+__attribute__((always_inline)) inline int InitAddPreCfgLoadHook(int prio, OhosHook hook)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, prio, hook);
+}
+
+__attribute__((always_inline)) inline int InitAddPostCfgLoadHook(int prio, OhosHook hook)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, prio, hook);
+}
+
+__attribute__((always_inline)) inline int InitAddPostPersistParamLoadHook(int prio, OhosHook hook)
+{
+ return HookMgrAdd(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, prio, hook);
+}
+
+/**
+ * @brief service config parsing context information
+ */
+typedef struct tagSERVICE_PARSE_CTX {
+ const char *serviceName; /* Service name */
+ const cJSON *serviceNode; /* Service JSON node */
+} SERVICE_PARSE_CTX;
+
+/**
+ * @brief job config parsing context information
+ */
+typedef struct tagJOB_PARSE_CTX {
+ const char *jobName; /* job name */
+ const cJSON *jobNode; /* job JSON node */
+} JOB_PARSE_CTX;
+
+/**
+ * @brief service info
+ */
+typedef struct tagSERVICE_INFO_CTX {
+ const char *serviceName; /* Service name */
+ const char *reserved; /* reserved info */
+} SERVICE_INFO_CTX;
+
+/**
+ * @brief service info
+ */
+typedef struct tagSERVICE_BOOTEVENT_CTX {
+ const char *serviceName; /* Service name */
+ const char *reserved; /* reserved info */
+ int state; /* bootevent state */
+} SERVICE_BOOTEVENT_CTX;
+
+/**
+ * @brief service restart info
+ */
+typedef struct tagSERVICE_RESTART_CTX {
+ const char *serviceName; /* Service name */
+ const char *serviceNode; /* Service node */
+} SERVICE_RESTART_CTX;
+
+/**
+ * @brief init cmd info
+ */
+typedef struct InitCmdInfo {
+ const char *cmdName; /* cmd name */
+ const char *cmdContent; /* cmd content */
+ const char *reserved; /* reserved info */
+} INIT_CMD_INFO;
+
+/**
+ * @brief service config parse hook function prototype
+ *
+ * @param serviceParseCtx service config parsing context information
+ * @return None
+ */
+typedef void (*ServiceParseHook)(SERVICE_PARSE_CTX *serviceParseCtx);
+
+/**
+ * @brief job config parse hook function prototype
+ *
+ * @param JobParseHook job config parsing context information
+ * @return None
+ */
+typedef void (*JobParseHook)(JOB_PARSE_CTX *jobParseCtx);
+
+/**
+ * @brief service hook function prototype
+ *
+ * @param ServiceHook service info
+ * @return None
+ */
+typedef void (*ServiceHook)(SERVICE_INFO_CTX *serviceCtx);
+
+/**
+ * @brief service restart hook function prototype
+ *
+ * @param ServiceRestartHook service info
+ * @return None
+ */
+typedef void (*ServiceRestartHook) (SERVICE_RESTART_CTX *serviceRestartCtx);
+
+/**
+ * @brief Register a hook for service config parsing
+ *
+ * @param hook service config parsing hook
+ * in the hook, we can parse extra fields in the config file.
+ * @return return 0 if succeed; other values if failed.
+ */
+int InitAddServiceParseHook(ServiceParseHook hook);
+
+/**
+ * @brief service config parsing context information
+ */
+typedef struct tagReboot {
+ char *reason;
+} RebootHookCtx;
+
+/**
+ * @brief service config parse hook function prototype
+ *
+ * @param serviceParseCtx service config parsing context information
+ * @return None
+ */
+typedef void (*InitRebootHook)(RebootHookCtx *ctx);
+/**
+ * @brief Register a hook for reboot
+ *
+ * @param hook
+ *
+ * @return return 0 if succeed; other values if failed.
+ */
+int InitAddRebootHook(InitRebootHook hook);
+
+/**
+ * @brief Register a hook for job config parsing
+ *
+ * @param hook job config parsing hook
+ * in the hook, we can parse extra fields in the config file.
+ * @return return 0 if succeed; other values if failed.
+ */
+int InitAddJobParseHook(JobParseHook hook);
+
+/**
+ * @brief Register a hook for service
+ *
+ * @param hook service hook
+ * in the hook, we can get service.
+ * @param hookState init boot state
+ * @return return 0 if succeed; other values if failed.
+ */
+int InitAddServiceHook(ServiceHook hook, int hookState);
+
+/**
+ * @brief Register a hook for service restart
+ *
+ * @param hook service restart hook
+ * in the hook, we can get service.
+ * @return return 0 if succeed; other values if failed.
+ */
+int InitServiceRestartHook(ServiceRestartHook hook, int hookState);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/services/param/include/param_request.h b/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h
similarity index 47%
rename from services/param/include/param_request.h
rename to interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h
index d2ed318d6b17c3583b863d2e1f69ac48c2412ea7..89b1859573cb4c315ed4661980e8c56c9753ffb6 100644
--- a/services/param/include/param_request.h
+++ b/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-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,57 +12,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef STARTUP_INIT_CMD_EXECUTOR_H
+#define STARTUP_INIT_CMD_EXECUTOR_H
+#include
+#include
-#ifndef BASE_STARTUP_PARAM_REQUEST_H
-#define BASE_STARTUP_PARAM_REQUEST_H
+#include "list.h"
-#include
-#include "sys_param.h"
-#include "param_manager.h"
-
-#include "uv.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
-typedef enum RequestType {
- SET_PARAM,
- GET_PARAM,
-} RequestType;
-
typedef struct {
- ParamSecurityLabel securitylabel;
- RequestType type;
- int contentSize;
- char content[0];
-} RequestMsg;
+ ListNode cmdExecutor;
+ int cmdId;
+ unsigned char careContext;
+ char *name;
+} PluginCmd;
+typedef int (*CmdExecutor)(int id, const char *name, int argc, const char **argv);
typedef struct {
- RequestType type;
- int result;
- int contentSize;
- char content[0];
-} ResponseMsg;
+ ListNode node;
+ int id;
+ CmdExecutor execCmd;
+} PluginCmdExecutor;
-typedef struct {
- uv_loop_t *loop;
- uv_connect_t connect;
- uv_pipe_t handle;
- uv_write_t wr;
- int result;
- RequestMsg msg;
-} RequestNode;
+void PluginExecCmdByName(const char *name, const char *cmdContent);
+// only exec in current context
+int PluginExecCmd(const char *name, int argc, const char **argv);
-typedef struct {
- uv_write_t writer;
- ResponseMsg msg;
-} ResponseNode;
+int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd);
+
+int AddRebootCmdExecutor(const char *cmd, CmdExecutor executor);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/services/include/init_signal_handler.h b/interfaces/innerkits/init_module_engine/include/init_filesystems.h
old mode 100644
new mode 100755
similarity index 63%
rename from services/include/init_signal_handler.h
rename to interfaces/innerkits/init_module_engine/include/init_filesystems.h
index 433d4f99a696b8967a4aaa75447de37e18413aed..f79b7c37237a8ffc2d69294cb91fa8431477d9c0
--- a/services/include/init_signal_handler.h
+++ b/interfaces/innerkits/init_module_engine/include/init_filesystems.h
@@ -1,42 +1,36 @@
-/*
- * Copyright (c) 2020 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 BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H
-#define BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H
-
-#ifdef __LINUX__
-#include
-#include
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus
-extern "C" {
-#endif
-#endif
-
-void SignalInitModule();
-
-#ifdef __LINUX__
-void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem);
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus
-}
-#endif
-#endif
-
-#endif // BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef STARTUP_INIT_SUPPORTED_FILE_SYSTEMS_H
+#define STARTUP_INIT_SUPPORTED_FILE_SYSTEMS_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+typedef struct tagSUPPORTED_FILE_SYSTEM {
+ const char *fs_name;
+ int for_userdata;
+} SUPPORTED_FILE_SYSTEM;
+
+void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[]);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/init_module_engine/include/init_module_engine.h b/interfaces/innerkits/init_module_engine/include/init_module_engine.h
new file mode 100755
index 0000000000000000000000000000000000000000..8a1bd582f3a7e9e7bd3a6960055231e5267239a1
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/include/init_module_engine.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_STARTUP_INIT_PLUGIN_H
+#define BASE_STARTUP_INIT_PLUGIN_H
+#include
+#include
+#include
+#include "modulemgr.h"
+#include "bootstage.h"
+#include "init_modulemgr.h"
+#include "init_cmdexecutor.h"
+#include "init_running_hooks.h"
+#include "init_filesystems.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+int SystemWriteParam(const char *name, const char *value);
+
+int SystemReadParam(const char *name, char *value, unsigned int *len);
+
+int LoadParamsFile(const char *fileName, bool onlyAdd);
+
+typedef int (*CmdExecutor)(int id, const char *name, int argc, const char **argv);
+
+int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd);
+
+void RemoveCmdExecutor(const char *cmdName, int id);
+
+int DoJobNow(const char *jobName);
+
+int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif // BASE_STARTUP_INIT_PLUGIN_H
diff --git a/interfaces/innerkits/init_module_engine/include/init_modulemgr.h b/interfaces/innerkits/init_module_engine/include/init_modulemgr.h
new file mode 100755
index 0000000000000000000000000000000000000000..ee528857cbb1f3ba171afc3029f2d2026d621781
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/include/init_modulemgr.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_STARTUP_INIT_MODULEMGR_H
+#define BASE_STARTUP_INIT_MODULEMGR_H
+
+#include "modulemgr.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+int InitModuleMgrInstall(const char *moduleName);
+
+void InitModuleMgrUnInstall(const char *moduleName);
+
+void AutorunModuleMgrUnInstall(const char *moduleName);
+
+void InitModuleMgrDump(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/init_module_engine/include/init_running_hooks.h b/interfaces/innerkits/init_module_engine/include/init_running_hooks.h
new file mode 100755
index 0000000000000000000000000000000000000000..522d4e89094623e8753a41626809a70fc31ac7ee
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/include/init_running_hooks.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_STARTUP_BOOT_RUNNING_HOOKS_H
+#define BASE_STARTUP_BOOT_RUNNING_HOOKS_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+/**
+ * @brief Running hook stage definition for init
+ */
+/* Hook stage for setting parameters */
+#define INIT_PARAM_SET_HOOK_STAGE 0
+
+/**
+ * @brief parameter setting context information
+ */
+typedef struct tagPARAM_SET_CTX {
+ const char *name; /* Parameter name */
+ const char *value; /* Parameter value */
+
+ /* Skip setting parameter if true
+ * When setting parameters, parameter service will save the the value by default
+ * If set skipParamSet in the hook, parameter service will not save
+ */
+ int skipParamSet;
+} PARAM_SET_CTX;
+
+/**
+ * @brief set parameter hook function prototype
+ *
+ * @param paramSetCtx parameter setting context information
+ * @return None
+ */
+typedef void (*ParamSetHook)(PARAM_SET_CTX *paramSetCtx);
+
+/**
+ * @brief Register a hook for setting parameters
+ *
+ * @param hook parameter setting hook
+ * in the hook, we can match the parameters with special patterns to do extra controls.
+ * For example, ohos.ctl.start will control services besides the normal parameter saving.
+ * @return return 0 if succeed; other values if failed.
+ */
+int ParamSetHookAdd(ParamSetHook hook);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/interfaces/innerkits/init_module_engine/init_modulemgr.c b/interfaces/innerkits/init_module_engine/init_modulemgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..76b6af802db6254729fc13ab0e59c495ac710450
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/init_modulemgr.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2020-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 "init_log.h"
+#include "init_module_engine.h"
+#include "loop_event.h"
+
+static MODULE_MGR *defaultModuleMgr = NULL;
+static MODULE_MGR *autorunModuleMgr = NULL;
+
+int InitModuleMgrInstall(const char *moduleName)
+{
+ if (moduleName == NULL) {
+ return -1;
+ }
+
+ if (defaultModuleMgr == NULL) {
+ defaultModuleMgr = ModuleMgrCreate("init");
+ }
+ if (defaultModuleMgr == NULL) {
+ return -1;
+ }
+
+ return ModuleMgrInstall(defaultModuleMgr, moduleName, 0, NULL);
+}
+
+void InitModuleMgrUnInstall(const char *moduleName)
+{
+ ModuleMgrUninstall(defaultModuleMgr, moduleName);
+}
+
+static void DelayedUninstall(const IdleHandle taskHandle, void *context)
+{
+ const char *moduleName = (const char *)context;
+ if (moduleName == NULL) {
+ return;
+ }
+ ModuleMgrUninstall(autorunModuleMgr, moduleName);
+}
+
+void AutorunModuleMgrUnInstall(const char *moduleName)
+{
+ void *context = (void *)strdup(moduleName);
+ if (context == NULL) {
+ return;
+ }
+ LE_DelayProc(LE_GetDefaultLoop(), DelayedUninstall, context);
+}
+
+static void InitModuleDump(const MODULE_INFO *moduleInfo)
+{
+ printf("%s\n", moduleInfo->name);
+}
+
+void InitModuleMgrDump(void)
+{
+ if (defaultModuleMgr != NULL) {
+ ModuleMgrTraversal(defaultModuleMgr, NULL, InitModuleDump);
+ }
+
+ if (autorunModuleMgr != NULL) {
+ ModuleMgrTraversal(autorunModuleMgr, NULL, InitModuleDump);
+ }
+}
+
+static int ModuleMgrCmdInstall(int id, const char *name, int argc, const char **argv)
+{
+ INIT_ERROR_CHECK(argv != NULL && argc >= 1, return -1, "Invalid install parameter");
+ int ret;
+ if (defaultModuleMgr == NULL) {
+ defaultModuleMgr = ModuleMgrCreate("init");
+ }
+ ret = ModuleMgrInstall(defaultModuleMgr, argv[0], argc-1, argv+1);
+ INIT_ERROR_CHECK(ret == 0, return ret, "Install module %s fail errno %d", argv[0], ret);
+ return 0;
+}
+
+static int ModuleMgrCmdUninstall(int id, const char *name, int argc, const char **argv)
+{
+ INIT_ERROR_CHECK(argv != NULL && argc >= 1, return -1, "Invalid install parameter");
+ ModuleMgrUninstall(defaultModuleMgr, argv[0]);
+ return 0;
+}
+
+static int moduleMgrCommandsInit(const HOOK_INFO *info, void *cookie)
+{
+ // "ohos.servicectrl.install"
+ (void)AddCmdExecutor("install", ModuleMgrCmdInstall);
+ (void)AddCmdExecutor("uninstall", ModuleMgrCmdUninstall);
+ // read cfg and start static plugin
+ return 0;
+}
+
+static int loadAutorunModules(const HOOK_INFO *info, void *cookie)
+{
+ autorunModuleMgr = ModuleMgrScan("init/autorun");
+ INIT_LOGV("Load autorun modules return autorunModuleMgr");
+ return 0;
+}
+
+MODULE_CONSTRUCTOR(void)
+{
+ // Depends on parameter service
+ InitAddGlobalInitHook(0, loadAutorunModules);
+ InitAddPreCfgLoadHook(0, moduleMgrCommandsInit);
+}
diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.empty.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.empty.json
new file mode 100755
index 0000000000000000000000000000000000000000..0d4f101c7a37a4c875e6999bee1a287fdb733380
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.empty.json
@@ -0,0 +1,2 @@
+[
+]
diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json
new file mode 100644
index 0000000000000000000000000000000000000000..b51c09d9009ef4744aacf3beb9ae87f21d4fccc6
--- /dev/null
+++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json
@@ -0,0 +1,95 @@
+[
+ { "name": "SystemWriteParam" },
+ { "name": "SystemReadParam" },
+ { "name": "LoadParamsFile" },
+ { "name": "LoadPersistParams" },
+ { "name": "SplitString" },
+ { "name": "AddCmdExecutor" },
+ { "name": "GetServiceByName"},
+ { "name": "RemoveCmdExecutor" },
+ { "name": "HookMgrAdd" },
+ { "name": "HookMgrAddEx" },
+ { "name": "HookMgrDel" },
+ { "name": "GetBootStageHookMgr"},
+ { "name": "InitAddGlobalInitHook" },
+ { "name": "InitAddPreParamServiceHook" },
+ { "name": "InitAddPreParamLoadHook" },
+ { "name": "InitAddPreCfgLoadHook" },
+ { "name": "InitAddPostCfgLoadHook" },
+ { "name": "InitModuleMgrInstall" },
+ { "name": "InitModuleMgrUnInstall" },
+ { "name": "InitSetExtendedFileSystems" },
+ { "name": "AutorunModuleMgrUnInstall" },
+ { "name": "StartupLog" },
+ { "name": "DoJobNow" },
+ { "name": "GetServiceExtData" },
+ { "name": "UpdateMiscMessage" },
+ { "name": "AddRebootCmdExecutor" },
+ { "name": "GetBootEventList" },
+ { "name": "WaitForFile" },
+ { "name": "DoCmdByIndex" },
+ { "name": "GetMatchCmd" },
+ { "name": "AddCareContextCmdExecutor" },
+ { "name": "GetParameterFromCmdLine" },
+ { "name": "InitSubInitContext" },
+ { "name": "ExecReboot" },
+ { "name": "LE_AcceptStreamClient" },
+ { "name": "LE_AddSignal" },
+ { "name": "LE_CloseLoop" },
+ { "name": "LE_CloseSignalTask" },
+ { "name": "LE_CloseStreamTask" },
+ { "name": "LE_CloseTask" },
+ { "name": "LE_CreateAsyncTask" },
+ { "name": "LE_CreateBuffer" },
+ { "name": "LE_CreateLoop" },
+ { "name": "LE_CreateSignalTask" },
+ { "name": "LE_CreateStreamClient" },
+ { "name": "LE_CreateStreamServer" },
+ { "name": "LE_CreateTimer" },
+ { "name": "LE_FreeBuffer" },
+ { "name": "LE_GetBufferInfo" },
+ { "name": "LE_GetDefaultLoop" },
+ { "name": "LE_GetSendResult" },
+ { "name": "LE_GetSocketFd" },
+ { "name": "LE_GetUserData" },
+ { "name": "LE_RemoveSignal" },
+ { "name": "LE_RemoveWatcher" },
+ { "name": "LE_RunLoop" },
+ { "name": "LE_Send" },
+ { "name": "LE_StartAsyncEvent" },
+ { "name": "LE_StartTimer" },
+ { "name": "LE_StartWatcher" },
+ { "name": "LE_StopAsyncTask" },
+ { "name": "LE_StopLoop" },
+ { "name": "LE_StopTimer" },
+ { "name": "LE_AddIdle" },
+ { "name": "LE_DelIdle" },
+ { "name": "LE_DelayProc" },
+ { "name": "OH_ListAddTail" },
+ { "name": "OH_ListInit" },
+ { "name": "OH_ListRemove" },
+ { "name": "OH_ListGetCnt" },
+ { "name": "OH_ListAddWithOrder" },
+ { "name": "OH_ListFind" },
+ { "name": "OH_ListRemoveAll" },
+ { "name": "OH_ListTraversal" },
+ { "name": "OH_HashMapAdd" },
+ { "name": "OH_HashMapCreate" },
+ { "name": "OH_HashMapDestory" },
+ { "name": "OH_HashMapFind" },
+ { "name": "OH_HashMapGet" },
+ { "name": "OH_HashMapIsEmpty" },
+ { "name": "OH_HashMapRemove" },
+ { "name": "OH_HashMapTraverse" },
+ { "name": "InitAddServiceHook" },
+ { "name": "InitAddRebootHook" },
+ { "name": "InitAddServiceParseHook" },
+ { "name": "InitAddJobParseHook" },
+ { "name": "InitAddPostPersistParamLoadHook"},
+ { "name": "InitServiceRestartHook" },
+ { "name": "OH_StrArrayGetIndex" },
+ { "name": "OH_ExtendableStrArrayGetIndex" },
+ { "name": "OH_StrDictGet" },
+ { "name": "OH_ExtendableStrDictGet" },
+ { "name": "GetUptimeInMicroSeconds" }
+]
diff --git a/interfaces/innerkits/libbeget_proxy.versionscript b/interfaces/innerkits/libbeget_proxy.versionscript
new file mode 100644
index 0000000000000000000000000000000000000000..f35cd896b0e92c2e49e715eccfd26d16ef7d8ba4
--- /dev/null
+++ b/interfaces/innerkits/libbeget_proxy.versionscript
@@ -0,0 +1,24 @@
+# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+1.0 {
+ global:
+ AclGetDevUdid;
+ AclGetSerial;
+ ServiceWatchForStatus;
+ SystemWatchParameter;
+ WatchParameter;
+ RemoveParameterWatcher;
+ local:
+ *;
+};
diff --git a/interfaces/innerkits/libbegetutil.versionscript b/interfaces/innerkits/libbegetutil.versionscript
new file mode 100644
index 0000000000000000000000000000000000000000..a6762300ec8510b3f2b939742c06223f8197cdcc
--- /dev/null
+++ b/interfaces/innerkits/libbegetutil.versionscript
@@ -0,0 +1,161 @@
+# Copyright (c) 2023 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+1.0 {
+ global:
+ DecodeUid;
+ DecodeGid;
+ ResetParamSecurityLabel;
+ StartupLog;
+ ServiceGetFd;
+ ServiceSaveFd;
+ HookMgrAdd;
+ HookMgrAddEx;
+ HookMgrCreate;
+ HookMgrDel;
+ HookMgrDestroy;
+ HookMgrExecute;
+ HookMgrGetHooksCnt;
+ HookMgrGetStagesCnt;
+ HookMgrTraversal;
+ GetControlFile;
+ OH_HashMapAdd;
+ OH_HashMapCreate;
+ OH_HashMapDestory;
+ OH_HashMapFind;
+ OH_HashMapGet;
+ OH_HashMapIsEmpty;
+ OH_HashMapRemove;
+ OH_HashMapTraverse;
+ SystemReadParam;
+ SystemTraversalParameter;
+ GetSystemCommitId;
+ CachedParameterCreate;
+ CachedParameterGet;
+ CachedParameterGetChanged;
+ CachedParameterDestroy;
+ DoReboot;
+ DoRebootExt;
+ GetControlSocket;
+ OH_ListAddTail;
+ OH_ListAddWithOrder;
+ OH_ListFind;
+ OH_ListGetCnt;
+ OH_ListInit;
+ OH_ListRemove;
+ OH_ListRemoveAll;
+ OH_ListTraversal;
+ LE_AcceptStreamClient;
+ LE_AddSignal;
+ LE_CloseLoop;
+ LE_CloseSignalTask;
+ LE_CloseStreamTask;
+ LE_CloseTask;
+ LE_CreateAsyncTask;
+ LE_CreateBuffer;
+ LE_CreateLoop;
+ LE_CreateSignalTask;
+ LE_CreateStreamClient;
+ LE_CreateStreamServer;
+ LE_CreateTimer;
+ LE_FreeBuffer;
+ LE_GetBufferInfo;
+ LE_GetDefaultLoop;
+ LE_GetSendResult;
+ LE_GetSocketFd;
+ LE_GetUserData;
+ LE_RemoveSignal;
+ LE_RemoveWatcher;
+ LE_RunLoop;
+ LE_Send;
+ LE_StartAsyncEvent;
+ LE_StartTimer;
+ LE_StartWatcher;
+ LE_StopAsyncTask;
+ LE_StopLoop;
+ LE_StopTimer;
+ LE_AddIdle;
+ LE_DelIdle;
+ LE_DelayProc;
+ ModuleMgrCreate;
+ ModuleMgrDestroy;
+ ModuleMgrGetArgs;
+ ModuleMgrGetCnt;
+ ModuleMgrInstall;
+ ModuleMgrScan;
+ ModuleMgrTraversal;
+ ModuleMgrUninstall;
+ *GetStringParameter*;
+ FindParameter;
+ GetAbiList;
+ GetBootloaderVersion;
+ GetBrand;
+ GetBuildHost;
+ GetBuildRootHash;
+ GetBuildTime;
+ GetBuildType;
+ GetBuildUser;
+ GetDevUdid;
+ GetDisplayVersion;
+ GetFirstApiVersion;
+ GetHardwareModel;
+ GetHardwareProfile;
+ GetIncrementalVersion;
+ GetManufacture;
+ GetMarketName;
+ GetOSFullName;
+ GetOsReleaseType;
+ GetParameterCommitId;
+ GetParameterName;
+ GetParameterValue;
+ GetProductModel;
+ GetProductModelAlias;
+ GetProductSeries;
+ GetSdkApiVersion;
+ GetSecurityPatchTag;
+ GetSerial;
+ GetSoftwareModel;
+ GetVersionId;
+ WaitParameter;
+ *GetIntParameter*;
+ *GetDeviceType*;
+ *GetParameter*;
+ *GetUintParameter*;
+ *SetParameter*;
+ *GetBoolParameter*;
+ ServiceControl;
+ ServiceControlWithExtra;
+ ServiceSetReady;
+ ServiceWaitForStatus;
+ StartServiceByTimer;
+ StopServiceTimer;
+ HasSystemCapability;
+ GetBuildVersion;
+ GetFeatureVersion;
+ GetMajorVersion;
+ GetSeniorVersion;
+ OH_Ext*;
+ GetDistributionOSName;
+ GetDistributionOSVersion;
+ GetDistributionOSApiVersion;
+ GetDistributionOSApiName;
+ GetDistributionOSReleaseType;
+ SaveParameters;
+ OH_StrArrayGetIndex;
+ OH_ExtendableStrArrayGetIndex;
+ OH_StrDictGet;
+ OH_ExtendableStrDictGet;
+ OpenConsole;
+ local:
+ *;
+};
diff --git a/interfaces/innerkits/modulemgr/modulemgr.c b/interfaces/innerkits/modulemgr/modulemgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..12b38fd45f67d3910d209cb954fe9ae38ee8ce99
--- /dev/null
+++ b/interfaces/innerkits/modulemgr/modulemgr.c
@@ -0,0 +1,335 @@
+/*
+ * 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 "beget_ext.h"
+#include "config_policy_utils.h"
+#include "init_utils.h"
+#include "list.h"
+#include "securec.h"
+#include "modulemgr.h"
+
+#define MODULE_SUFFIX_D ".z.so"
+#ifdef SUPPORT_64BIT
+#define MODULE_LIB_NAME "lib64"
+#else
+#define MODULE_LIB_NAME "lib"
+#endif
+#define LIB_NAME_LEN 3
+
+struct tagMODULE_MGR {
+ ListNode modules;
+ const char *name;
+ MODULE_INSTALL_ARGS installArgs;
+};
+
+MODULE_MGR *ModuleMgrCreate(const char *name)
+{
+ MODULE_MGR *moduleMgr;
+
+ BEGET_CHECK(name != NULL, return NULL);
+
+ moduleMgr = (MODULE_MGR *)malloc(sizeof(MODULE_MGR));
+ BEGET_CHECK(moduleMgr != NULL, return NULL);
+ OH_ListInit(&(moduleMgr->modules));
+ moduleMgr->name = strdup(name);
+ if (moduleMgr->name == NULL) {
+ free((void *)moduleMgr);
+ return NULL;
+ }
+ moduleMgr->installArgs.argc = 0;
+ moduleMgr->installArgs.argv = NULL;
+
+ return moduleMgr;
+}
+
+void ModuleMgrDestroy(MODULE_MGR *moduleMgr)
+{
+ BEGET_CHECK(moduleMgr != NULL, return);
+
+ ModuleMgrUninstall(moduleMgr, NULL);
+ BEGET_CHECK(moduleMgr->name == NULL, free((void *)moduleMgr->name));
+ free((void *)moduleMgr);
+}
+
+/*
+ * Module Item related api
+ */
+
+
+typedef struct tagMODULE_ITEM {
+ ListNode node;
+ MODULE_MGR *moduleMgr;
+ const char *name;
+ void *handle;
+} MODULE_ITEM;
+
+static void ModuleDestroy(ListNode *node)
+{
+ MODULE_ITEM *module;
+
+ BEGET_CHECK(node != NULL, return);
+
+ module = (MODULE_ITEM *)node;
+ BEGET_CHECK(module->name == NULL, free((void *)module->name));
+ BEGET_CHECK(module->handle == NULL, dlclose(module->handle));
+ free((void *)module);
+}
+
+static MODULE_INSTALL_ARGS *currentInstallArgs = NULL;
+
+static void *ModuleInstall(MODULE_ITEM *module, int argc, const char *argv[])
+{
+ void *handle;
+ char path[PATH_MAX];
+ int rc;
+
+ module->moduleMgr->installArgs.argc = argc;
+ module->moduleMgr->installArgs.argv = argv;
+
+ BEGET_LOGV("Module install name %s", module->name);
+ if (module->name[0] == '/') {
+ rc = snprintf_s(path, sizeof(path), sizeof(path) - 1, STARTUP_INIT_UT_PATH"%s" MODULE_SUFFIX_D, module->name);
+ BEGET_CHECK(rc >= 0, return NULL);
+ } else {
+ const char *fmt = (InUpdaterMode() == 0) ? "/system/" MODULE_LIB_NAME : "/" MODULE_LIB_NAME;
+ rc = snprintf_s(path, sizeof(path), sizeof(path) - 1,
+ STARTUP_INIT_UT_PATH"%s/%s/lib%s" MODULE_SUFFIX_D, fmt, module->moduleMgr->name, module->name);
+ BEGET_CHECK(rc >= 0, return NULL);
+ }
+ BEGET_LOGV("Module install path %s", path);
+ char *realPath = GetRealPath(path);
+ BEGET_ERROR_CHECK(realPath != NULL, return NULL, "Failed to get real path");
+ currentInstallArgs = &(module->moduleMgr->installArgs);
+ handle = dlopen(realPath, RTLD_LAZY | RTLD_GLOBAL);
+ currentInstallArgs = NULL;
+ BEGET_CHECK_ONLY_ELOG(handle != NULL, "ModuleInstall path %s fail %d", realPath, errno);
+ free(realPath);
+ return handle;
+}
+
+static int ModuleCompare(ListNode *node, void *data)
+{
+ MODULE_ITEM *module = (MODULE_ITEM *)node;
+ const char *name = module->name;
+ if (module->name[0] == '/') {
+ name = strrchr((name), '/') + 1;
+ }
+ if (strncmp(name, "lib", LIB_NAME_LEN) == 0) {
+ name = name + LIB_NAME_LEN;
+ }
+ return strcmp(name, (char *)data);
+}
+
+/*
+ * 用于扫描安装指定目录下所有的插件。
+ */
+int ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName,
+ int argc, const char *argv[])
+{
+ MODULE_ITEM *module;
+ BEGET_LOGV("ModuleMgrInstall moduleName %s", moduleName);
+ // Get module manager
+ BEGET_CHECK(!(moduleMgr == NULL || moduleName == NULL), return -1);
+
+ module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)moduleName, ModuleCompare);
+ BEGET_ERROR_CHECK(module == NULL, return 0, "%s module already exists", moduleName);
+
+ // Create module item
+ module = (MODULE_ITEM *)malloc(sizeof(MODULE_ITEM));
+ BEGET_CHECK(module != NULL, return -1);
+
+ module->handle = NULL;
+ module->moduleMgr = moduleMgr;
+
+ module->name = strdup(moduleName);
+ BEGET_CHECK(module->name != NULL, free(module);
+ return -1);
+
+ // Install
+ module->handle = ModuleInstall(module, argc, argv);
+#ifndef STARTUP_INIT_TEST
+ if (module->handle == NULL) {
+ BEGET_LOGE("Failed to install module %s", module->name);
+ ModuleDestroy((ListNode *)module);
+ return -1;
+ }
+#endif
+ // Add to list
+ OH_ListAddTail(&(moduleMgr->modules), (ListNode *)module);
+
+ return 0;
+}
+
+const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void)
+{
+ return currentInstallArgs;
+}
+
+static int StringEndsWith(const char *srcStr, const char *endStr)
+{
+ int srcStrLen = strlen(srcStr);
+ int endStrLen = strlen(endStr);
+
+ BEGET_CHECK(!(srcStrLen < endStrLen), return -1);
+
+ srcStr += (srcStrLen - endStrLen);
+ BEGET_CHECK(strcmp(srcStr, endStr) != 0, return (srcStrLen - endStrLen));
+ return -1;
+}
+
+static void ScanModules(MODULE_MGR *moduleMgr, const char *path)
+{
+ BEGET_LOGV("Scan module with name '%s'", path);
+ DIR *dir = opendir(path);
+ BEGET_CHECK(dir != NULL, return);
+ char *moduleName = calloc(PATH_MAX, sizeof(char));
+ while (moduleName != NULL) {
+ struct dirent *file = readdir(dir);
+ if (file == NULL) {
+ break;
+ }
+ if ((file->d_type != DT_REG) && (file->d_type != DT_LNK)) {
+ continue;
+ }
+
+ // Must be ended with MODULE_SUFFIX_D
+ int end = StringEndsWith(file->d_name, MODULE_SUFFIX_D);
+ if (end <= 0) {
+ continue;
+ }
+
+ file->d_name[end] = '\0';
+ int len = sprintf_s(moduleName, PATH_MAX - 1, "%s/%s", path, file->d_name);
+ if (len > 0) {
+ moduleName[len] = '\0';
+ BEGET_LOGI("Scan module with name '%s'", moduleName);
+ ModuleMgrInstall(moduleMgr, moduleName, 0, NULL);
+ }
+ }
+ if (moduleName != NULL) {
+ free(moduleName);
+ }
+ closedir(dir);
+}
+
+/*
+ * 用于扫描安装指定目录下所有的插件。
+ */
+MODULE_MGR *ModuleMgrScan(const char *modulePath)
+{
+ MODULE_MGR *moduleMgr;
+ char path[PATH_MAX];
+ BEGET_LOGV("ModuleMgrScan moduleName %s", modulePath);
+ moduleMgr = ModuleMgrCreate(modulePath);
+ BEGET_CHECK(moduleMgr != NULL, return NULL);
+
+ if (modulePath[0] == '/') {
+ ScanModules(moduleMgr, modulePath);
+ } else if (InUpdaterMode() == 1) {
+ BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
+ "/%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL);
+ ScanModules(moduleMgr, path);
+ } else {
+ BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
+ "%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL);
+ CfgFiles *files = GetCfgFiles(path);
+ for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) {
+ if (files->paths[i]) {
+ ScanModules(moduleMgr, files->paths[i]);
+ }
+ }
+ FreeCfgFiles(files);
+ }
+ return moduleMgr;
+}
+
+/*
+ * 卸载指定插件。
+ */
+void ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name)
+{
+ MODULE_ITEM *module;
+ BEGET_CHECK(moduleMgr != NULL, return);
+ // Uninstall all modules if no name specified
+ if (name == NULL) {
+ OH_ListRemoveAll(&(moduleMgr->modules), ModuleDestroy);
+ return;
+ }
+ BEGET_LOGV("ModuleMgrUninstall moduleName %s", name);
+ // Find module by name
+ module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)name, ModuleCompare);
+ BEGET_ERROR_CHECK(module != NULL, return, "Can not find module %s", name);
+
+ // Remove from the list
+ OH_ListRemove((ListNode *)module);
+ // Destroy the module
+ ModuleDestroy((ListNode *)module);
+}
+
+int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr)
+{
+ BEGET_CHECK(moduleMgr != NULL, return 0);
+ return OH_ListGetCnt(&(moduleMgr->modules));
+}
+
+typedef struct tagMODULE_TRAVERSAL_ARGS {
+ void *cookie;
+ OhosModuleTraversal traversal;
+} MODULE_TRAVERSAL_ARGS;
+
+static int ModuleTraversalProc(ListNode *node, void *cookie)
+{
+ MODULE_ITEM *module;
+ MODULE_TRAVERSAL_ARGS *args;
+ MODULE_INFO info;
+
+ module = (MODULE_ITEM *)node;
+ args = (MODULE_TRAVERSAL_ARGS *)cookie;
+
+ info.cookie = args->cookie;
+ info.handle = module->handle;
+ info.name = module->name;
+ args->traversal(&info);
+
+ return 0;
+}
+
+/**
+ * @brief Traversing all hooks in the HookManager
+ *
+ * @param moduleMgr HookManager handle.
+ * If hookMgr is NULL, it will use default HookManager
+ * @param cookie traversal cookie.
+ * @param traversal traversal function.
+ * @return None.
+ */
+void ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal)
+{
+ MODULE_TRAVERSAL_ARGS args;
+ if (moduleMgr == NULL) {
+ return;
+ }
+
+ args.cookie = cookie;
+ args.traversal = traversal;
+ OH_ListTraversal((ListNode *)(&(moduleMgr->modules)), (void *)(&args), ModuleTraversalProc, 0);
+}
diff --git a/interfaces/innerkits/reboot/init_reboot_innerkits.c b/interfaces/innerkits/reboot/init_reboot_innerkits.c
new file mode 100644
index 0000000000000000000000000000000000000000..81d5023d9bfcc116368b18cccb42d8f9be86d518
--- /dev/null
+++ b/interfaces/innerkits/reboot/init_reboot_innerkits.c
@@ -0,0 +1,88 @@
+/*
+ * 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 "init_reboot.h"
+
+#include
+#include |