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