* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/proc_fs.h>
#include "dsmm_developer.h"
#include "xpm_log.h"
#define DSMM_DIR "dsmm"
#define DSMM_DEVELOPER_FILE "developer"
#define DSMM_DEVELOPER_PARAM_NAME "const.security.developermode.state"
static struct proc_dir_entry *g_dsmm_dir;
static uint32_t developer_state = STATE_UNINT;
static uint32_t g_state_table[BUILD_VARIANT_MAX][CMDLINE_DEV_STATE_MAX] = {
{ STATE_OFF, STATE_ON, STATE_OFF },
{ STATE_ON, STATE_ON, STATE_ON },
};
static int get_developer_status(uint32_t *status)
{
if (!strstr(saved_command_line, "developer_mode=")) {
*status = CMDLINE_DEV_STATE_NA;
} else if (strstr(saved_command_line, "developer_mode=1")) {
*status = CMDLINE_DEV_STATE_ON;
} else if (strstr(saved_command_line, "developer_mode=0")) {
*status = CMDLINE_DEV_STATE_OFF;
} else {
xpm_log_error("invalid developer_mode value in cmdline");
return -EINVAL;
}
return 0;
}
static int get_build_variant(uint32_t *variant)
{
if (strstr(saved_command_line, "buildvariant=user")) {
*variant = BUILD_VARIANT_USER;
} else if (strstr(saved_command_line, "buildvariant=eng")) {
*variant = BUILD_VARIANT_ENG;
} else {
xpm_log_error("invalid buildvariant value in cmdline");
return -EINVAL;
}
return 0;
}
int get_developer_mode_state(void)
{
uint32_t variant, status;
if (developer_state != STATE_UNINT)
return developer_state;
#ifdef CONFIG_DSMM_DEVELOPER_ENABLE
if (get_build_variant(&variant) || get_developer_status(&status)) {
xpm_log_error("get build variant or developer status failed");
developer_state = STATE_OFF;
} else {
developer_state = g_state_table[variant][status];
}
#else
developer_state = STATE_ON;
#endif
return developer_state;
}
#define PROC_DEVELOPER_LEN 50
static ssize_t dsmm_read_developer_proc(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
size_t len;
uint32_t state;
char proc_developer[PROC_DEVELOPER_LEN] = {0};
state = get_developer_mode_state();
len = snprintf(proc_developer, PROC_DEVELOPER_LEN - 1,
DSMM_DEVELOPER_PARAM_NAME"=%s",
state == STATE_ON ? "true" : "false");
return simple_read_from_buffer(buf, count, pos, proc_developer, len);
}
static const struct proc_ops dsmm_proc_fops_developer = {
.proc_read = dsmm_read_developer_proc,
};
void dsmm_developer_proc_create(void)
{
g_dsmm_dir = proc_mkdir(DSMM_DIR, NULL);
if (!g_dsmm_dir) {
xpm_log_error("[%s] proc dir create failed", DSMM_DIR);
return;
}
if(!proc_create(DSMM_DEVELOPER_FILE, S_IRUGO, g_dsmm_dir,
&dsmm_proc_fops_developer)) {
xpm_log_error("[%s] proc file create failed",
DSMM_DEVELOPER_FILE);
}
}
void dsmm_developer_proc_clean(void)
{
if (!g_dsmm_dir)
return;
remove_proc_entry(DSMM_DEVELOPER_FILE, g_dsmm_dir);
remove_proc_entry(DSMM_DIR, NULL);
}