• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2023 Huawei Device Co., Ltd.
4  */
5 
6 #include <linux/proc_fs.h>
7 
8 #include "dsmm_developer.h"
9 #include "xpm_log.h"
10 
11 #define DSMM_DIR "dsmm"
12 #define DSMM_DEVELOPER_FILE "developer"
13 #define DSMM_DEVELOPER_PARAM_NAME "const.security.developermode.state"
14 
15 static struct proc_dir_entry *g_dsmm_dir;
16 static uint32_t developer_state = STATE_UNINT;
17 
18 static uint32_t g_state_table[BUILD_VARIANT_MAX][CMDLINE_DEV_STATE_MAX] = {
19 	{ STATE_OFF, STATE_ON, STATE_OFF },
20 	{ STATE_ON, STATE_ON, STATE_ON },
21 };
22 
get_developer_status(uint32_t * status)23 static int get_developer_status(uint32_t *status)
24 {
25 	if (!strstr(saved_command_line, "developer_mode=")) {
26 		*status = CMDLINE_DEV_STATE_NA;
27 	} else if (strstr(saved_command_line, "developer_mode=1")) {
28 		*status = CMDLINE_DEV_STATE_ON;
29 	} else if (strstr(saved_command_line, "developer_mode=0")) {
30 		*status = CMDLINE_DEV_STATE_OFF;
31 	} else {
32 		xpm_log_error("invalid developer_mode value in cmdline");
33 		return -EINVAL;
34 	}
35 
36 	return 0;
37 }
38 
get_build_variant(uint32_t * variant)39 static int get_build_variant(uint32_t *variant)
40 {
41 	if (strstr(saved_command_line, "buildvariant=user")) {
42 		*variant = BUILD_VARIANT_USER;
43 	} else if (strstr(saved_command_line, "buildvariant=eng")) {
44 		*variant = BUILD_VARIANT_ENG;
45 	} else {
46 		xpm_log_error("invalid buildvariant value in cmdline");
47 		return -EINVAL;
48 	}
49 
50 	return 0;
51 }
52 
get_developer_mode_state(void)53 int get_developer_mode_state(void)
54 {
55 	uint32_t variant, status;
56 
57 	if (developer_state != STATE_UNINT)
58 		return developer_state;
59 
60 #ifdef CONFIG_DSMM_DEVELOPER_ENABLE
61 	if (get_build_variant(&variant) || get_developer_status(&status)) {
62 		xpm_log_error("get build variant or developer status failed");
63 		developer_state = STATE_OFF;
64 	} else {
65 		developer_state = g_state_table[variant][status];
66 	}
67 #else
68 	developer_state = STATE_ON;
69 #endif
70 
71 	return developer_state;
72 }
73 
74 #define PROC_DEVELOPER_LEN 50
dsmm_read_developer_proc(struct file * file,char __user * buf,size_t count,loff_t * pos)75 static ssize_t dsmm_read_developer_proc(struct file *file, char __user *buf,
76 	size_t count, loff_t *pos)
77 {
78 	size_t len;
79 	uint32_t state;
80 	char proc_developer[PROC_DEVELOPER_LEN] = {0};
81 
82 	state = get_developer_mode_state();
83 	len = snprintf(proc_developer, PROC_DEVELOPER_LEN - 1,
84 		DSMM_DEVELOPER_PARAM_NAME"=%s",
85 		state == STATE_ON ? "true" : "false");
86 
87 	return simple_read_from_buffer(buf, count, pos, proc_developer, len);
88 }
89 
90 static const struct proc_ops dsmm_proc_fops_developer = {
91 	.proc_read = dsmm_read_developer_proc,
92 };
93 
dsmm_developer_proc_create(void)94 void dsmm_developer_proc_create(void)
95 {
96 	g_dsmm_dir = proc_mkdir(DSMM_DIR, NULL);
97 	if (!g_dsmm_dir) {
98 		xpm_log_error("[%s] proc dir create failed", DSMM_DIR);
99 		return;
100 	}
101 
102 	if(!proc_create(DSMM_DEVELOPER_FILE, S_IRUGO, g_dsmm_dir,
103 		&dsmm_proc_fops_developer)) {
104 		xpm_log_error("[%s] proc file create failed",
105 			DSMM_DEVELOPER_FILE);
106 	}
107 }
108 
dsmm_developer_proc_clean(void)109 void dsmm_developer_proc_clean(void)
110 {
111 	if (!g_dsmm_dir)
112 		return;
113 
114 	remove_proc_entry(DSMM_DEVELOPER_FILE, g_dsmm_dir);
115 	remove_proc_entry(DSMM_DIR, NULL);
116 }
117