• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }