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: diag oam log
15 * This file should be changed only infrequently and with great care.
16 */
17 #include "securec.h"
18 #include "log_oam_msg.h"
19 #include "log_oam_logger.h"
20 #include "log_oam_status.h"
21 #include "log_oam_ota.h"
22 #include "log_oam_pcm.h"
23 #include "log_oml_exception.h"
24 #include "diag.h"
25 #include "soc_diag_util.h"
26 #include "diag_common.h"
27 #include "diag_filter.h"
28 #include "diag_adapt_layer.h"
29 #include "sample_data_adapt.h"
30 #include "log_common.h"
31 #include "diag_adapt_sdt.h"
32
33 #ifdef SUPPORT_CONNECTIVITY
34 #include "connectivity_log.h"
35 #endif
36
37 enum {
38 LOG_STATUS_MODULE = MODULEID_BUTT,
39 LOG_OTA_MODULE,
40 } log_adapt_module;
41
42 typedef enum {
43 SDT_MSG_STEP_HEAD, /* sdt msg head */
44 SDT_MSG_STEP_BODY, /* sdt msg body */
45 STD_MSG_STEP_TAIL, /* sdt msg tail */
46 } sdt_msg_pack_step_t;
47
48 typedef struct {
49 uint8_t *msg;
50 uint32_t len;
51 } zdiag_adapt_sdt_msg_t;
52
53 typedef struct diag_msg_para {
54 uint32_t module_id;
55 uint32_t msg_id;
56 uint32_t no;
57 uint8_t *buf;
58 uint16_t buf_size;
59 uint8_t level;
60 } diag_msg_para_t;
61
62 oam_cmd_handle_callback g_diag_debug_proc = NULL;
63 uint8_t g_recv_msg_step = SDT_MSG_STEP_HEAD;
64 uint8_t *g_recv_buf = NULL; /* 组包buf */
65
log_level_trans(uint32_t sdt_level)66 static uint32_t log_level_trans(uint32_t sdt_level)
67 {
68 /* sdt 日志等级4种, hso日志等级8种,需要转换一次 */
69 uint32_t level[LOG_LEVEL_MAX] = {
70 DIAG_LOG_LEVEL_ALERT,
71 DIAG_LOG_LEVEL_ERROR,
72 DIAG_LOG_LEVEL_WARN,
73 DIAG_LOG_LEVEL_INFO,
74 DIAG_LOG_LEVEL_DBG,
75 };
76
77 if (sdt_level < LOG_LEVEL_MAX) {
78 return level[sdt_level];
79 } else {
80 return LOG_LEVEL_NONE;
81 }
82 }
83
84 /*
85 For std log:
86 1bit | 4bit | 10bit | 14bit | 3bit |
87 logFlag = 1 | mod_id | file_id | line_no | level |
88 for other:
89 1bit | 7bit | 8bit | 16bit |
90 logFlag = 0 | resv = 0 | type | msg_id |
91 */
92
zdiag_adapt_sdt_om_log_parse(uint8_t * sdt_buf,uint16_t sdt_buf_size,diag_msg_para_t * para)93 static void zdiag_adapt_sdt_om_log_parse(uint8_t *sdt_buf, uint16_t sdt_buf_size, diag_msg_para_t *para)
94 {
95 om_log_header_t* om_log = (om_log_header_t*)sdt_buf;
96
97 uint32_t file_id = (om_log->file_idx_high << 2) + om_log->bit2_file_idx_low;
98 uint32_t line_no = (om_log->bit6_line_no_high << 8) + om_log->line_no_low;
99 uint32_t sdt_level = (uint32_t)om_log->mod_print_lev_info >> 6; /* level 2 bit */
100 uint32_t mod_id = om_log->header.prime_id >> 4; /* 高4 bit 为mod_id */
101
102 para->module_id = mod_id;
103
104 para->msg_id = (1 << 31); /* bit31 为logFlag */
105 para->msg_id += mod_id << 27; /* bit27 ~ bit30 为mod_id */
106 para->msg_id += (file_id & 0x3FF) << 17; /* bit17 ~ bit26 为file_id */
107 para->msg_id += (line_no & 0x3FFF) << 3; /* bit3 ~ bit16 为line_no */
108 para->msg_id += log_level_trans(sdt_level);
109
110 para->no = om_log->header.sn;
111 para->buf = sdt_buf + sizeof(om_log_header_t);
112 para->buf_size = (uint16_t)(sdt_buf_size - sizeof(om_log_header_t) - sizeof(uint8_t));
113 para->level = (uint8_t)log_level_trans(sdt_level);
114 }
115
zdiag_adapt_sdt_om_status_parse(uint8_t * sdt_buf,uint16_t sdt_buf_size,diag_msg_para_t * para)116 static void zdiag_adapt_sdt_om_status_parse(uint8_t *sdt_buf, uint16_t sdt_buf_size, diag_msg_para_t *para)
117 {
118 om_status_data_stru_t *om_status = (om_status_data_stru_t*)sdt_buf;
119
120 unused(sdt_buf_size);
121 para->module_id = LOG_STATUS_MODULE;
122 para->msg_id = (OM_MSG_TYPE_STATUS << 16) | om_status->msg_id; /* 高16 bit 为MSG_TYPE */
123 para->no = om_status->header.sn;
124 para->buf = om_status->data;
125 para->buf_size = om_status->data_len;
126 para->level = DIAG_LOG_LEVEL_INFO;
127 }
128
zdiag_adapt_sdt_om_ota_parse(uint8_t * sdt_buf,uint16_t sdt_buf_size,diag_msg_para_t * para)129 static void zdiag_adapt_sdt_om_ota_parse(uint8_t *sdt_buf, uint16_t sdt_buf_size, diag_msg_para_t *para)
130 {
131 om_ota_header_t *om_ota = (om_ota_header_t*)sdt_buf;
132 para->module_id = LOG_OTA_MODULE;
133 para->msg_id = (OM_MSG_TYPE_OTA << 16) | om_ota->msg_id; /* 高16 bit 为MSG_TYPE */
134 para->no = om_ota->header.sn;
135 para->buf = sdt_buf + sizeof(om_ota_header_t);
136 para->buf_size = (uint16_t)(sdt_buf_size - sizeof(om_ota_header_t) - sizeof(uint8_t));
137 para->level = DIAG_LOG_LEVEL_INFO;
138 }
139
zdiag_adapt_sdt_om_last_parse(uint8_t * sdt_buf,uint16_t sdt_buf_size,diag_msg_para_t * para)140 static void zdiag_adapt_sdt_om_last_parse(uint8_t *sdt_buf, uint16_t sdt_buf_size, diag_msg_para_t *para)
141 {
142 om_exception_info_stru_t *om_last = (om_exception_info_stru_t*)sdt_buf;
143 para->module_id = LOG_BTMODULE;
144 para->msg_id = (OM_MSG_TYPE_LAST << 16) | om_last->msg_header.prime_id; /* 高16 bit 为MSG_TYPE */
145 para->no = om_last->msg_header.sn;
146 para->buf = sdt_buf + sizeof(om_msg_header_stru_t);
147 para->buf_size = (uint16_t)(sdt_buf_size - sizeof(om_msg_header_stru_t) - sizeof(uint8_t));
148 para->level = DIAG_LOG_LEVEL_INFO;
149 }
150
zdiag_adapt_sdt_msg_report(uint8_t * sdt_buf,uint16_t sdt_buf_size)151 static void zdiag_adapt_sdt_msg_report(uint8_t *sdt_buf, uint16_t sdt_buf_size)
152 {
153 om_msg_header_stru_t *om_msg_header;
154 diag_msg_para_t para;
155
156 om_msg_header = (om_msg_header_stru_t*)sdt_buf;
157 if (om_msg_header->func_type == OM_MSG_TYPE_OTA) {
158 zdiag_adapt_sdt_om_ota_parse(sdt_buf, sdt_buf_size, ¶);
159 uapi_diag_report_sys_msg(para.module_id, para.msg_id, para.buf, para.buf_size, para.level);
160 } else if (om_msg_header->func_type == OM_BT_SAMPLE_DATA) {
161 zdiag_adapt_sample_data_report(sdt_buf, sdt_buf_size);
162 } else {
163 return;
164 }
165 }
166
zdiag_adapt_msg_pack_check(uint8_t * data,uint32_t data_len)167 static errcode_t zdiag_adapt_msg_pack_check(uint8_t *data, uint32_t data_len)
168 {
169 om_msg_header_stru_t *om_msg_header = (om_msg_header_stru_t*)data;
170 if (data_len < sizeof(om_msg_header_stru_t)) {
171 return ERRCODE_FAIL;
172 }
173
174 if (om_msg_header->frame_start != OM_FRAME_DELIMITER) {
175 return ERRCODE_FAIL;
176 }
177
178 if (om_msg_header->func_type == OM_MSG_TYPE_OTA) {
179 if (om_msg_header->frame_len > OTA_DATA_MAX_SIZE + sizeof(om_msg_header_stru_t) + 1) {
180 return ERRCODE_FAIL;
181 }
182 } else if (om_msg_header->func_type == OM_BT_SAMPLE_DATA) {
183 if (om_msg_header->frame_len > BT_SAMPLE_DATA_MAX_SIZE + sizeof(om_pcm_header_t) + 1) {
184 return ERRCODE_FAIL;
185 }
186 } else {
187 return ERRCODE_FAIL;
188 }
189
190 return ERRCODE_SUCC;
191 }
zdiag_adapt_msg_pack_para_reinit(void)192 static void zdiag_adapt_msg_pack_para_reinit(void)
193 {
194 g_recv_msg_step = SDT_MSG_STEP_HEAD;
195 if (g_recv_buf != NULL) {
196 dfx_free(0, g_recv_buf);
197 g_recv_buf = NULL;
198 }
199 }
200
zdiag_adapt_sdt_msg_dispatch(uint32_t msg_id,uint8_t * data,uint32_t data_len)201 errcode_t zdiag_adapt_sdt_msg_dispatch(uint32_t msg_id, uint8_t *data, uint32_t data_len)
202 {
203 zdiag_adapt_sdt_msg_t *msg = (zdiag_adapt_sdt_msg_t*)data;
204 uint32_t check_valid;
205 unused(msg_id);
206 unused(data_len);
207 uint32_t frame_len = 0; /* om包长度 */
208 uint32_t recv_len = 0;
209
210 if (g_recv_msg_step == SDT_MSG_STEP_HEAD) {
211 check_valid = zdiag_adapt_msg_pack_check(msg->msg, msg->len);
212 if (check_valid == ERRCODE_SUCC) {
213 frame_len = ((om_msg_header_stru_t *)msg->msg)->frame_len;
214 g_recv_buf = dfx_malloc(0, frame_len);
215 if (g_recv_buf != NULL) {
216 (void)memcpy_s(g_recv_buf, frame_len, msg->msg, msg->len);
217 recv_len = msg->len;
218 g_recv_msg_step = SDT_MSG_STEP_BODY;
219 }
220 }
221 } else if (g_recv_msg_step == SDT_MSG_STEP_BODY) {
222 if (frame_len - recv_len > 0) {
223 (void)memcpy_s(g_recv_buf + recv_len, frame_len - recv_len, msg->msg, msg->len);
224 }
225 recv_len += msg->len;
226 g_recv_msg_step = STD_MSG_STEP_TAIL;
227 } else {
228 if (frame_len - recv_len > 0) {
229 (void)memcpy_s(g_recv_buf + recv_len, frame_len - recv_len, msg->msg, msg->len);
230 }
231 zdiag_adapt_sdt_msg_report(g_recv_buf, (uint16_t)frame_len);
232 zdiag_adapt_msg_pack_para_reinit();
233 }
234 dfx_free(0, msg->msg);
235 return ERRCODE_SUCC;
236 }
237
zdiag_adapt_sdt_short_msg_report(uint8_t * data,uint32_t data_len)238 static bool zdiag_adapt_sdt_short_msg_report(uint8_t *data, uint32_t data_len)
239 {
240 om_msg_header_stru_t *om_msg_header = NULL;
241 diag_msg_para_t para;
242 bool pack = true;
243 bool report = false;
244
245 if (data_len >= sizeof(om_msg_header_stru_t)) {
246 om_msg_header = (om_msg_header_stru_t*)data;
247 if ((om_msg_header->frame_start == OM_FRAME_DELIMITER) &&
248 (om_msg_header->frame_len == data_len) &&
249 (data[data_len - 1] == OM_FRAME_DELIMITER)) {
250 if (om_msg_header->func_type == OM_MSG_TYPE_LOG) {
251 zdiag_adapt_sdt_om_log_parse(data, (uint16_t)data_len, ¶);
252 report = true;
253 } else if (om_msg_header->func_type == OM_MSG_TYPE_STATUS) {
254 zdiag_adapt_sdt_om_status_parse(data, (uint16_t)data_len, ¶);
255 report = true;
256 } else if (om_msg_header->func_type == OM_MSG_TYPE_LAST) {
257 zdiag_adapt_sdt_om_last_parse(data, (uint16_t)data_len, ¶);
258 report = true;
259 }
260 pack = false;
261 /* OTA, BT SAMPLE 三包数据一起写buffer,不会夹杂其他数据,若出现丢弃已pack的部分包 */
262 zdiag_adapt_msg_pack_para_reinit();
263 }
264 }
265
266 if (report) {
267 uapi_diag_report_sys_msg(para.module_id, para.msg_id, para.buf, para.buf_size, para.level);
268 }
269
270 return pack;
271 }
272
zdiag_adapt_sdt_msg_proc(uint8_t * buf1,uint32_t len1,uint8_t * buf2,uint32_t len2)273 void zdiag_adapt_sdt_msg_proc(uint8_t *buf1, uint32_t len1, uint8_t *buf2, uint32_t len2)
274 {
275 zdiag_adapt_sdt_msg_t msg;
276 uint32_t len = len1 + len2;
277 uint8_t *buf = NULL;
278 uint32_t pos = 0;
279 uint32_t ret;
280 bool pack;
281
282 if (zdiag_is_enable() == false) {
283 return;
284 }
285
286 if (len > 0) {
287 buf = dfx_malloc(0, len);
288 }
289
290 if (buf == NULL) {
291 return;
292 }
293
294 if (len1 > 0) {
295 (void)memcpy_s(buf + pos, len1, buf1, len1);
296 pos += len1;
297 }
298
299 if (len2 > 0) {
300 (void)memcpy_s(buf + pos, len2, buf2, len2);
301 }
302
303 /* 如果是非整包数据,入队列,做pack处理 */
304 pack = zdiag_adapt_sdt_short_msg_report(buf, len);
305 if (pack) {
306 msg.msg = buf;
307 msg.len = len;
308 ret = dfx_msg_write(DFX_MSG_ID_SDT_MSG, (uint8_t *)&msg, sizeof(zdiag_adapt_sdt_msg_t), false);
309 if (ret != ERRCODE_SUCC) {
310 dfx_log_err("sdt msg write to queue error\r\n");
311 dfx_free(0, buf);
312 }
313 } else {
314 dfx_free(0, buf);
315 }
316 }
317
diag_register_debug_cmd_callback(oam_cmd_handle_callback func)318 void diag_register_debug_cmd_callback(oam_cmd_handle_callback func)
319 {
320 g_diag_debug_proc = func;
321 }
322
diag_debug_cmd_proc(uint8_t * data,uint32_t len)323 void diag_debug_cmd_proc(uint8_t *data, uint32_t len)
324 {
325 if (g_diag_debug_proc != NULL) {
326 g_diag_debug_proc(data, (uint16_t)len);
327 }
328 }
329
330 #ifndef FORBID_AUTO_LOG_REPORT
diag_auto_log_report_enable(void)331 void diag_auto_log_report_enable(void)
332 {
333 uint8_t level[] = {
334 DIAG_LOG_LEVEL_ERROR,
335 DIAG_LOG_LEVEL_WARN,
336 DIAG_LOG_LEVEL_INFO,
337 DIAG_LOG_LEVEL_DBG,
338 };
339 uint32_t mod_id[] = {
340 LOG_WIFIMODULE,
341 LOG_BTMODULE,
342 LOG_PFMODULE,
343 LOG_NFCMODULE,
344 LOG_STATUS_MODULE,
345 LOG_OTA_MODULE,
346 };
347
348 /* module 使能 */
349 for (uint32_t i = 0; i < sizeof(mod_id) / sizeof(uint32_t); i++) {
350 zdiag_set_id_enable(mod_id[i], 1);
351 }
352
353 /* 未连接hso时,不上报所有 level */
354 for (uint32_t i = 0; i < sizeof(level) / sizeof(uint32_t); i++) {
355 zdiag_set_level_enable(level[i], 0);
356 }
357 }
358 #endif
359
zdiag_level_proc(uint8_t level)360 void zdiag_level_proc(uint8_t level)
361 {
362 log_level_e core_level = LOG_LEVEL_NONE;
363
364 if ((level & (1 << DIAG_LOG_LEVEL_INFO)) != 0) {
365 core_level = LOG_LEVEL_INFO;
366 } else if ((level & (1 << DIAG_LOG_LEVEL_WARN)) != 0) {
367 core_level = LOG_LEVEL_WARNING;
368 } else if ((level & (1 << DIAG_LOG_LEVEL_ERROR)) != 0) {
369 core_level = LOG_LEVEL_ERROR;
370 }
371
372 log_set_local_log_level(core_level);
373 }
374