2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /*******************************************************************************
20 *******************************************************************************/
22 /*******************************************************************************
27 ******************************************************************************/
28 #include "system_service/nor_backup.h"
31 #include <sys/ioctl.h>
37 #include <asm/unistd.h>
38 #include <mtd/mtd-user.h>
40 #define BACKUP_RETRY_CNT 3
43 #define FLSBACKUP_SEMAPHORE_INVALID (0)
46 #define BACKUP_SECTOR_SIZ 1024 // Secter Size
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
54 #define NOR_ERRLOG(fmt, args...) \
55 fprintf(stderr, "[ERR]%ld/%s/%d/= "fmt"\n", syscall(__NR_gettid), __func__, __LINE__, ##args)
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;
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
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
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);
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);
114 int MtdBackupInfo(const char * path_name, mtd_info_t * mtd_info); // INFO Get
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
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)
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;
136 if (path_name == NULL) {
137 NOR_ERRLOG("invalid path:%p", path_name);
138 return RET_DEV_ERR_PARAM;
140 if (p_buff == NULL) {
141 NOR_ERRLOG("invalid buf:%p", p_buff);
142 return RET_DEV_ERR_PARAM;
145 NOR_ERRLOG("invalid id:%d", i_id);
146 return RET_DEV_ERR_PARAM;
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;
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;
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;
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;
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);
176 /* End Semaphore(flash) */
177 pthread_mutex_unlock(&g_semid_flash);
180 if (ret_status != RET_DEV_NORMAL) {
181 NOR_ERRLOG("error return:%d", ret_status);
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)
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;
203 if (path_name == NULL) {
204 NOR_ERRLOG("invalid path:%p", path_name);
205 return RET_DEV_ERR_PARAM;
207 if (p_buff == NULL) {
208 NOR_ERRLOG("invalid buf:%p", p_buff);
209 return RET_DEV_ERR_PARAM;
212 NOR_ERRLOG("invalid id:%d", i_id);
213 return RET_DEV_ERR_PARAM;
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;
219 if (g_backup_init == FLSBACKUP_SEMAPHORE_INVALID) {
220 pthread_mutex_init(&g_semid_flash, NULL);
221 g_backup_init = ~FLSBACKUP_SEMAPHORE_INVALID;
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;
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;
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);
244 /* End Semaphore(flash) */
245 pthread_mutex_unlock(&g_semid_flash);
248 if (ret_status != RET_DEV_NORMAL) {
249 NOR_ERRLOG("error return:%d", ret_status);
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;
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
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
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;
293 while ((cycle_state < NOR_READ_END)
294 &&(ret_status == RET_RD_CHK_OK)) {
295 switch (cycle_state) {
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
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;
308 block_check_mode = 0; // Org Normal
309 cycle_state = NOR_READ_OK;
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)) {
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.
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
328 block_check_mode = 1; // Bak Normal
329 cycle_state = NOR_READ_OK;
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)) {
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.
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
347 block_check_mode = 1; // Bak Normal
348 cycle_state = NOR_READ_OK;
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;
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);
361 ret_status = RET_RD_ERR_OTHER;
366 *get_state = block_check_mode; // 0:OrgNormal 1:BakNormal
369 return ret_status; // Normal
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;
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;
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;
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
407 memset(lp_buffer, 0x00, mtd_info->erasesize);
408 NOR_W_STATE cycle_state = NOR_IDEL;
410 int get_state = 0; // Read status
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
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
426 cycle_state = NOR_BACK_READ;
428 // Embedding of write-in data
429 memcpy(&lp_buffer[i_offset], p_buff, (size_t)i_size);
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
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
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
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
452 ret_status = MtdnBackupWriteRetryCount(&retry_cnt, ret_status);
456 case NOR_BAK_WRT: // BakWriteSuccess
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)) {
462 cycle_state = NOR_WRITE_END; // Normal end
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);
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
475 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
476 ret_status = RET_WT_DEV_ERR; // LCOV_EXCL_LINE 8: dead code
479 if (0 == MtdnBackupWriteBase((const char *)path_name, i_id, 0,
480 (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
482 cycle_state = NOR_ORG_WRITE;
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);
492 case NOR_ORG_WRITE: // Org write Succses
494 if (0 == MtdnBackupWriteBase((const char *)path_name, (i_id+1), 0,
495 (int)mtd_info->erasesize, lp_buffer, mtd_info)) {
497 cycle_state = NOR_WRITE_END;
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);
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);
510 ret_status = RET_WT_ERR_OTHER;
517 return ret_status; // Normal
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 :
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;
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.
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;
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
554 int get_size = i_size;
555 char * work_buff = (char *)p_buff;
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;
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);
569 NOR_ERRLOG("read():%zd %s", read_size, strerror(errno));
570 ret_status = RET_DEV_ERROR;
574 get_size -= sector_size;
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);
583 NOR_ERRLOG("read():%zd %s", read_size, strerror(errno));
584 ret_status = RET_DEV_ERROR;
590 seek_top += (int)read_size;
591 buff_top += (int)read_size;
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)) {
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;
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 :
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;
625 int mtd_fd = open(path_name, O_RDWR|O_CLOEXEC);
627 NOR_ERRLOG("open(%s):%s", path_name, strerror(errno));
628 ret_status = RET_DEV_ERROR;
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;
634 if (ioctl(mtd_fd, MEMERASE, &s_mtd_erase) < 0) {
635 NOR_ERRLOG("ioctl(MEMERASE):%s", strerror(errno));
636 ret_status = RET_DEV_ERROR;
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;
644 int put_size = i_size;
645 char * work_buff = (char *)p_buff;
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;
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;
661 put_size -= sector_size;
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;
677 seek_top += (int)write_size;
678 buff_top += (int)write_size;
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)) {
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;
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
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
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;
716 // The check of the compatibility of block data
720 get_sum = ((int)p_buff[(erase_size-BACKUP_CHECK_DAT2)] & 0xff) +
721 (((int)p_buff[(erase_size-BACKUP_CHECK_DAT1)]) << 8 & 0xff00);
723 for (llpi=0; llpi < (erase_size-BACKUP_CHECK_OFFSET); llpi++) {
724 work_sum += p_buff[llpi];
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
731 if (ret_sum != NULL) { // LCOV_EXCL_BR_LINE 6: double check
732 *ret_sum = work_sum; // chesum Storing
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);
739 return RET_CHK_BCC_ERR;
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
751 OUT: int 0:normal Except:error
753 *****************************************************************************/
754 int MtdBackupCheksumWrite(char * p_buff, int erase_size ) {
757 if (erase_size > BACKUP_CHECK_OFFSET) { // LCOV_EXCL_BR_LINE 11:unexpected branch
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);
765 for (llpi=0; llpi < (erase_size-BACKUP_CHECK_OFFSET); llpi++) {
766 sum_add += p_buff[llpi];
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;
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
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;
787 int mtd_fd = open(path_name, O_RDONLY|O_CLOEXEC);
789 NOR_ERRLOG("open(%s):%s", path_name, strerror(errno));
790 ret_status = RET_DEV_ERROR;
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;
797 if (0 != close(mtd_fd)) {
798 NOR_ERRLOG("close():%s", strerror(errno));
799 ret_status = RET_DEV_ERROR;
805 /**************************************************************
807 **************************************************************/