mirror of
https://github.com/openharmony/drivers_peripheral.git
synced 2026-08-24 07:45:51 -04:00
715a91a9b0
Signed-off-by: w30051647 <wangyikai14@h-partners.com>
337 lines
10 KiB
C
337 lines
10 KiB
C
/*
|
|
* 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 <errno.h>
|
|
#include <limits.h>
|
|
#include <sched.h>
|
|
#include <signal.h>
|
|
#include <stdlib.h>
|
|
#include <sys/prctl.h>
|
|
#include <sys/resource.h>
|
|
#include <getopt.h>
|
|
|
|
#include "securec.h"
|
|
#include "parameter.h"
|
|
#include "malloc.h"
|
|
#include "devhost_dump.h"
|
|
#include "devhost_service.h"
|
|
#include "devhost_service_full.h"
|
|
#include "hdf_base.h"
|
|
#include "hdf_core_log.h"
|
|
#include "hdf_power_manager.h"
|
|
|
|
#define HDF_LOG_TAG hdf_device_host
|
|
#define DEVHOST_MIN_INPUT_PARAM_NUM 5
|
|
#define DEVHOST_INPUT_PARAM_HOSTID_POS 1
|
|
#define DEVHOST_HOST_NAME_POS 2
|
|
#define DEVHOST_PROCESS_PRI_POS 3
|
|
#define DEVHOST_THREAD_PRI_POS 4
|
|
#define PARAM_BUF_LEN 128
|
|
#define MALLOPT_PARA_CNT 2
|
|
#define INVALID_PRIORITY "0"
|
|
#define DEVHOST_ARGUMENT 2
|
|
|
|
typedef struct {
|
|
int hostId;
|
|
const char *hostName;
|
|
int schedPriority;
|
|
int processPriority;
|
|
int malloptKey;
|
|
int malloptValue;
|
|
} HostConfig;
|
|
|
|
bool HdfStringToInt(const char *str, int *value)
|
|
{
|
|
if (str == NULL || value == NULL) {
|
|
return false;
|
|
}
|
|
|
|
char *end = NULL;
|
|
errno = 0;
|
|
const int base = 10;
|
|
long result = strtol(str, &end, base);
|
|
if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) {
|
|
return false;
|
|
}
|
|
|
|
*value = (int)result;
|
|
return true;
|
|
}
|
|
|
|
static void SetMallopt(int32_t malloptKey, int32_t malloptValue)
|
|
{
|
|
int ret = mallopt(malloptKey, malloptValue);
|
|
if (ret != 1) {
|
|
HDF_LOGE("mallopt failed, malloptKey:%{public}d, malloptValue:%{public}d, ret:%{public}d",
|
|
malloptKey, malloptValue, ret);
|
|
return;
|
|
}
|
|
HDF_LOGI("host set mallopt succeed, mallopt:%{public}d %{public}d", malloptKey, malloptValue);
|
|
}
|
|
|
|
typedef int32_t (*CommandFunc)(const char *key, const char *value, HostConfig *config);
|
|
typedef struct CommandToFunc {
|
|
const char *opt;
|
|
CommandFunc func;
|
|
} CommandToFunc;
|
|
|
|
static int32_t CommandIFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
(void)key;
|
|
if (!HdfStringToInt(value, &config->hostId)) {
|
|
HDF_LOGE("Invalid process ID: %{public}s", value);
|
|
return HDF_ERR_INVALID_PARAM;
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int32_t CommandNFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
(void)key;
|
|
config->hostName = value;
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int32_t CommandPFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
(void)key;
|
|
if (!HdfStringToInt(value, &config->processPriority)) {
|
|
HDF_LOGE("Invalid process ID: %{public}s", value);
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int32_t CommandSFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
(void)key;
|
|
if (!HdfStringToInt(value, &config->schedPriority)) {
|
|
HDF_LOGE("Invalid process ID: %{public}s", value);
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int32_t CommandMFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
(void)key;
|
|
if (!HdfStringToInt(value, &config->malloptKey)) {
|
|
HDF_LOGE("Invalid process ID: %{public}s", value);
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int32_t CommandVFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
(void)key;
|
|
if (!HdfStringToInt(value, &config->malloptValue)) {
|
|
HDF_LOGE("Invalid process ID: %{public}s", value);
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int32_t CommandNumFunc(const char *key, const char *value, HostConfig *config)
|
|
{
|
|
int32_t malloptKey = 0;
|
|
int32_t malloptValue = 0;
|
|
if (!HdfStringToInt(value, &malloptValue)) {
|
|
HDF_LOGE("Invalid value: %{public}s", value);
|
|
return HDF_FAILURE;
|
|
}
|
|
if (!HdfStringToInt(key, &malloptKey)) {
|
|
HDF_LOGE("Invalid key: %{public}s", key);
|
|
return HDF_FAILURE;
|
|
}
|
|
SetMallopt(malloptKey, malloptValue);
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static struct CommandToFunc g_commandFuncs[] = {
|
|
{"-i", CommandIFunc},
|
|
{"-n", CommandNFunc},
|
|
{"-p", CommandPFunc},
|
|
{"-s", CommandSFunc},
|
|
{"-m", CommandMFunc},
|
|
{"-v", CommandVFunc},
|
|
{"-1005", CommandNumFunc},
|
|
{"-1006", CommandNumFunc},
|
|
{"-1007", CommandNumFunc},
|
|
{"-1008", CommandNumFunc},
|
|
{"-1009", CommandNumFunc},
|
|
{"-1010", CommandNumFunc},
|
|
{"-1011", CommandNumFunc},
|
|
{"-1012", CommandNumFunc},
|
|
{"-1013", CommandNumFunc},
|
|
{"-1014", CommandNumFunc},
|
|
};
|
|
|
|
static void StartMemoryHook(const char* processName)
|
|
{
|
|
const char defaultValue[PARAM_BUF_LEN] = { 0 };
|
|
const char targetPrefix[] = "startup:";
|
|
const int targetPrefixLen = strlen(targetPrefix);
|
|
char paramValue[PARAM_BUF_LEN] = { 0 };
|
|
int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
|
|
if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
|
|
return;
|
|
}
|
|
if (strstr(paramValue + targetPrefixLen, processName) != NULL) {
|
|
const int hookSignal = 36; // 36: native memory hooked signal
|
|
HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName);
|
|
raise(hookSignal);
|
|
}
|
|
}
|
|
|
|
static void SetProcTitle(char **argv, const char *newTitle)
|
|
{
|
|
if (newTitle == NULL) {
|
|
HDF_LOGE("failed because newTitle is NULL");
|
|
return;
|
|
}
|
|
size_t len = strlen(argv[0]);
|
|
if (strlen(newTitle) > len) {
|
|
HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle);
|
|
return;
|
|
}
|
|
(void)memset_s(argv[0], len, 0, len);
|
|
if (strcpy_s(argv[0], len + 1, newTitle) != EOK) {
|
|
HDF_LOGE("failed to set new process title");
|
|
return;
|
|
}
|
|
prctl(PR_SET_NAME, newTitle);
|
|
}
|
|
|
|
static void HdfSetProcPriority(int32_t procPriority, int32_t schedPriority)
|
|
{
|
|
if (setpriority(PRIO_PROCESS, 0, procPriority) != 0) {
|
|
HDF_LOGE("host setpriority failed: %{public}d", errno);
|
|
}
|
|
|
|
struct sched_param param = {0};
|
|
param.sched_priority = schedPriority;
|
|
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
|
|
HDF_LOGE("host sched_setscheduler failed: %{public}d", errno);
|
|
} else {
|
|
HDF_LOGI("host sched_setscheduler succeed:%{public}d %{public}d", procPriority, schedPriority);
|
|
}
|
|
}
|
|
|
|
static int FindFunc(const char* arg, const char* value, HostConfig *config)
|
|
{
|
|
for (size_t i = 0; i < sizeof(g_commandFuncs) / sizeof(g_commandFuncs[0]); ++i) {
|
|
if (strcmp(g_commandFuncs[i].opt, arg) == 0) {
|
|
return g_commandFuncs[i].func(arg, value, config);
|
|
}
|
|
}
|
|
HDF_LOGE("FindFunc failed: %{public}s", arg);
|
|
return HDF_FAILURE;
|
|
}
|
|
|
|
static int ParseCommandLineArgs(int argc, char **argv, HostConfig *config)
|
|
{
|
|
for (int i = 1; i < argc; i += DEVHOST_ARGUMENT) {
|
|
const char* arg = argv[i];
|
|
|
|
if (arg == NULL) {
|
|
HDF_LOGE("NULL argument:arg");
|
|
continue;
|
|
}
|
|
|
|
int valueIndex = i + 1;
|
|
if (valueIndex >= argc) {
|
|
HDF_LOGE("Missing argument for %{public}s", arg);
|
|
continue;
|
|
}
|
|
const char* value = argv[valueIndex];
|
|
if (value == NULL) {
|
|
HDF_LOGE("NULL argument: value");
|
|
continue;
|
|
}
|
|
if (FindFunc(arg, value, config) == HDF_ERR_INVALID_PARAM) {
|
|
return HDF_ERR_INVALID_PARAM;
|
|
}
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int InitializeHost(const HostConfig *config, char **argv)
|
|
{
|
|
prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process
|
|
|
|
HDF_LOGI("hdf device host %{public}s %{public}d start", config->hostName, config->hostId);
|
|
SetProcTitle(argv, config->hostName);
|
|
StartMemoryHook(config->hostName);
|
|
if ((config->processPriority != 0) && (config->schedPriority != 0)) {
|
|
HdfSetProcPriority(config->processPriority, config->schedPriority);
|
|
}
|
|
if ((config->malloptKey != 0) && (config->malloptValue != 0)) {
|
|
SetMallopt(config->malloptKey, config->malloptValue);
|
|
}
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
static int StartHostService(const HostConfig *config)
|
|
{
|
|
struct IDevHostService *instance = DevHostServiceNewInstance(config->hostId, config->hostName);
|
|
if (instance == NULL || instance->StartService == NULL) {
|
|
HDF_LOGE("DevHostServiceGetInstance fail");
|
|
return HDF_ERR_INVALID_OBJECT;
|
|
}
|
|
HDF_LOGD("create IDevHostService of %{public}s success", config->hostName);
|
|
|
|
DevHostDumpInit();
|
|
HDF_LOGD("%{public}s start device service begin", config->hostName);
|
|
int status = instance->StartService(instance);
|
|
if (status != HDF_SUCCESS) {
|
|
HDF_LOGE("Devhost StartService fail, return: %{public}d", status);
|
|
DevHostServiceFreeInstance(instance);
|
|
DevHostDumpDeInit();
|
|
return status;
|
|
}
|
|
|
|
HdfPowerManagerInit();
|
|
struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
|
|
struct HdfMessageLooper *looper = &fullService->looper;
|
|
if ((looper != NULL) && (looper->Start != NULL)) {
|
|
HDF_LOGI("%{public}s start loop", config->hostName);
|
|
looper->Start(looper);
|
|
}
|
|
|
|
DevHostServiceFreeInstance(instance);
|
|
HdfPowerManagerExit();
|
|
DevHostDumpDeInit();
|
|
return HDF_SUCCESS;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc < DEVHOST_MIN_INPUT_PARAM_NUM) {
|
|
HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc);
|
|
return HDF_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
HostConfig config = {0};
|
|
if (ParseCommandLineArgs(argc, argv, &config) != HDF_SUCCESS) {
|
|
HDF_LOGE("ParseCommandLineArgs(argc, argv, &config) != HDF_SUCCESS");
|
|
return HDF_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (InitializeHost(&config, argv) != HDF_SUCCESS) {
|
|
return HDF_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
int status = StartHostService(&config);
|
|
HDF_LOGI("hdf device host %{public}s %{public}d exit", config.hostName, config.hostId);
|
|
return status;
|
|
}
|