• 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:  LOG BUFFER READER MODULE.
15  * Author:
16  * Create:  2018-10-15
17  */
18 #include "panic.h"
19 #include "securec.h"
20 #include "log_memory_section.h"
21 #include "stdint.h"
22 #include "diag_log.h"
23 #include "log_buffer_reader.h"
24 /*
25  *  Private type definitions
26  */
27 typedef struct {
28     uint8_t *log_buffer_start;
29     uint32_t log_buffer_size;
30     volatile uint32_t lb_next_to_consume;  // == not disdarded yet
31 } log_buffer_reader_control_t;
32 
33 /*
34  *  Private variable declarations
35  */
36 /** Array of pointers to the section control structures for the different regions in the shared memory */
37 static log_memory_section_control_t *g_section_control[LOG_MEMORY_REGION_MAX_NUMBER];
38 
39 /** Internal control for the different log regions */
40 static log_buffer_reader_control_t g_buffer_reader_control[LOG_MEMORY_REGION_MAX_NUMBER];
41 
42 /*
43  *  Private function definitions
44  */
circled_index(const log_buffer_reader_control_t * lmscontrol,uint32_t index_in)45 static uint32_t circled_index(const log_buffer_reader_control_t *lmscontrol, uint32_t index_in)
46 {
47     uint32_t index_out;
48 
49     if (index_in < lmscontrol->log_buffer_size) {
50         index_out = index_in;
51     } else {
52         index_out = index_in - lmscontrol->log_buffer_size;
53     }
54     if (index_out >= lmscontrol->log_buffer_size) {
55         panic(PANIC_LOG, __LINE__);
56     }
57     return index_out;
58 }
59 
log_buffer_copy_consecutive(const log_buffer_reader_control_t * lmscontrol,uint8_t * destination_p,uint32_t index_in,uint32_t len)60 static void log_buffer_copy_consecutive(const log_buffer_reader_control_t *lmscontrol,
61                                         uint8_t *destination_p, uint32_t index_in, uint32_t len)
62 {
63     if (destination_p == NULL) {
64         panic(PANIC_LOG, __LINE__);
65         return;
66     }
67     if (len >= lmscontrol->log_buffer_size) {
68         panic(PANIC_LOG, __LINE__);
69         return;
70     }
71     errno_t sec_ret;
72 
73     if (index_in + len <= lmscontrol->log_buffer_size) {
74         sec_ret = memcpy_s((void *)destination_p, len, (void *)(lmscontrol->log_buffer_start + index_in), len);
75     } else {
76         uint32_t l1;
77         l1 = lmscontrol->log_buffer_size - index_in;
78         // copy first part
79         sec_ret = memcpy_s(destination_p, l1, (void *)(lmscontrol->log_buffer_start + index_in), l1);
80         if (sec_ret != EOK) {
81             return;
82         }
83         // copy second part
84         sec_ret = memcpy_s((void *)(destination_p + l1), len - l1, (void *)lmscontrol->log_buffer_start, len - l1);
85     }
86     if (sec_ret != EOK) {
87         return;
88     }
89 }
90 
log_buffer_get_used(const log_buffer_reader_control_t * lmscontrol,uint32_t read_i,uint32_t write_i)91 static uint32_t log_buffer_get_used(const log_buffer_reader_control_t *lmscontrol, uint32_t read_i, uint32_t write_i)
92 {
93     uint32_t in_use;
94     /* Check how much space is available. Use -1 to ensure the log_section_control->write ==
95      * log_section_control->read means the buffer is EMPTY.
96      * Without the -1, the log_section_control->write COULD wrap and catch up with log_section_control->read. */
97     if (read_i <= write_i) {
98         in_use = write_i - read_i;
99     } else {
100         /* log_section_control->write has wrapped, but log_section_control->read has not yet. */
101         in_use = (lmscontrol->log_buffer_size - read_i) + write_i;
102     }
103     return in_use;
104 }
105 
log_buffer_reader_get_msg_header(log_memory_region_section_t lmsec,const log_buffer_header_t * lb_header,uint32_t m_index)106 static log_reader_ret_t log_buffer_reader_get_msg_header(log_memory_region_section_t lmsec,
107                                                          const log_buffer_header_t *lb_header, uint32_t m_index)
108 {
109     const log_buffer_reader_control_t *lmsec_reader_control = &g_buffer_reader_control[lmsec];
110     uint32_t in_use;
111     uint32_t l_write_i;
112 
113     if (lb_header == NULL) {
114         return LOG_READER_RET_ERROR_IN_PARAMS;
115     }
116 
117     // Get the write index and check if there is at least a header to read
118     l_write_i = g_section_control[lmsec]->write;
119     if (l_write_i >= g_buffer_reader_control[lmsec].log_buffer_size) {
120         return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
121     }
122 
123     in_use = log_buffer_get_used(lmsec_reader_control, m_index, l_write_i);  // data between the index and the write
124     if (in_use == 0) {
125         return LOG_READER_RET_THERE_IS_NO_NEXT_MESSAGE;
126     } else if (in_use < sizeof(log_buffer_header_t) || (in_use >= g_buffer_reader_control[lmsec].log_buffer_size)) {
127         return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
128     } else {
129         log_buffer_copy_consecutive(lmsec_reader_control, (uint8_t *)lb_header, m_index, sizeof(log_buffer_header_t));
130         return LOG_READER_RET_OK;
131     }
132 }
133 
134 /*
135  *  Public function definitions
136  */
log_buffer_reader_init(void)137 log_reader_ret_t log_buffer_reader_init(void)
138 {
139     log_memory_section_params_t ms_params;
140     log_reader_ret_t ret_val;
141 
142     // Initialize the control structures for the different regions
143     for (uint8_t lmsec = LOG_MEMORY_REGION_SECTION_0; lmsec < LOG_MEMORY_REGION_MAX_NUMBER; lmsec++) {
144         uint32_t l_read_i;
145         log_memory_section_get((log_memory_region_section_t)lmsec, &ms_params);
146         g_section_control[lmsec] = log_memory_section_get_control((log_memory_region_section_t)lmsec);
147 
148         if (!pointer_in_log_memory_region((uintptr_t)ms_params.start)) {
149             panic(PANIC_LOG, __LINE__);
150             return LOG_READER_RET_ERROR_OVERFLOW_ON_DISCARDING;
151         }
152         if (!pointer_in_log_memory_region((uintptr_t)ms_params.start + ms_params.length - 1)) {
153             panic(PANIC_LOG, __LINE__);
154             return LOG_READER_RET_ERROR_OVERFLOW_ON_DISCARDING;
155         }
156 
157         if (!pointer_in_log_memory_region((uintptr_t)ms_params.start) ||
158             !pointer_in_log_memory_region((uint32_t)((uintptr_t)ms_params.start) + ms_params.length - 1)) {
159             return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
160         }
161 
162         g_buffer_reader_control[lmsec].log_buffer_start = ms_params.start;  // first element
163         g_buffer_reader_control[lmsec].log_buffer_size = ms_params.length;  // buffer size
164 
165         l_read_i = g_section_control[lmsec]->read;
166 
167         if (l_read_i >= g_buffer_reader_control[lmsec].log_buffer_size) {
168             return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
169         }
170 
171         g_buffer_reader_control[lmsec].lb_next_to_consume = l_read_i;
172         ret_val = LOG_READER_RET_OK;
173     }
174     return ret_val;
175 }
176 
log_buffer_reader_lock_next(log_memory_region_section_t * lmsec,const log_buffer_header_t * lb_header)177 log_reader_ret_t log_buffer_reader_lock_next(log_memory_region_section_t *lmsec, const log_buffer_header_t *lb_header)
178 {
179     log_reader_ret_t helper_log_ret;
180 
181     // when the log buffer is full,"read" is modified by unknown,so Synchronize to the "consume".
182     for (uint8_t i_lmsec = LOG_MEMORY_REGION_SECTION_0; i_lmsec < LOG_MEMORY_REGION_MAX_NUMBER; i_lmsec++) {
183         uint32_t read = g_section_control[i_lmsec]->read;
184         if (g_buffer_reader_control[i_lmsec].lb_next_to_consume != read) {
185             g_buffer_reader_control[i_lmsec].lb_next_to_consume = g_section_control[i_lmsec]->read;
186         }
187     }
188 
189     *lmsec = LOG_MEMORY_REGION_MAX_NUMBER;
190 
191     for (uint8_t i_lmsec = LOG_MEMORY_REGION_SECTION_0; i_lmsec < LOG_MEMORY_REGION_MAX_NUMBER; i_lmsec++) {
192         helper_log_ret = log_buffer_reader_get_msg_header((log_memory_region_section_t)i_lmsec, lb_header,
193                                                           g_buffer_reader_control[i_lmsec].lb_next_to_consume);
194         if (helper_log_ret == LOG_READER_RET_OK) {
195             *lmsec = i_lmsec;
196             break;
197         }
198     }
199 
200 #if CORE_NUMS > 1
201     log_buffer_header_t c_lb_header = { 0 };  // candidate header
202     if (*lmsec < (LOG_MEMORY_REGION_MAX_NUMBER - 1)) {
203         errno_t sec_ret;
204         // There is already one candidate
205         for (uint32_t i_lmsec = ((uint32_t)*lmsec + 1); i_lmsec < LOG_MEMORY_REGION_MAX_NUMBER; i_lmsec++) {
206             helper_log_ret = log_buffer_reader_get_msg_header((log_memory_region_section_t)i_lmsec, &c_lb_header,
207                                                               g_buffer_reader_control[i_lmsec].lb_next_to_consume);
208             if (helper_log_ret != LOG_READER_RET_OK) {
209                 continue;
210             }
211             if ((lb_header->time_us - c_lb_header.time_us) == 0) {
212                 continue;
213             }
214             sec_ret = memcpy_s((void *)lb_header, sizeof(log_buffer_header_t),
215                                (const void *)&c_lb_header, sizeof(log_buffer_header_t));
216             if (sec_ret != EOK) {
217                 return LOG_READER_RET_ERROR;
218             }
219             *lmsec = i_lmsec;
220         }
221     }
222 #endif
223     if (*lmsec == LOG_MEMORY_REGION_MAX_NUMBER) {
224         // no new messages found
225         return LOG_READER_RET_THERE_IS_NO_NEXT_MESSAGE;
226     }
227     return LOG_READER_RET_OK;
228 }
229 
log_buffer_get_used_space(log_memory_region_section_t lmsec,uint32_t * used_space)230 log_reader_ret_t log_buffer_get_used_space(log_memory_region_section_t lmsec, uint32_t *used_space)
231 {
232     log_reader_ret_t ret_value;
233     uint32_t l_write_i;
234     const log_buffer_reader_control_t *lmsec_reader_control;
235 
236     ret_value = LOG_READER_RET_OK;
237 
238     lmsec_reader_control = &g_buffer_reader_control[lmsec];
239 
240     l_write_i = g_section_control[lmsec]->write;
241     if (l_write_i >= g_buffer_reader_control[lmsec].log_buffer_size) {
242         return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
243     }
244     *used_space = log_buffer_get_used(lmsec_reader_control,
245                                       lmsec_reader_control->lb_next_to_consume,
246                                       l_write_i);  // data between the index and the write
247 
248     return ret_value;
249 }
250 
log_buffer_reader_claim_next(log_memory_region_section_t lmsec,uint8_t ** r1,uint32_t * len1,uint8_t ** r2,uint32_t * len2)251 log_reader_ret_t log_buffer_reader_claim_next(log_memory_region_section_t lmsec, uint8_t **r1,
252                                               uint32_t *len1, uint8_t **r2, uint32_t *len2)
253 {
254     uint32_t ret_r1;
255     log_buffer_header_t lb_header = { 0 };
256     const log_buffer_reader_control_t *lmsec_reader_control = &g_buffer_reader_control[lmsec];
257     log_reader_ret_t ret_value;
258     uint32_t l_write_i;
259     uint32_t new_next_to_consume;
260 
261     // Get the next message header
262     ret_value = log_buffer_reader_get_msg_header(lmsec, &lb_header, lmsec_reader_control->lb_next_to_consume);
263     if (ret_value == LOG_READER_RET_OK) {
264         if (lb_header.length <= sizeof(log_buffer_header_t)) {
265             uapi_diag_error_log(0, "[log_reader][header]length error, len = 0x%x", lb_header.length);
266             return LOG_READER_RET_ERROR;
267         }
268         // Get the buffer pointers
269         ret_r1 = circled_index(lmsec_reader_control,
270                                lmsec_reader_control->lb_next_to_consume + sizeof(log_buffer_header_t));
271         if (ret_r1 + (lb_header.length - sizeof(log_buffer_header_t)) <= lmsec_reader_control->log_buffer_size) {
272             /* 'Normal' case */
273             *r1 = lmsec_reader_control->log_buffer_start + ret_r1;
274             *len1 = lb_header.length - (uint32_t)sizeof(log_buffer_header_t);
275             *r2 = NULL;
276             *len2 = 0;
277         } else {
278             /* message divided at the end of the buffer case */
279             *r1 = lmsec_reader_control->log_buffer_start + ret_r1;
280             *len1 = lmsec_reader_control->log_buffer_size - ret_r1;
281             *r2 = lmsec_reader_control->log_buffer_start;
282             *len2 = (lb_header.length - (uint32_t)sizeof(log_buffer_header_t)) - *len1;
283         }
284         if ((*len1 > lmsec_reader_control->log_buffer_size) || (*len2 > lmsec_reader_control->log_buffer_size)) {
285             uapi_diag_error_log(0, "[log_reader][data]length error, len1 = 0x%x, len2 = 0x%x", *len1, *len2);
286             return LOG_READER_RET_ERROR_OVERFLOW_ON_DISCARDING;
287         }
288 
289         // Assert if log_section_control->read tries to overflow lb_next_to_consume
290         l_write_i = g_section_control[lmsec]->write;
291         new_next_to_consume = circled_index(lmsec_reader_control,
292                                             lmsec_reader_control->lb_next_to_consume + lb_header.length);
293         // equivalent to:  if (write > next_to_consume) {
294         if (((lmsec_reader_control->lb_next_to_consume >= l_write_i) ||
295              ((new_next_to_consume <= l_write_i) ||
296               (new_next_to_consume > lmsec_reader_control->lb_next_to_consume))) &&
297             ((lmsec_reader_control->lb_next_to_consume <= l_write_i) ||
298              ((new_next_to_consume <= lmsec_reader_control->lb_next_to_consume) ||
299               (new_next_to_consume > l_write_i)))) {
300             // Move the lb_next_to_consume data
301             log_buffer_reader_control_t *writable_lmsec_reader_control = &g_buffer_reader_control[lmsec];
302             writable_lmsec_reader_control->lb_next_to_consume = new_next_to_consume;
303             ret_value = LOG_READER_RET_OK;
304         } else {
305             uapi_diag_error_log(0, "[log_reader][pointer]write_p=0x%x, read_p=0x%x, new_read_p=0x%x\r\n", l_write_i,
306                 lmsec_reader_control->lb_next_to_consume, new_next_to_consume);
307             ret_value = LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
308         }
309     }
310 
311     return ret_value;
312 }
313 
log_buffer_reader_discard(log_memory_region_section_t lmsec)314 log_reader_ret_t log_buffer_reader_discard(log_memory_region_section_t lmsec)
315 {
316     log_buffer_header_t lb_header;
317     const log_buffer_reader_control_t *lmscontrol = &g_buffer_reader_control[lmsec];
318     log_reader_ret_t ret_value;
319     uint32_t l_read_i;
320     uint32_t new_lb_read;
321 
322     if (lmsec >= LOG_MEMORY_REGION_MAX_NUMBER) {
323         return LOG_READER_RET_ERROR_IN_PARAMS;
324     }
325 
326     memset_s((void *)&lb_header, sizeof(log_buffer_header_t), 0, sizeof(log_buffer_header_t));
327 
328     // Get last read pointer message header message header
329     l_read_i = g_section_control[lmsec]->read;
330     ret_value = log_buffer_reader_get_msg_header(lmsec, &lb_header, l_read_i);
331     if (ret_value == LOG_READER_RET_OK) {
332         new_lb_read = circled_index(lmscontrol, l_read_i + lb_header.length);
333         if (((lmscontrol->lb_next_to_consume <= l_read_i) ||
334              ((new_lb_read <= lmscontrol->lb_next_to_consume) &&
335               (new_lb_read > l_read_i))) &&
336             ((lmscontrol->lb_next_to_consume >= l_read_i) ||
337              ((new_lb_read <= lmscontrol->lb_next_to_consume) ||
338               (new_lb_read > l_read_i))) &&
339             (new_lb_read < lmscontrol->log_buffer_size)) {
340             g_section_control[lmsec]->read = new_lb_read;
341         } else {
342             return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;  // Trying to overflow
343         }
344     }
345 
346     return LOG_READER_RET_OK;
347 }
348 
log_buffer_reader_error_recovery(log_memory_region_section_t lmsec)349 void log_buffer_reader_error_recovery(log_memory_region_section_t lmsec)
350 {
351     g_section_control[lmsec]->read = g_section_control[lmsec]->write;
352 }