@@ -848,33 +848,11 @@ int TDBStore::garbage_collection()
848848 int ret;
849849 size_t ind;
850850
851- ret = check_erase_before_write (1 - _active_area, 0 , _master_record_offset + _master_record_size );
851+ ret = reset_area (1 - _active_area);
852852 if (ret) {
853853 return ret;
854854 }
855855
856- ret = do_reserved_data_get (0 , RESERVED_AREA_SIZE);
857-
858- if (!ret) {
859- // Copy reserved data
860- to_offset = 0 ;
861- reserved_size = _master_record_offset;
862-
863- while (reserved_size) {
864- chunk_size = std::min (work_buf_size, reserved_size);
865- ret = read_area (_active_area, to_offset, chunk_size, _work_buf);
866- if (ret) {
867- return ret;
868- }
869- ret = write_area (1 - _active_area, to_offset, chunk_size, _work_buf);
870- if (ret) {
871- return ret;
872- }
873- to_offset += chunk_size;
874- reserved_size -= chunk_size;
875- }
876- }
877-
878856 to_offset = _master_record_offset + _master_record_size;
879857
880858 // Initialize in case table is empty
@@ -1078,7 +1056,7 @@ int TDBStore::init()
10781056 // Master record may be either corrupt or erased - either way erase it
10791057 // (this will do nothing if already erased)
10801058 if (ret == MBED_ERROR_INVALID_DATA_DETECTED) {
1081- if (check_erase_before_write (area, _master_record_offset, _master_record_size, true )) {
1059+ if (reset_area (area)) {
10821060 MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to reset area at init" );
10831061 }
10841062 area_state[area] = TDBSTORE_AREA_STATE_EMPTY;
@@ -1143,11 +1121,9 @@ int TDBStore::init()
11431121 }
11441122 }
11451123
1146- reserved_ret = do_reserved_data_get (0 , RESERVED_AREA_SIZE);
1147-
1148- // If we either have a corrupt record somewhere, or the reserved area is corrupt,
1149- // perform garbage collection to salvage all preceding records and/or clean reserved area.
1150- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED) || (reserved_ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
1124+ // If we either have a corrupt record somewhere
1125+ // perform garbage collection to salvage all preceding records.
1126+ if ((ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
11511127 ret = garbage_collection ();
11521128 if (ret) {
11531129 MBED_ERROR (ret, " TDBSTORE: Unable to perform GC at init" );
@@ -1198,8 +1174,19 @@ int TDBStore::deinit()
11981174
11991175int TDBStore::reset_area (uint8_t area)
12001176{
1177+ uint8_t buf[RESERVED_AREA_SIZE + sizeof (reserved_trailer_t )];
1178+ int ret;
1179+ bool copy_reserved_data = do_reserved_data_get (buf, sizeof (buf), 0 , buf + RESERVED_AREA_SIZE) == MBED_SUCCESS;
1180+
12011181 // Erase reserved area and master record
1202- return check_erase_before_write (area, 0 , _master_record_offset + _master_record_size, true );
1182+ ret = check_erase_before_write (area, 0 , _master_record_offset + _master_record_size, true );
1183+ if (ret) {
1184+ return ret;
1185+ }
1186+ if (copy_reserved_data) {
1187+ ret = write_area (area, 0 , sizeof (buf), buf);
1188+ }
1189+ return ret;
12031190}
12041191
12051192int TDBStore::reset ()
@@ -1215,7 +1202,7 @@ int TDBStore::reset()
12151202
12161203 // Reset both areas
12171204 for (area = 0 ; area < _num_areas; area++) {
1218- ret = reset_area (area);
1205+ ret = check_erase_before_write (area, 0 , _master_record_offset + _master_record_size, true );
12191206 if (ret) {
12201207 goto end;
12211208 }
@@ -1362,116 +1349,97 @@ void TDBStore::update_all_iterators(bool added, uint32_t ram_table_ind)
13621349int TDBStore::reserved_data_set (const void *reserved_data, size_t reserved_data_buf_size)
13631350{
13641351 reserved_trailer_t trailer;
1365- int os_ret, ret = MBED_SUCCESS ;
1352+ int ret;
13661353
13671354 if (reserved_data_buf_size > RESERVED_AREA_SIZE) {
13681355 return MBED_ERROR_INVALID_SIZE;
13691356 }
13701357
13711358 _mutex.lock ();
13721359
1373- ret = do_reserved_data_get (0 , RESERVED_AREA_SIZE );
1374- if (( ret == MBED_SUCCESS) || (ret == MBED_ERROR_INVALID_DATA_DETECTED) ) {
1360+ ret = do_reserved_data_get (0 , 0 );
1361+ if (ret == MBED_SUCCESS) {
13751362 ret = MBED_ERROR_WRITE_FAILED;
13761363 goto end;
1377- } else if (ret != MBED_ERROR_ITEM_NOT_FOUND) {
1378- goto end;
1379- }
1380-
1381- ret = write_area (_active_area, 0 , reserved_data_buf_size, reserved_data);
1382- if (ret) {
1383- goto end;
13841364 }
13851365
13861366 trailer.trailer_size = sizeof (trailer);
13871367 trailer.data_size = reserved_data_buf_size;
13881368 trailer.crc = calc_crc (initial_crc, reserved_data_buf_size, reserved_data);
13891369
1390- ret = write_area (_active_area, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1391- if (ret) {
1392- goto end;
1393- }
1394-
1395- os_ret = _buff_bd->sync ();
1396- if (os_ret) {
1397- ret = MBED_ERROR_WRITE_FAILED;
1398- goto end;
1370+ /*
1371+ * Write to both areas
1372+ * Both must success, as they are required to be erased when TDBStore initializes
1373+ * its area
1374+ */
1375+ for (int i = 0 ; i < _num_areas; ++i) {
1376+ ret = write_area (i, 0 , reserved_data_buf_size, reserved_data);
1377+ if (ret) {
1378+ goto end;
1379+ }
1380+ ret = write_area (i, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1381+ if (ret) {
1382+ goto end;
1383+ }
1384+ ret = _buff_bd->sync ();
1385+ if (ret) {
1386+ goto end;
1387+ }
13991388 }
1400-
1389+ ret = MBED_SUCCESS;
14011390end:
14021391 _mutex.unlock ();
14031392 return ret;
14041393}
14051394
1406- int TDBStore::do_reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size)
1395+ int TDBStore::do_reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size, void *copy_trailer )
14071396{
14081397 reserved_trailer_t trailer;
1409- uint8_t * buf;
1398+ uint8_t buf[RESERVED_AREA_SIZE] ;
14101399 int ret;
1411- bool erased = true ;
1412- size_t actual_size;
1413- uint32_t crc = initial_crc;
1414- uint32_t offset;
1415- uint8_t blank = _buff_bd->get_erase_value ();
1416-
1417- ret = read_area (_active_area, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1418- if (ret) {
1419- return ret;
1420- }
1400+ uint32_t crc;
14211401
1422- buf = reinterpret_cast <uint8_t *>(&trailer);
1423- for (uint32_t i = 0 ; i < sizeof (trailer); i++) {
1424- if (buf[i] != blank) {
1425- erased = false ;
1426- break ;
1402+ /*
1403+ * Try to keep reserved data identical on both areas, therefore
1404+ * we can return any of these data, if the checmsum is correct.
1405+ */
1406+ for (int i = 0 ; i < _num_areas; ++i) {
1407+ ret = read_area (i, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1408+ if (ret) {
1409+ return ret;
14271410 }
1428- }
14291411
1430- if (!erased) {
1431- actual_size = trailer.data_size ;
1432- if (actual_data_size) {
1433- *actual_data_size = actual_size;
1412+ // First validy check: is the trailer header size correct
1413+ if (trailer.trailer_size != sizeof (trailer)) {
1414+ continue ;
14341415 }
1435- if (reserved_data_buf_size < actual_size) {
1436- return MBED_ERROR_INVALID_SIZE;
1416+ // Second validy check: Is the data too big (corrupt header)
1417+ if (trailer.data_size > RESERVED_AREA_SIZE) {
1418+ continue ;
14371419 }
1438- } else {
1439- actual_size = std::min ((size_t ) RESERVED_AREA_SIZE, reserved_data_buf_size);
1440- }
1441-
1442- if (reserved_data) {
1443- buf = reinterpret_cast <uint8_t *>(reserved_data);
1444- } else {
1445- buf = _work_buf;
1446- }
1447-
1448- offset = 0 ;
14491420
1450- while (actual_size) {
1451- uint32_t chunk = std::min (work_buf_size, (uint32_t ) actual_size);
1452- ret = read_area (_active_area, offset, chunk, buf + offset);
1421+ // Next, verify the checksum
1422+ ret = read_area (i, 0 , trailer.data_size , buf);
14531423 if (ret) {
14541424 return ret;
14551425 }
1456- for (uint32_t i = 0 ; i < chunk; i++) {
1457- if (buf[i] != blank) {
1458- erased = false ;
1459- break ;
1426+ crc = calc_crc (initial_crc, trailer.data_size , buf);
1427+ if (crc == trailer.crc ) {
1428+ // Correct data, copy it and return to caller
1429+ if (reserved_data) {
1430+ memcpy (reserved_data, buf, trailer.data_size );
14601431 }
1432+ if (actual_data_size) {
1433+ *actual_data_size = trailer.data_size ;
1434+ }
1435+ if (copy_trailer) {
1436+ memcpy (copy_trailer, &trailer, sizeof (trailer));
1437+ }
1438+ return MBED_SUCCESS;
14611439 }
1462-
1463- crc = calc_crc (crc, chunk, buf + offset);
1464- offset += chunk;
1465- actual_size -= chunk;
14661440 }
14671441
1468- if (erased) {
1469- return MBED_ERROR_ITEM_NOT_FOUND;
1470- } else if (crc != trailer.crc ) {
1471- return MBED_ERROR_INVALID_DATA_DETECTED;
1472- }
1473-
1474- return MBED_SUCCESS;
1442+ return MBED_ERROR_ITEM_NOT_FOUND;
14751443}
14761444
14771445int TDBStore::reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size)
0 commit comments