common_library: gettid is multiple declaration in cl_error
[staging/basesystem.git] / video_in_hal / systemservice / rom_access_library / library / nor / src / nor_backup.c
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*******************************************************************************
18 * $Header::                                                                   $
19 * $Revision::                                                                 $
20 *******************************************************************************/
21
22 /*******************************************************************************
23 @file        mtd_backup.c
24 @system
25 @process
26 @detail
27  ******************************************************************************/
28 #include "system_service/nor_backup.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <pthread.h>
37 #include <asm/unistd.h>
38 #include <mtd/mtd-user.h>
39
40 #define BACKUP_RETRY_CNT    3
41
42 /* Invalid Value */
43 #define FLSBACKUP_SEMAPHORE_INVALID    (0)
44
45
46 #define BACKUP_SECTOR_SIZ        1024                    // Secter Size
47
48 #define BACKUP_CHECK_OFFSET    16
49 #define BACKUP_CHECK_SIZE        12
50 #define BACKUP_CHECK_TEXT        "MTD_BACKUPDT"
51 #define BACKUP_CHECK_DAT1        1    // Lower 8bit
52 #define BACKUP_CHECK_DAT2        2    // Upper 8bit
53
54 #define NOR_ERRLOG(fmt, args...) \
55   fprintf(stderr, "[ERR]%ld/%s/%d/= "fmt"\n", syscall(__NR_gettid), __func__, __LINE__, ##args)
56
57 static pthread_mutex_t    g_semid_flash = PTHREAD_MUTEX_INITIALIZER;       /* Semaphore ID of dram area access    */
58 static int    g_backup_init = FLSBACKUP_SEMAPHORE_INVALID;
59
60 typedef enum {
61   RET_WT_CHK_OK = 0,
62   RET_WT_ERR_OTHER,
63   RET_WT_DEV_ERR,
64 } NOR_WRITE_BLK_CHK;
65
66 typedef enum {
67   RET_RD_CHK_OK = 0,
68   RET_RD_ERR_OTHER,
69   RET_RD_DEV_ERR,
70   RET_RD_ERR_1 = -1,
71   RET_RD_ERR_2 = -2,
72   RET_RD_ERR_3 = -3,
73   RET_RD_ERR_4 = -4,
74 } NOR_READ_BLK_CHK;
75
76 typedef enum {
77   RET_CHK_OK = 0,
78   RET_CHK_TEXT_ERR,
79   RET_CHK_BCC_ERR,
80 } NOR_BLK_CHK;
81
82 typedef enum {
83   NOR_IDLE = 0,        // 0:Read-out of block data
84   NOR_ORG_TEXT,        // 1:OrgText Error
85   NOR_ORG_BCC,        // 2:OrgBcc error
86   NOR_READ_OK,        // 3:Normal read-out
87   NOR_READ_END        // 4:end state
88 } NOR_R_STATE;
89
90 typedef enum {
91   NOR_IDEL = 0,            // 0:IDEL
92   NOR_READ_ERR,            // 1:Read Error
93   NOR_ORG_READ,            // 2:Org Read OK
94   NOR_BAK_WRT,            // 3:Bak Write OK
95   NOR_BACK_READ,            // 4:Bak Read OK
96   NOR_ORG_WRITE,            // 5:Org Write OK
97   NOR_WRITE_END            // 6:end state
98 } NOR_W_STATE;
99
100 NOR_READ_BLK_CHK MtdnBackupReadSub(
101     const char * path_name, int i_id, int i_offset, int i_size,
102     void *p_buff, mtd_info_t * mtd_info, int * get_state);
103 NOR_WRITE_BLK_CHK MtdnBackupWriteSub(
104     const char * path_name, int i_id, int i_offset, int i_size,
105     void *p_buff, mtd_info_t * mtd_info);
106
107 int MtdnBackupWriteBase(
108     const char * path_name, int i_id, int i_offset, int i_size,
109     void *p_buff, mtd_info_t * mtd_info);
110 int MtdnBackupReadBase(
111     const char * path_name, int i_id, int i_offset, int i_size,
112     void *p_buff, mtd_info_t * mtd_info);
113
114 int MtdBackupInfo(const char * path_name, mtd_info_t * mtd_info);        // INFO Get
115
116 NOR_BLK_CHK    MtdBackupCheksumRead(char * p_buff, int erase_size, int * ret_sum);            // check SUM
117 int    MtdBackupCheksumWrite(char * p_buff, int erase_size);            // check SUM
118
119 /***************************************************************************
120 @brief        mtdn_backup_Read
121 @outline        Read-out of specified block ID
122 @type        Completion return type
123 @param[in]    const char * path_name    : (/dev/mtd  Device)
124 @param[in]    int    i_id        : ID...0~
125 @param[in]    int    i_offset    :  ( i_offset >= 0)
126 @param[in]    int    i_size    :  ( i_size > 0)
127 @param[in]    void *p_buff    : (p_buff != NULL)
128 @return     int
129 @retval        0        : No error
130 @retval        Except    : Error
131 @usage        It is Backup API of data read.
132 *****************************************************************************/
133 int    mtdn_backup_Read(const char * path_name, int i_id, int i_offset, int i_size, void *p_buff ) {
134     int    ret_status = RET_DEV_NORMAL;
135
136     if (path_name == NULL) {
137         NOR_ERRLOG("invalid path:%p", path_name);
138         return  RET_DEV_ERR_PARAM;
139     }
140     if (p_buff == NULL) {
141         NOR_ERRLOG("invalid buf:%p", p_buff);
142         return  RET_DEV_ERR_PARAM;
143     }
144     if (i_id < 0) {
145         NOR_ERRLOG("invalid id:%d", i_id);
146         return  RET_DEV_ERR_PARAM;
147     }
148     if ((i_offset < 0) || (i_size <= 0)) {
149         NOR_ERRLOG("invalid size:%d offset:%d", i_size, i_offset);
150         return  RET_DEV_ERR_PARAM;
151     }
152     if (g_backup_init == FLSBACKUP_SEMAPHORE_INVALID) {  // LCOV_EXCL_BR_LINE 200: g_backup_init is static variable
153         pthread_mutex_init(&g_semid_flash, NULL);
154         g_backup_init = ~FLSBACKUP_SEMAPHORE_INVALID;
155     }
156     mtd_info_t mtd_info;
157     memset(&mtd_info, 0, sizeof(mtd_info_t));
158     ret_status = MtdBackupInfo((const char *)path_name, &mtd_info);
159     if (ret_status == RET_DEV_NORMAL) {
160         if (mtd_info.type != MTD_NORFLASH) {
161             NOR_ERRLOG("invalid type:%d", mtd_info.type);
162             ret_status = RET_DEV_ERR_PARAM;
163         } else {
164             if ((i_offset + i_size) > (int)(mtd_info.erasesize - BACKUP_CHECK_OFFSET)) {
165                 NOR_ERRLOG("invalid size:%d offset:%d erasesize:%d", i_size, i_offset, mtd_info.erasesize);
166                 ret_status = RET_DEV_ERR_PARAM;
167             }
168         }
169         if (ret_status == RET_DEV_NORMAL) {
170             /* Start Semaphore(flash)    */
171             pthread_mutex_lock(&g_semid_flash);
172             int get_state;    // Read status
173             ret_status = (int)MtdnBackupReadSub(path_name, i_id, i_offset, i_size,
174                                                              p_buff, &mtd_info, &get_state);
175
176             /* End Semaphore(flash)    */
177             pthread_mutex_unlock(&g_semid_flash);
178         }
179     }
180     if (ret_status != RET_DEV_NORMAL) {
181         NOR_ERRLOG("error return:%d", ret_status);
182     }
183     return    ret_status;
184 }
185
186 /***************************************************************************
187 @brief        mtdn_backup_Write
188 @outline        Writing of specified block ID
189 @type        Completion return type
190 @param[in]    const char * path_name    : (/dev/mtd  Device)
191 @param[in]    int    i_id        : ID...0~
192 @param[in]    int    i_offset    :  ( i_offset >= 0)
193 @param[in]    int    i_size    :  ( i_size > 0)
194 @param[in]    void *p_buff    : (p_buff != NULL)
195 @return     int
196 @retval        0    : No error
197 @retval        Except: Error
198 @usage        It is Backup API of data read.
199 *****************************************************************************/
200 int    mtdn_backup_Write(const char * path_name, int i_id, int i_offset, int i_size, void *p_buff) {
201     int    ret_status = RET_DEV_NORMAL;
202
203     if (path_name == NULL) {
204         NOR_ERRLOG("invalid path:%p", path_name);
205         return  RET_DEV_ERR_PARAM;
206     }
207     if (p_buff == NULL) {
208         NOR_ERRLOG("invalid buf:%p", p_buff);
209         return RET_DEV_ERR_PARAM;
210     }
211     if (i_id < 0) {
212         NOR_ERRLOG("invalid id:%d", i_id);
213         return RET_DEV_ERR_PARAM;
214     }
215     if ((i_offset < 0) || (i_size <= 0)) {
216         NOR_ERRLOG("invalid size:%d offset:%d", i_size, i_offset);
217         return RET_DEV_ERR_PARAM;
218     }
219     if (g_backup_init == FLSBACKUP_SEMAPHORE_INVALID) {
220         pthread_mutex_init(&g_semid_flash, NULL);
221         g_backup_init = ~FLSBACKUP_SEMAPHORE_INVALID;
222     }
223     mtd_info_t mtd_info;
224     memset(&mtd_info, 0, sizeof(mtd_info_t));
225     ret_status = MtdBackupInfo((const char *)path_name, &mtd_info);
226     if (ret_status == RET_DEV_NORMAL) {
227         if (mtd_info.type != MTD_NORFLASH) {
228             NOR_ERRLOG("invalid type:%d", mtd_info.type);
229             ret_status = RET_DEV_ERR_PARAM;
230         } else if (mtd_info.erasesize == 0) {
231             NOR_ERRLOG("invalid erasesize:%d", mtd_info.erasesize);
232             ret_status = RET_DEV_ERR_PARAM;
233         } else {
234             if ((i_offset + i_size) > (int)(mtd_info.erasesize - BACKUP_CHECK_OFFSET)) {
235                 NOR_ERRLOG("invalid size:%d offset:%d erasesize:%d", i_size, i_offset, mtd_info.erasesize);
236                 ret_status = RET_DEV_ERR_PARAM;
237             }
238         }
239         if (ret_status == RET_DEV_NORMAL) {
240             /* Start Semaphore(flash)    */
241             pthread_mutex_lock(&g_semid_flash);
242             ret_status = (int)MtdnBackupWriteSub(path_name, i_id, i_offset, i_size, p_buff, &mtd_info);
243
244             /* End Semaphore(flash)    */
245             pthread_mutex_unlock(&g_semid_flash);
246         }
247     }
248     if (ret_status != RET_DEV_NORMAL) {
249         NOR_ERRLOG("error return:%d", ret_status);
250     }
251     return    ret_status;
252 }
253
254 /***************************************************************************
255 @brief        MtdnBackupReadSub
256 @outline        Read-out of specified block ID
257 @type        Completion return type
258 @param[in]    const char * path_name    : (/dev/mtd  Device)
259 @param[in]    int    i_id        : ID...0~
260 @param[in]    int    i_offset    :  ( i_offset >= 0)
261 @param[in]    int    i_size    :  ( i_size > 0)
262 @param[in]    void *p_buff    : (p_buff != NULL)
263 @param[in]    mtd_info_t * mtd_info    : info
264 @param[in]    int * get_state    : 0:Rrg Normal 1:Bak Normal
265 @return     NOR_READ_BLK_CHK
266 @retval        RET_RD_CHK_OK    : No error
267 @retval        Except        : Error
268 @usage        It is Backup API of data read.
269 *****************************************************************************/
270 NOR_READ_BLK_CHK    MtdnBackupReadSub(const char * path_name, int i_id, int i_offset, int i_size,
271                                       void *p_buff, mtd_info_t * mtd_info, int * get_state) {
272     NOR_READ_BLK_CHK ret_status = RET_RD_CHK_OK;
273     char *    lp_buffer;
274
275     if (mtd_info->erasesize != 0) {  // LCOV_EXCL_BR_LINE 6: double check
276         lp_buffer = (char *)malloc(mtd_info->erasesize);
277         if (lp_buffer == NULL) {
278             NOR_ERRLOG("malloc:%p", lp_buffer);
279             ret_status = RET_RD_DEV_ERR;        // error
280         }
281     } else {
282         // LCOV_EXCL_START 8: dead code
283         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
284         NOR_ERRLOG("invalid erasesize:%d", mtd_info->erasesize);
285         ret_status = RET_RD_DEV_ERR;        // error
286         // LCOV_EXCL_STOP
287     }
288     if (ret_status == RET_RD_CHK_OK) {
289         memset(lp_buffer, 0x00, mtd_info->erasesize);
290         NOR_R_STATE        cycle_state = NOR_IDLE;
291         int        block_check_mode = 0;
292         int ret_sum = 0;
293         while ((cycle_state < NOR_READ_END)
294               &&(ret_status == RET_RD_CHK_OK)) {
295             switch (cycle_state) {
296             case NOR_IDLE:
297                 // Read-out of block data
298                 if (0 != MtdnBackupReadBase((const char *)path_name, i_id, 0,
299                                             (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
300                     ret_status = RET_RD_ERR_OTHER;        // Other abnormalities
301                 } else {
302                     NOR_BLK_CHK ret = MtdBackupCheksumRead(lp_buffer, (int)mtd_info->erasesize, (int *)&ret_sum);
303                     if (ret == RET_CHK_TEXT_ERR) {            // Text character sequence   Abnormalities
304                         cycle_state = NOR_ORG_TEXT;
305                     } else if (ret == RET_CHK_BCC_ERR) {    // (BCC)error
306                         cycle_state = NOR_ORG_BCC;
307                     } else {
308                         block_check_mode = 0;        // Org Normal
309                         cycle_state = NOR_READ_OK;
310                     }
311                 }
312                 break;
313             case NOR_ORG_TEXT:    // OrgText Error
314                 // Read-out of block data
315                 if (0 != MtdnBackupReadBase((const char *)path_name, (i_id+1), 0,
316                                             (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
317                     // other error
318                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
319                     ret_status = RET_RD_ERR_OTHER;    // LCOV_EXCL_LINE 5: c API error case.
320                 } else {
321                     NOR_BLK_CHK ret = MtdBackupCheksumRead(lp_buffer, (int)mtd_info->erasesize,
322                                                            (int *)&ret_sum);      // check SUM
323                     if (ret == RET_CHK_TEXT_ERR) {            // Text character sequence   Abnormalities
324                         ret_status = RET_RD_ERR_1;        // Uninitialized.
325                     } else if (ret == RET_CHK_BCC_ERR) {    // BCC error
326                         ret_status = RET_RD_ERR_2;        // write error
327                     }
328                     block_check_mode = 1;        // Bak Normal
329                     cycle_state = NOR_READ_OK;
330                 }
331                 break;
332             case NOR_ORG_BCC:    // OrgBcc error
333                 // Read-out of block data
334                 if (0 != MtdnBackupReadBase((const char *)path_name, (i_id+1), 0,
335                                             (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
336                     // other error
337                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
338                     ret_status = RET_RD_ERR_OTHER;    // LCOV_EXCL_LINE 5: c API error case.
339                 } else {
340                     NOR_BLK_CHK ret = MtdBackupCheksumRead(lp_buffer, (int)mtd_info->erasesize,
341                                                            (int *)&ret_sum);      // check SUM
342                     if (ret == RET_CHK_TEXT_ERR) {            // Text character sequence   Abnormalities
343                         ret_status = RET_RD_ERR_3;        // write error
344                     } else if (ret == RET_CHK_BCC_ERR) {    // BCC error
345                         ret_status = RET_RD_ERR_4;        // write error
346                     }
347                     block_check_mode = 1;        // Bak Normal
348                     cycle_state = NOR_READ_OK;
349                 }
350                 break;
351             case NOR_READ_OK:    // Normal read-out
352                 // The pickup of the read data
353                 memcpy(p_buff, &lp_buffer[i_offset], (size_t)i_size);
354                 cycle_state = NOR_READ_END;
355                 break;
356             default:
357                 // LCOV_EXCL_START 8: dead code
358                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
359                 NOR_ERRLOG("invalid state:%d", cycle_state);
360                 // other error
361                 ret_status = RET_RD_ERR_OTHER;
362                 break;
363                 // LCOV_EXCL_STOP
364             }
365         }
366         *get_state = block_check_mode;    // 0:OrgNormal 1:BakNormal
367         free(lp_buffer);
368     }
369     return    ret_status;        // Normal
370 }
371
372 static inline NOR_WRITE_BLK_CHK MtdnBackupWriteRetryCount(int *count, NOR_WRITE_BLK_CHK cur_state) {
373     NOR_WRITE_BLK_CHK ret_state = cur_state;
374     (*count)++;
375     if (*count > BACKUP_RETRY_CNT) {
376         NOR_ERRLOG("retry over!! state:%d count:%d", ret_state, *count);
377         ret_state = RET_WT_DEV_ERR;
378     }
379     return ret_state;
380 }
381
382 /***************************************************************************
383 @brief        MtdnBackupWriteSub
384 @outline        Writing of specified block ID
385 @type        Completion return type
386 @param[in]    const char * path_name    : (/dev/mtd  Device)
387 @param[in]    int    i_id        : ID...0~
388 @param[in]    int    i_offset    :  ( i_offset >= 0)
389 @param[in]    int    i_size    :  ( i_size > 0)
390 @param[in]    void *p_buff    : (p_buff != NULL)
391 @param[in]    mtd_info_t * mtd_info    : info
392 @return     NOR_WRITE_BLK_CHK
393 @retval        RET_WT_CHK_OK    : No error
394 @retval        Except    : Error
395 @usage        It is Backup API of data read.
396 *****************************************************************************/
397 NOR_WRITE_BLK_CHK    MtdnBackupWriteSub(const char * path_name, int i_id, int i_offset,
398                                         int i_size, void *p_buff, mtd_info_t * mtd_info) {
399     NOR_WRITE_BLK_CHK ret_status = RET_WT_CHK_OK;
400     char*    lp_buffer;
401
402     lp_buffer = (char *)malloc(mtd_info->erasesize);
403     if (lp_buffer == NULL) {
404         NOR_ERRLOG("malloc:%p", lp_buffer);
405         ret_status = RET_WT_DEV_ERR;        // error
406     } else {
407         memset(lp_buffer, 0x00, mtd_info->erasesize);
408         NOR_W_STATE    cycle_state = NOR_IDEL;
409         int    retry_cnt = 0;
410         int get_state = 0;    // Read status
411
412         while ((cycle_state < NOR_WRITE_END)
413               &&(ret_status == RET_WT_CHK_OK)) {
414             switch (cycle_state) {
415             case NOR_IDEL:    // IDLE
416                 if (RET_RD_CHK_OK != MtdnBackupReadSub((const char *)path_name, i_id, 0,
417                                                        (int)mtd_info->erasesize, lp_buffer, mtd_info, &get_state)) {
418                     cycle_state = NOR_READ_ERR;    // read error
419                 } else {
420                     // write data set
421                     memcpy(&lp_buffer[i_offset], p_buff, (size_t)i_size);
422                     if (get_state == 0) {
423                         cycle_state = NOR_ORG_READ;    // Org read Normal
424                     } else {
425                         // Bakread Normal
426                         cycle_state = NOR_BACK_READ;
427                     }
428                     // Embedding of write-in data
429                     memcpy(&lp_buffer[i_offset], p_buff, (size_t)i_size);
430                 }
431                 break;
432             case NOR_READ_ERR:    // read error
433                 memset((char *)lp_buffer, 0x00, mtd_info->erasesize);
434                 // Embedding of write-in data
435                 memcpy(&lp_buffer[i_offset], p_buff, (size_t)i_size);
436                 cycle_state = NOR_ORG_READ;    // Org read Normal
437                 break;
438             case NOR_ORG_READ:    // Orgread Normal
439                 // LCOV_EXCL_BR_START 6: double check
440                 if (0 != MtdBackupCheksumWrite(lp_buffer, (int)mtd_info->erasesize )) {            // check SUM
441                 // LCOV_EXCL_BR_STOP
442                     // error(It does not generate.)
443                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
444                     ret_status = RET_WT_DEV_ERR;    // LCOV_EXCL_LINE 8: dead code
445                 } else {
446                     // data write
447                     if (0 == MtdnBackupWriteBase((const char *)path_name, (i_id+1), 0,
448                                                  (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
449                         cycle_state = NOR_BAK_WRT;    // Bakwrite Success
450                         retry_cnt = 0;
451                     } else {
452                         ret_status = MtdnBackupWriteRetryCount(&retry_cnt, ret_status);
453                     }
454                 }
455                 break;
456             case NOR_BAK_WRT:    // BakWriteSuccess
457                 // Data write
458                 // LCOV_EXCL_BR_START 11:unexpected branch
459                 if (0 == MtdnBackupWriteBase((const char *)path_name, i_id, 0,
460                                              (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
461                 // LCOV_EXCL_BR_STOP
462                     cycle_state = NOR_WRITE_END;    // Normal end
463                 } else {
464                     // LCOV_EXCL_START 5: c API error case.
465                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
466                     ret_status = MtdnBackupWriteRetryCount(&retry_cnt, ret_status);
467                     // LCOV_EXCL_STOP
468                 }
469                 break;
470             case NOR_BACK_READ:    // Bak read normal
471                 // LCOV_EXCL_BR_START 6: double check
472                 if (0 != MtdBackupCheksumWrite(lp_buffer, (int)mtd_info->erasesize )) {            // check SUM
473                 // LCOV_EXCL_BR_STOP
474                     // Retry over
475                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
476                     ret_status = RET_WT_DEV_ERR;    // LCOV_EXCL_LINE 8: dead code
477                 } else {
478                     // data write
479                     if (0 == MtdnBackupWriteBase((const char *)path_name, i_id, 0,
480                                                  (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
481                         // Org write Succses
482                         cycle_state = NOR_ORG_WRITE;
483                         retry_cnt = 0;
484                     } else {
485                         // LCOV_EXCL_START 5: c API error case.
486                         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
487                         ret_status = MtdnBackupWriteRetryCount(&retry_cnt, ret_status);
488                         // LCOV_EXCL_STOP
489                     }
490                 }
491                 break;
492             case NOR_ORG_WRITE:    // Org write Succses
493                 // data write
494                 if (0 == MtdnBackupWriteBase((const char *)path_name, (i_id+1), 0,
495                                              (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
496                     // Normal end
497                     cycle_state = NOR_WRITE_END;
498                 } else {
499                     // LCOV_EXCL_START 5: c API error case.
500                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
501                     ret_status = MtdnBackupWriteRetryCount(&retry_cnt, ret_status);
502                     // LCOV_EXCL_STOP
503                 }
504                 break;
505             default:
506                 // LCOV_EXCL_START 8: dead code
507                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
508                 NOR_ERRLOG("invalid state:%d", cycle_state);
509                 // other error
510                 ret_status = RET_WT_ERR_OTHER;
511                 break;
512                 // LCOV_EXCL_STOP
513             }
514         }
515         free(lp_buffer);
516     }
517     return    ret_status;        // Normal
518 }
519
520 /***************************************************************************
521 @brief        MtdnBackupReadBase
522 @outline        Read-out of specified block ID
523 @type        Completion return type
524 @param[in]    const char * path_name    : (/dev/mtd  Device)
525 @param[in]    int    i_id        : ID...0~
526 @param[in]    int    i_offset    :  ( i_offset >= 0)
527 @param[in]    int    i_size    :  ( i_size > 0)
528 @param[in]    void *p_buff    : (p_buff != NULL)
529 @param[in]    mtd_info_t * mtd_info    :
530 @return     int
531 @retval        0    : No error
532 @retval        Except    : Error
533 @usage        It is Backup API of data read.
534 *****************************************************************************/
535 int    MtdnBackupReadBase(const char * path_name, int i_id, int i_offset,
536                           int i_size, void *p_buff, mtd_info_t * mtd_info) {
537     int ret_status = RET_DEV_NORMAL;
538
539     int mtd_fd = open(path_name, O_RDONLY|O_CLOEXEC);
540     // LCOV_EXCL_BR_START 5:It's impossible to mock open() function,so this line can not be passed.
541     if (mtd_fd == -1) {
542     // LCOV_EXCL_BR_STOP
543     // LCOV_EXCL_START 5:It's impossible to mock open() function,so this line can not be passed.
544     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
545         NOR_ERRLOG("open(%s):%s", path_name, strerror(errno));
546         ret_status = RET_DEV_ERROR;
547     // LCOV_EXCL_STOP
548     } else {
549         int seek_top = i_id * (int)mtd_info->erasesize + i_offset;
550         int sector_size = BACKUP_SECTOR_SIZ;
551         int block_size = (int)mtd_info->erasesize / sector_size;    // Division number
552         int llpi;
553         int    buff_top = 0;
554         int    get_size = i_size;
555         char * work_buff = (char *)p_buff;
556         ssize_t        read_size;
557
558         // It reads several sector minutes.
559         for (llpi=0; llpi < block_size; llpi++) {  // LCOV_EXCL_BR_LINE 11:unexpected branch
560             // It moves to a head.
561             if (-1 == (off_t)lseek(mtd_fd, seek_top, SEEK_SET)) {
562                 NOR_ERRLOG("lseek():%s", strerror(errno));
563                 ret_status = RET_DEV_ERROR;
564                 break;
565             }
566             if (get_size >= sector_size) {  // LCOV_EXCL_BR_LINE 6:double check
567                 read_size = read(mtd_fd, &work_buff[buff_top], (size_t)sector_size);
568                 if (read_size < 0) {
569                     NOR_ERRLOG("read():%zd %s", read_size, strerror(errno));
570                     ret_status = RET_DEV_ERROR;
571                     break;
572                 }
573
574                 get_size -= sector_size;
575                 if (get_size <= 0) {
576                     break;
577                 }
578             } else {
579             // LCOV_EXCL_START 8: dead code
580             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
581                 read_size = read(mtd_fd, &work_buff[buff_top], (size_t)get_size);
582                 if (read_size < 0) {
583                     NOR_ERRLOG("read():%zd %s", read_size, strerror(errno));
584                     ret_status = RET_DEV_ERROR;
585                     break;
586                 }
587                 break;
588             // LCOV_EXCL_STOP
589             }
590             seek_top += (int)read_size;
591             buff_top += (int)read_size;
592         }
593         // LCOV_EXCL_BR_START 5:It's impossible to mock close() function,so this line can not be passed.
594         if (0 != close(mtd_fd)) {
595         // LCOV_EXCL_BR_STOP
596             // LCOV_EXCL_START 5:It's impossible to mock close() function,so this line can not be passed.
597             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
598             NOR_ERRLOG("close():%s", strerror(errno));
599             ret_status = RET_DEV_ERROR;
600             // LCOV_EXCL_STOP
601         }
602     }
603     return    ret_status;
604 }
605
606 /***************************************************************************
607 @brief        MtdnBackupWriteBase
608 @outline        Writing of specified block ID
609 @type        Completion return type
610 @param[in]    const char * path_name    : (/dev/mtd  Device)
611 @param[in]    int    i_id        : ID...0~
612 @param[in]    int    i_offset    :  ( i_offset >= 0)
613 @param[in]    int    i_size    :  ( i_size > 0)
614 @param[in]    void *p_buff    : (p_buff != NULL)
615 @param[in]    mtd_info_t * mtd_info    :
616 @return     int
617 @retval        0    : No error
618 @retval        Except    : Error
619 @usage        It is Backup API of data read.
620 *****************************************************************************/
621 int    MtdnBackupWriteBase(const char * path_name, int i_id, int i_offset,
622                            int i_size, void *p_buff, mtd_info_t * mtd_info) {
623     int ret_status = RET_DEV_NORMAL;
624
625     int mtd_fd = open(path_name, O_RDWR|O_CLOEXEC);
626     if (mtd_fd == -1) {
627         NOR_ERRLOG("open(%s):%s", path_name, strerror(errno));
628         ret_status = RET_DEV_ERROR;
629     } else {
630         erase_info_t s_mtd_erase;
631         s_mtd_erase.start = (__u32)i_id * mtd_info->erasesize;
632         s_mtd_erase.length = mtd_info->erasesize;
633         // erase
634         if (ioctl(mtd_fd, MEMERASE, &s_mtd_erase) < 0) {
635             NOR_ERRLOG("ioctl(MEMERASE):%s", strerror(errno));
636             ret_status = RET_DEV_ERROR;
637         } else {
638             // write
639             int seek_top = i_id * (int)mtd_info->erasesize + i_offset;
640             int sector_size = BACKUP_SECTOR_SIZ;        //
641             int block_size = (int)mtd_info->erasesize/sector_size;
642             int llpi;
643             int    buff_top = 0;
644             int    put_size = i_size;
645             char * work_buff = (char *)p_buff;
646             ssize_t    write_size;
647
648             for (llpi=0; llpi < block_size; llpi++) {  // LCOV_EXCL_BR_LINE 11:unexpected branch
649                 if (-1 == (off_t)lseek(mtd_fd, seek_top, SEEK_SET)) {
650                     NOR_ERRLOG("lseek():%s", strerror(errno));
651                     ret_status = RET_DEV_ERROR;
652                     break;
653                 }
654                 if (put_size >= sector_size) {  // LCOV_EXCL_BR_LINE 6:double check
655                     write_size = write(mtd_fd, &work_buff[buff_top], (size_t)sector_size);
656                     if (write_size < 0) {
657                         NOR_ERRLOG("write():%zd %s", write_size, strerror(errno));
658                         ret_status = RET_DEV_ERROR;
659                         break;
660                     }
661                     put_size -= sector_size;
662                     if (put_size <= 0) {
663                         break;
664                     }
665                 } else {
666                 // LCOV_EXCL_START 8: dead code
667                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
668                     write_size = write(mtd_fd, &work_buff[buff_top], (size_t)put_size);
669                     if (write_size < 0) {
670                         NOR_ERRLOG("write():%zd %s", write_size, strerror(errno));
671                         ret_status = RET_DEV_ERROR;
672                         break;
673                     }
674                     break;
675                 // LCOV_EXCL_STOP
676                 }
677                 seek_top += (int)write_size;
678                 buff_top += (int)write_size;
679             }
680         }
681         // LCOV_EXCL_BR_START 5:It's impossible to mock close() function,so this line can not be passed.
682         if (0 != close(mtd_fd)) {
683         // LCOV_EXCL_BR_STOP
684             // LCOV_EXCL_START 5:It's impossible to mock close() function,so this line can not be passed.
685             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
686             NOR_ERRLOG("close():%s", strerror(errno));
687             ret_status = RET_DEV_ERROR;
688             // LCOV_EXCL_STOP
689         }
690     }
691     return    ret_status;
692 }
693
694 /***************************************************************************
695 int    backup_cheksum_read(char * p_buff, int erase_size ,int * ret_sum)
696  * A text character sequence and a sum value are checked.
697  IN:     char * p_buff        ...top address
698         int erase_size    ...erase size
699         int * ret_sum    ...return sum
700
701  OUT: NOR_BLK_CHK    RET_CHK_OK:Normal
702                     RET_CHK_TEXT_ERR:test error
703                     RET_CHK_BCC_ERR:sum error Except:other error
704  Remarks:
705 *****************************************************************************/
706 NOR_BLK_CHK    MtdBackupCheksumRead(char * p_buff, int erase_size, int * ret_sum) {
707     if (erase_size > BACKUP_CHECK_OFFSET) {  // LCOV_EXCL_BR_LINE 6: double check
708         // The check of the compatibility of block data
709         if (0 != memcmp(&p_buff[(erase_size-BACKUP_CHECK_OFFSET)], BACKUP_CHECK_TEXT, BACKUP_CHECK_SIZE)) {
710             char tmp[BACKUP_CHECK_SIZE + 1];
711             memcpy(tmp, &p_buff[(erase_size-BACKUP_CHECK_OFFSET)], BACKUP_CHECK_SIZE);
712             tmp[BACKUP_CHECK_SIZE] = '\0';
713             NOR_ERRLOG("invalid check_text:%s", tmp);
714             return    RET_CHK_TEXT_ERR;
715         }
716         // The check of the compatibility of block data
717         int llpi;
718         int get_sum;
719         int    work_sum = 0;
720         get_sum = ((int)p_buff[(erase_size-BACKUP_CHECK_DAT2)] & 0xff) +
721                     (((int)p_buff[(erase_size-BACKUP_CHECK_DAT1)]) << 8 & 0xff00);
722
723         for (llpi=0; llpi < (erase_size-BACKUP_CHECK_OFFSET); llpi++) {
724             work_sum += p_buff[llpi];
725         }
726         work_sum = (work_sum & 0xffff);
727         if (work_sum != get_sum) {
728             NOR_ERRLOG("invalid checksum: work:%d get:%d", work_sum, get_sum);
729             return    RET_CHK_BCC_ERR;        // checksum error
730         }
731         if (ret_sum != NULL) {  // LCOV_EXCL_BR_LINE 6: double check
732             *ret_sum = work_sum;    // chesum Storing
733         }
734     } else {
735     // LCOV_EXCL_START 8: dead code
736     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
737         NOR_ERRLOG("invalid erase_size:%d", erase_size);
738         // checksum error
739         return    RET_CHK_BCC_ERR;
740     // LCOV_EXCL_STOP
741     }
742     return    RET_CHK_OK;
743 }
744
745 /***************************************************************************
746 int    backup_cheksum_write(char * p_buff, int erase_size )
747  * A text character sequence and a sum value are written in a buffer.
748  IN:     char * p_buff        ...top address
749         int erase_size    ...erase size
750
751  OUT: int    0:normal Except:error
752  Remarks:
753 *****************************************************************************/
754 int    MtdBackupCheksumWrite(char * p_buff, int erase_size ) {
755     int    sum_add = 0;
756
757     if (erase_size > BACKUP_CHECK_OFFSET) {  // LCOV_EXCL_BR_LINE 11:unexpected branch
758         int ret_status;
759         // The check of the compatibility of block data
760         ret_status = memcmp(&p_buff[(erase_size-BACKUP_CHECK_OFFSET)], BACKUP_CHECK_TEXT, BACKUP_CHECK_SIZE);
761         if (ret_status != 0) {
762             memcpy(&p_buff[(erase_size-BACKUP_CHECK_OFFSET)], BACKUP_CHECK_TEXT, BACKUP_CHECK_SIZE);
763         }
764         int llpi;
765         for (llpi=0; llpi < (erase_size-BACKUP_CHECK_OFFSET); llpi++) {
766             sum_add += p_buff[llpi];
767         }
768     }
769     p_buff[(erase_size-BACKUP_CHECK_DAT2)] = (char)(sum_add     & 0xff);
770     p_buff[(erase_size-BACKUP_CHECK_DAT1)] = (char)((sum_add>>8) & 0xff);
771     return    RET_DEV_NORMAL;
772 }
773
774 /***************************************************************************
775 @brief        MtdBackupInfo( mtd_info_t * mtd_info)
776 @outline        The information to obtain is obtained.
777 @type        Completion return type
778 @param[in]    mtd_info_t * mtd_info
779 @return     int
780 @retval        0        : No error
781 @retval        Except    : Error
782 @usage        It is Backup API of data read.
783 *****************************************************************************/
784 int    MtdBackupInfo(const char * path_name, mtd_info_t * mtd_info) {
785     int         ret_status = RET_DEV_NORMAL;
786
787     int mtd_fd = open(path_name, O_RDONLY|O_CLOEXEC);
788     if (mtd_fd == -1) {
789         NOR_ERRLOG("open(%s):%s", path_name, strerror(errno));
790         ret_status = RET_DEV_ERROR;
791     } else {
792         // device control  mtdchar_ioctl of mtdchar.c
793         if (ioctl(mtd_fd, MEMGETINFO, mtd_info) < 0) {
794             NOR_ERRLOG("ioctl(MEMGETINFO):%s", strerror(errno));
795             ret_status = RET_DEV_ERROR;
796         }
797         if (0 != close(mtd_fd)) {
798             NOR_ERRLOG("close():%s", strerror(errno));
799             ret_status = RET_DEV_ERROR;
800         }
801     }
802     return    ret_status;
803 }
804
805 /**************************************************************
806   End Of Files
807 **************************************************************/