@@ -831,33 +831,11 @@ int TDBStore::garbage_collection()
831
831
int ret;
832
832
size_t ind;
833
833
834
- ret = check_erase_before_write (1 - _active_area, 0 , _master_record_offset + _master_record_size );
834
+ ret = reset_area (1 - _active_area);
835
835
if (ret) {
836
836
return ret;
837
837
}
838
838
839
- ret = do_reserved_data_get (0 , RESERVED_AREA_SIZE);
840
-
841
- if (!ret) {
842
- // Copy reserved data
843
- to_offset = 0 ;
844
- reserved_size = _master_record_offset;
845
-
846
- while (reserved_size) {
847
- chunk_size = std::min (work_buf_size, reserved_size);
848
- ret = read_area (_active_area, to_offset, chunk_size, _work_buf);
849
- if (ret) {
850
- return ret;
851
- }
852
- ret = write_area (1 - _active_area, to_offset, chunk_size, _work_buf);
853
- if (ret) {
854
- return ret;
855
- }
856
- to_offset += chunk_size;
857
- reserved_size -= chunk_size;
858
- }
859
- }
860
-
861
839
to_offset = _master_record_offset + _master_record_size;
862
840
863
841
// Initialize in case table is empty
@@ -1059,7 +1037,7 @@ int TDBStore::init()
1059
1037
// Master record may be either corrupt or erased - either way erase it
1060
1038
// (this will do nothing if already erased)
1061
1039
if (ret == MBED_ERROR_INVALID_DATA_DETECTED) {
1062
- if (check_erase_before_write (area, _master_record_offset, _master_record_size, true )) {
1040
+ if (reset_area (area)) {
1063
1041
MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to reset area at init" );
1064
1042
}
1065
1043
area_state[area] = TDBSTORE_AREA_STATE_EMPTY;
@@ -1124,11 +1102,9 @@ int TDBStore::init()
1124
1102
}
1125
1103
}
1126
1104
1127
- reserved_ret = do_reserved_data_get (0 , RESERVED_AREA_SIZE);
1128
-
1129
- // If we either have a corrupt record somewhere, or the reserved area is corrupt,
1130
- // perform garbage collection to salvage all preceding records and/or clean reserved area.
1131
- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED) || (reserved_ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
1105
+ // If we either have a corrupt record somewhere
1106
+ // perform garbage collection to salvage all preceding records.
1107
+ if ((ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
1132
1108
ret = garbage_collection ();
1133
1109
if (ret) {
1134
1110
MBED_ERROR (ret, " TDBSTORE: Unable to perform GC at init" );
@@ -1179,8 +1155,19 @@ int TDBStore::deinit()
1179
1155
1180
1156
int TDBStore::reset_area (uint8_t area)
1181
1157
{
1158
+ uint8_t buf[RESERVED_AREA_SIZE + sizeof (reserved_trailer_t )];
1159
+ int ret;
1160
+ bool copy_reserved_data = do_reserved_data_get (buf, sizeof (buf), 0 , buf + RESERVED_AREA_SIZE) == MBED_SUCCESS;
1161
+
1182
1162
// Erase reserved area and master record
1183
- return check_erase_before_write (area, 0 , _master_record_offset + _master_record_size, true );
1163
+ ret = check_erase_before_write (area, 0 , _master_record_offset + _master_record_size, true );
1164
+ if (ret) {
1165
+ return ret;
1166
+ }
1167
+ if (copy_reserved_data) {
1168
+ ret = write_area (area, 0 , sizeof (buf), buf);
1169
+ }
1170
+ return ret;
1184
1171
}
1185
1172
1186
1173
int TDBStore::reset ()
@@ -1196,7 +1183,7 @@ int TDBStore::reset()
1196
1183
1197
1184
// Reset both areas
1198
1185
for (area = 0 ; area < _num_areas; area++) {
1199
- ret = reset_area (area);
1186
+ ret = check_erase_before_write (area, 0 , _master_record_offset + _master_record_size, true );
1200
1187
if (ret) {
1201
1188
goto end;
1202
1189
}
@@ -1343,116 +1330,97 @@ void TDBStore::update_all_iterators(bool added, uint32_t ram_table_ind)
1343
1330
int TDBStore::reserved_data_set (const void *reserved_data, size_t reserved_data_buf_size)
1344
1331
{
1345
1332
reserved_trailer_t trailer;
1346
- int os_ret, ret = MBED_SUCCESS ;
1333
+ int ret;
1347
1334
1348
1335
if (reserved_data_buf_size > RESERVED_AREA_SIZE) {
1349
1336
return MBED_ERROR_INVALID_SIZE;
1350
1337
}
1351
1338
1352
1339
_mutex.lock ();
1353
1340
1354
- ret = do_reserved_data_get (0 , RESERVED_AREA_SIZE );
1355
- if (( ret == MBED_SUCCESS) || (ret == MBED_ERROR_INVALID_DATA_DETECTED) ) {
1341
+ ret = do_reserved_data_get (0 , 0 );
1342
+ if (ret == MBED_SUCCESS) {
1356
1343
ret = MBED_ERROR_WRITE_FAILED;
1357
1344
goto end;
1358
- } else if (ret != MBED_ERROR_ITEM_NOT_FOUND) {
1359
- goto end;
1360
- }
1361
-
1362
- ret = write_area (_active_area, 0 , reserved_data_buf_size, reserved_data);
1363
- if (ret) {
1364
- goto end;
1365
1345
}
1366
1346
1367
1347
trailer.trailer_size = sizeof (trailer);
1368
1348
trailer.data_size = reserved_data_buf_size;
1369
1349
trailer.crc = calc_crc (initial_crc, reserved_data_buf_size, reserved_data);
1370
1350
1371
- ret = write_area (_active_area, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1372
- if (ret) {
1373
- goto end;
1374
- }
1375
-
1376
- os_ret = _buff_bd->sync ();
1377
- if (os_ret) {
1378
- ret = MBED_ERROR_WRITE_FAILED;
1379
- goto end;
1351
+ /*
1352
+ * Write to both areas
1353
+ * Both must success, as they are required to be erased when TDBStore initializes
1354
+ * its area
1355
+ */
1356
+ for (int i = 0 ; i < _num_areas; ++i) {
1357
+ ret = write_area (i, 0 , reserved_data_buf_size, reserved_data);
1358
+ if (ret) {
1359
+ goto end;
1360
+ }
1361
+ ret = write_area (i, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1362
+ if (ret) {
1363
+ goto end;
1364
+ }
1365
+ ret = _buff_bd->sync ();
1366
+ if (ret) {
1367
+ goto end;
1368
+ }
1380
1369
}
1381
-
1370
+ ret = MBED_SUCCESS;
1382
1371
end:
1383
1372
_mutex.unlock ();
1384
1373
return ret;
1385
1374
}
1386
1375
1387
- int TDBStore::do_reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size)
1376
+ int TDBStore::do_reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size, void *copy_trailer )
1388
1377
{
1389
1378
reserved_trailer_t trailer;
1390
- uint8_t * buf;
1379
+ uint8_t buf[RESERVED_AREA_SIZE] ;
1391
1380
int ret;
1392
- bool erased = true ;
1393
- size_t actual_size;
1394
- uint32_t crc = initial_crc;
1395
- uint32_t offset;
1396
- uint8_t blank = _buff_bd->get_erase_value ();
1397
-
1398
- ret = read_area (_active_area, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1399
- if (ret) {
1400
- return ret;
1401
- }
1381
+ uint32_t crc;
1402
1382
1403
- buf = reinterpret_cast <uint8_t *>(&trailer);
1404
- for (uint32_t i = 0 ; i < sizeof (trailer); i++) {
1405
- if (buf[i] != blank) {
1406
- erased = false ;
1407
- break ;
1383
+ /*
1384
+ * Try to keep reserved data identical on both areas, therefore
1385
+ * we can return any of these data, if the checmsum is correct.
1386
+ */
1387
+ for (int i = 0 ; i < _num_areas; ++i) {
1388
+ ret = read_area (i, RESERVED_AREA_SIZE, sizeof (trailer), &trailer);
1389
+ if (ret) {
1390
+ return ret;
1408
1391
}
1409
- }
1410
1392
1411
- if (!erased) {
1412
- actual_size = trailer.data_size ;
1413
- if (actual_data_size) {
1414
- *actual_data_size = actual_size;
1393
+ // First validy check: is the trailer header size correct
1394
+ if (trailer.trailer_size != sizeof (trailer)) {
1395
+ continue ;
1415
1396
}
1416
- if (reserved_data_buf_size < actual_size) {
1417
- return MBED_ERROR_INVALID_SIZE;
1397
+ // Second validy check: Is the data too big (corrupt header)
1398
+ if (trailer.data_size > RESERVED_AREA_SIZE) {
1399
+ continue ;
1418
1400
}
1419
- } else {
1420
- actual_size = std::min ((size_t ) RESERVED_AREA_SIZE, reserved_data_buf_size);
1421
- }
1422
-
1423
- if (reserved_data) {
1424
- buf = reinterpret_cast <uint8_t *>(reserved_data);
1425
- } else {
1426
- buf = _work_buf;
1427
- }
1428
-
1429
- offset = 0 ;
1430
1401
1431
- while (actual_size) {
1432
- uint32_t chunk = std::min (work_buf_size, (uint32_t ) actual_size);
1433
- ret = read_area (_active_area, offset, chunk, buf + offset);
1402
+ // Next, verify the checksum
1403
+ ret = read_area (i, 0 , trailer.data_size , buf);
1434
1404
if (ret) {
1435
1405
return ret;
1436
1406
}
1437
- for (uint32_t i = 0 ; i < chunk; i++) {
1438
- if (buf[i] != blank) {
1439
- erased = false ;
1440
- break ;
1407
+ crc = calc_crc (initial_crc, trailer.data_size , buf);
1408
+ if (crc == trailer.crc ) {
1409
+ // Correct data, copy it and return to caller
1410
+ if (reserved_data) {
1411
+ memcpy (reserved_data, buf, trailer.data_size );
1441
1412
}
1413
+ if (actual_data_size) {
1414
+ *actual_data_size = trailer.data_size ;
1415
+ }
1416
+ if (copy_trailer) {
1417
+ memcpy (copy_trailer, &trailer, sizeof (trailer));
1418
+ }
1419
+ return MBED_SUCCESS;
1442
1420
}
1443
-
1444
- crc = calc_crc (crc, chunk, buf + offset);
1445
- offset += chunk;
1446
- actual_size -= chunk;
1447
1421
}
1448
1422
1449
- if (erased) {
1450
- return MBED_ERROR_ITEM_NOT_FOUND;
1451
- } else if (crc != trailer.crc ) {
1452
- return MBED_ERROR_INVALID_DATA_DETECTED;
1453
- }
1454
-
1455
- return MBED_SUCCESS;
1423
+ return MBED_ERROR_ITEM_NOT_FOUND;
1456
1424
}
1457
1425
1458
1426
int TDBStore::reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size)
0 commit comments