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