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 15static struct proc_dir_entry *g_dsmm_dir; 16static uint32_t developer_state = STATE_UNINT; 17 18static 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 23static 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 39static 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 53int 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 75static 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 90static const struct proc_ops dsmm_proc_fops_developer = { 91 .proc_read = dsmm_read_developer_proc, 92}; 93 94void 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 109void 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