1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: mocked shell
15 */
16
17 #include "diag_mocked_shell.h"
18 #include "soc_diag_cmd_id.h"
19 #include "diag_filter.h"
20 #include "diag_common.h"
21 #include "diag_channel_item.h"
22 #include "diag_ind_src.h"
23 #include "diag_adapt_layer.h"
24 #include "securec.h"
25 #include "dfx_adapt_layer.h"
26 #include "uapi_crc.h"
27
28 #define SIZEBUF 256
29 #define BITS_PER_BYTE 8
30 #define MUTEX_STS_BIT 0x1
31 #define ASCII_MAX_VALID_VALUE 0x7F
32 #define DIAG_CMD_SHELL_STR_MAX_LEN 256
33
34 static bool g_zdiag_mocked_shell_enable = false;
35 static uint32_t g_zdiag_msg_flag = MUX_START_FLAG;
36 static zdiag_data_put_uart g_zdiag_data_to_uart = NULL;
37 static diag_cmd_shell_data_proc g_cmd_shell_data_proc = NULL;
38
39 static diag_cmd_reg_obj_t g_zdiag_mocked_shell_cmd_tbl[] = {
40 {DIAG_CMD_MOCKED_SHELL, DIAG_CMD_MOCKED_SHELL, zdiag_cmd_mocked_shell},
41 {DIAG_CMD_MOCKED_SHELL_ENABLE, DIAG_CMD_MOCKED_SHELL_ENABLE, zdiag_cmd_mocked_shell_enable},
42 };
43
zdiag_cmd_mocked_shell(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)44 errcode_t zdiag_cmd_mocked_shell(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size,
45 diag_option_t *option)
46 {
47 unused(cmd_id);
48 unused(option);
49 unused(cmd_param_size);
50
51 uint32_t str_len = *(uint32_t *)cmd_param;
52 if ((str_len == 0) || (str_len >= DIAG_CMD_SHELL_STR_MAX_LEN)) {
53 return ERRCODE_FAIL;
54 }
55
56 uint8_t *data = (uint8_t *)dfx_malloc(0, str_len + 1);
57 if (data == NULL) {
58 return ERRCODE_MALLOC;
59 }
60
61 if (memcpy_s(data, str_len, (void *)((uint32_t)(uintptr_t)cmd_param + sizeof(uint32_t)), str_len) != EOK) {
62 dfx_free(0, data);
63 return ERRCODE_MEMCPY;
64 }
65 data[str_len] = 0;
66 if (g_cmd_shell_data_proc != NULL) {
67 g_cmd_shell_data_proc(data, str_len);
68 }
69 dfx_free(0, data);
70 return ERRCODE_SUCC;
71 }
72
zdiag_cmd_mocked_shell_enable(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)73 errcode_t zdiag_cmd_mocked_shell_enable(uint16_t cmd_id, void *cmd_param,
74 uint16_t cmd_param_size, diag_option_t *option)
75 {
76 unused(cmd_id);
77 unused(option);
78 unused(cmd_param_size);
79
80 bool shell_enabled = false;
81 uint32_t enable = *(uint32_t *)cmd_param;
82
83 if (enable == (uint32_t)-1) {
84 shell_enabled = zdiag_mocked_shell_is_enabled();
85 } else if (enable == 0 || enable == 1) {
86 shell_enabled = (enable == 0) ? false : true;
87 zdiag_mocked_shell_set_enable(shell_enabled);
88 } else {
89 uapi_diag_report_packet(cmd_id, option, (uint8_t *)("Invaild Parameter\r\n"),
90 (uint16_t)strlen("Invaild Parameter\r\n") + 1, true);
91 return ERRCODE_SUCC;
92 }
93
94 if (shell_enabled) {
95 uapi_diag_report_packet(cmd_id, option, (uint8_t *)("Mocked Shell Enabled\r\n"),
96 (uint16_t)strlen("Mocked Shell Enabled\r\n") + 1, true);
97 } else {
98 uapi_diag_report_packet(cmd_id, option, (uint8_t *)("Mocked Shell Disabled\r\n"),
99 (uint16_t)strlen("Mocked Shell Disabled\r\n") + 1, true);
100 }
101 return ERRCODE_SUCC;
102 }
103
zdiag_mocked_shell_register_cmd_data_proc(diag_cmd_shell_data_proc data_proc_hook)104 void zdiag_mocked_shell_register_cmd_data_proc(diag_cmd_shell_data_proc data_proc_hook)
105 {
106 g_cmd_shell_data_proc = data_proc_hook;
107 }
108
109 #ifdef CONFIG_SUPPORT_UART_SHELL
zdiag_mocked_shell_process_uart_data(uint8_t * data,uint16_t size)110 static void zdiag_mocked_shell_process_uart_data(uint8_t *data, uint16_t size)
111 {
112 if (data == NULL || size == 0) {
113 return;
114 }
115
116 if (zdiag_is_enable() != true) {
117 for (uint16_t i = 0; i < size; i++) {
118 g_zdiag_msg_flag =
119 ((uint8_t)g_zdiag_msg_flag == data[i]) ? (g_zdiag_msg_flag >> BITS_PER_BYTE) : MUX_START_FLAG;
120 if (g_zdiag_msg_flag == 0) {
121 g_zdiag_mocked_shell_enable = false;
122 return;
123 }
124 }
125
126 if (g_cmd_shell_data_proc != NULL) {
127 g_cmd_shell_data_proc(data, size);
128 }
129 }
130 }
131 #endif
132
zdiag_mocked_shell_update_status(bool enable)133 static void zdiag_mocked_shell_update_status(bool enable)
134 {
135 if (enable == false) {
136 g_zdiag_msg_flag = MUX_START_FLAG;
137 }
138 }
139
zdiag_mocked_shell_uart_puts(uint8_t * data,uint32_t data_len)140 int zdiag_mocked_shell_uart_puts(uint8_t *data, uint32_t data_len)
141 {
142 #ifndef SUPPORT_DIAG_V2_PROTOCOL
143 uint8_t header_len = (uint8_t)(sizeof(msp_mux_packet_head_stru_t) + sizeof(msp_diag_head_ind_stru_t));
144 uint8_t *print_buf = (uint8_t *)dfx_malloc(0, header_len + data_len);
145 if (print_buf == NULL) {
146 return 0;
147 }
148
149 (void)memset_s(print_buf, header_len + data_len, 0, header_len + data_len);
150 if (memcpy_s(print_buf + header_len, data_len, data, data_len) != EOK) {
151 dfx_free(0, print_buf);
152 return 0;
153 }
154
155 msp_mux_packet_head_stru_t *header = (msp_mux_packet_head_stru_t *)print_buf;
156 header->start_flag = MUX_START_FLAG;
157 header->au_id = 0;
158 header->ver = MUX_PKT_VER;
159 header->cmd_id = DIAG_CMD_MOCKED_SHELL_IND;
160 header->dst = zdiag_get_connect_tool_addr();
161 header->src = diag_adapt_get_local_addr();
162 header->packet_data_size = (uint16_t)sizeof(msp_diag_head_ind_stru_t) + (uint16_t)data_len;
163
164 msp_diag_head_ind_stru_t *ind_head = (msp_diag_head_ind_stru_t *)(print_buf + sizeof(msp_mux_packet_head_stru_t));
165 ind_head->cmd_id = DIAG_CMD_MOCKED_SHELL_IND;
166 ind_head->param_size = (uint16_t)data_len;
167 header->crc16 = uapi_crc16(0, header->puc_packet_data, header->packet_data_size);
168
169 uint8_t *out_data[2];
170 uint16_t out_len[2];
171 out_data[0] = print_buf;
172 out_len[0] = header_len + (uint16_t)data_len;
173 diag_channel_item_t *chan = zdiag_dst_2_chan(header->dst);
174
175 uint32_t lock = dfx_int_lock();
176 chan->tx_hook(0, DFX_DATA_DIAG_PKT, out_data, out_len, 1);
177 dfx_int_restore(lock);
178
179 dfx_free(0, print_buf);
180 return (int)data_len;
181 #else
182 diag_option_t option;
183 option.peer_addr = DIAG_FRAME_FID_UART;
184 if (uapi_diag_report_packet_direct(DIAG_CMD_MOCKED_SHELL_IND, &option, data, (uint16_t)data_len) == ERRCODE_SUCC) {
185 return (int)data_len;
186 } else {
187 return 0;
188 }
189 #endif
190 }
191
zdiag_mocked_shell_print(const char * fmt,va_list ap)192 int zdiag_mocked_shell_print(const char *fmt, va_list ap)
193 {
194 uint8_t *out_buf = (uint8_t *)dfx_malloc(0, SIZEBUF);
195 if (out_buf == NULL) {
196 return -1;
197 }
198 (void)memset_s(out_buf, SIZEBUF, 0, SIZEBUF);
199 int32_t len = vsnprintf_s((char *)out_buf, SIZEBUF, SIZEBUF - 1, fmt, ap);
200 if (len == -1) {
201 dfx_free(0, out_buf);
202 return -1;
203 }
204
205 if (strcmp((char *)(out_buf), "LiteOS$ ") == 0 ||
206 strcmp((char *)(out_buf), "FreeRTOS$ ") == 0) {
207 strcpy_s((char *)(out_buf), SIZEBUF, "End shell command.\r\n");
208 len = (int32_t)strlen("End shell command.\r\n");
209 }
210
211 zdiag_mocked_shell_uart_puts(out_buf, (uint32_t)len);
212 dfx_free(0, out_buf);
213 return len;
214 }
215
zdiag_mocked_shell_register_directly_uartput(zdiag_data_put_uart uart_hook)216 void zdiag_mocked_shell_register_directly_uartput(zdiag_data_put_uart uart_hook)
217 {
218 g_zdiag_data_to_uart = uart_hook;
219 }
220
zdiag_mocked_shell_init(void)221 void zdiag_mocked_shell_init(void)
222 {
223 zdiag_filter_register_notify_hook(zdiag_mocked_shell_update_status);
224 #ifdef CONFIG_SUPPORT_UART_SHELL
225 zdiag_uart_register_bypass_hook(zdiag_mocked_shell_process_uart_data);
226 #endif
227 uapi_diag_register_cmd(g_zdiag_mocked_shell_cmd_tbl,
228 sizeof(g_zdiag_mocked_shell_cmd_tbl) / sizeof(g_zdiag_mocked_shell_cmd_tbl[0]));
229 }
230
zdiag_mocked_shell_set_enable(bool enable)231 void zdiag_mocked_shell_set_enable(bool enable)
232 {
233 g_zdiag_mocked_shell_enable = enable;
234 }
235
zdiag_mocked_shell_is_enabled(void)236 bool zdiag_mocked_shell_is_enabled(void)
237 {
238 return g_zdiag_mocked_shell_enable;
239 }