@@ -848,33 +848,11 @@ int TDBStore::garbage_collection()
848
848
int ret;
849
849
size_t ind;
850
850
851
- ret = check_erase_before_write (1 - _active_area, 0 , _master_record_offset + _master_record_size );
851
+ ret = reset_area (1 - _active_area);
852
852
if (ret) {
853
853
return ret;
854
854
}
855
855
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
-
878
856
to_offset = _master_record_offset + _master_record_size;
879
857
880
858
// Initialize in case table is empty
@@ -1078,7 +1056,7 @@ int TDBStore::init()
1078
1056
// Master record may be either corrupt or erased - either way erase it
1079
1057
// (this will do nothing if already erased)
1080
1058
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)) {
1082
1060
MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to reset area at init" );
1083
1061
}
1084
1062
area_state[area] = TDBSTORE_AREA_STATE_EMPTY;
@@ -1143,11 +1121,9 @@ int TDBStore::init()
1143
1121
}
1144
1122
}
1145
1123
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)) {
1151
1127
ret = garbage_collection ();
1152
1128
if (ret) {
1153
1129
MBED_ERROR (ret, " TDBSTORE: Unable to perform GC at init" );
@@ -1198,8 +1174,19 @@ int TDBStore::deinit()
1198
1174
1199
1175
int TDBStore::reset_area (uint8_t area)
1200
1176
{
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
+
1201
1181
// 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;
1203
1190
}
1204
1191
1205
1192
int TDBStore::reset ()
@@ -1215,7 +1202,7 @@ int TDBStore::reset()
1215
1202
1216
1203
// Reset both areas
1217
1204
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 );
1219
1206
if (ret) {
1220
1207
goto end;
1221
1208
}
@@ -1362,116 +1349,97 @@ void TDBStore::update_all_iterators(bool added, uint32_t ram_table_ind)
1362
1349
int TDBStore::reserved_data_set (const void *reserved_data, size_t reserved_data_buf_size)
1363
1350
{
1364
1351
reserved_trailer_t trailer;
1365
- int os_ret, ret = MBED_SUCCESS ;
1352
+ int ret;
1366
1353
1367
1354
if (reserved_data_buf_size > RESERVED_AREA_SIZE) {
1368
1355
return MBED_ERROR_INVALID_SIZE;
1369
1356
}
1370
1357
1371
1358
_mutex.lock ();
1372
1359
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) {
1375
1362
ret = MBED_ERROR_WRITE_FAILED;
1376
1363
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;
1384
1364
}
1385
1365
1386
1366
trailer.trailer_size = sizeof (trailer);
1387
1367
trailer.data_size = reserved_data_buf_size;
1388
1368
trailer.crc = calc_crc (initial_crc, reserved_data_buf_size, reserved_data);
1389
1369
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
+ }
1399
1388
}
1400
-
1389
+ ret = MBED_SUCCESS;
1401
1390
end:
1402
1391
_mutex.unlock ();
1403
1392
return ret;
1404
1393
}
1405
1394
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 )
1407
1396
{
1408
1397
reserved_trailer_t trailer;
1409
- uint8_t * buf;
1398
+ uint8_t buf[RESERVED_AREA_SIZE] ;
1410
1399
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;
1421
1401
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;
1427
1410
}
1428
- }
1429
1411
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 ;
1434
1415
}
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 ;
1437
1419
}
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 ;
1449
1420
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);
1453
1423
if (ret) {
1454
1424
return ret;
1455
1425
}
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 );
1460
1431
}
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;
1461
1439
}
1462
-
1463
- crc = calc_crc (crc, chunk, buf + offset);
1464
- offset += chunk;
1465
- actual_size -= chunk;
1466
1440
}
1467
1441
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;
1475
1443
}
1476
1444
1477
1445
int TDBStore::reserved_data_get (void *reserved_data, size_t reserved_data_buf_size, size_t *actual_data_size)
0 commit comments