in libs/storage/SNORFS.cpp [328:423]
bool FS::readHeaders()
{
memset(rowRemapCache, 0xff, numRows);
static BlockHeader hd; // can't be on stack!
int freeRow = -1;
bool freeDirty = false;
bool freeRandom = false;
int minEraseIdx = -1;
uint32_t minEraseCnt = 0;
uint32_t freeEraseCnt = 0;
uint32_t totalEraseCount = 0;
for (unsigned i = 0; i < (unsigned)numRows + 1; ++i)
{
auto addr = i * SPIFLASH_BIG_ROW_SIZE;
flash.readBytes(addr, &hd, sizeof(hd));
if (hd.magic != SNORFS_MAGIC || hd.version != 0)
{
// likely, we got a power failure during row erase - it now contains random data
if (freeRow == -1)
{
freeDirty = true;
freeRandom = true;
freeRow = i;
continue;
}
return false;
}
numMetaRows = hd.numMetaRows;
totalEraseCount += hd.eraseCount;
if (hd.logicalBlockId == 0xffff || hd.copiedFlag != SNORFS_COPIED_FLAG)
goto isFree;
else
{
if (hd.logicalBlockId >= numRows)
return false;
// if this is the first duplicate, it is liekly a duplicate left over from unfinished
// swapRow
if (rowRemapCache[hd.logicalBlockId] != 0xff)
goto isFree;
rowRemapCache[hd.logicalBlockId] = i;
if (minEraseIdx < 0 || hd.eraseCount < minEraseCnt)
{
minEraseCnt = hd.eraseCount;
minEraseIdx = i;
}
}
continue;
isFree:
if (freeRow == -1)
{
freeRow = i;
if (hd.freeFlag != SNORFS_FREE_FLAG)
freeDirty = true;
}
else
return false;
freeEraseCnt = hd.eraseCount;
}
feedRandom(totalEraseCount);
this->freeRow = freeRow;
if (freeRow == -1 || !numMetaRows || numMetaRows > numRows / 2)
return false;
if (freeDirty)
{
LOG("fixing free row: %d\n", freeRow);
busy();
initBlockHeader(hd, true);
hd.eraseCount = freeRandom ? totalEraseCount / numRows : freeEraseCnt;
flash.eraseBigRow(freeRow * SPIFLASH_BIG_ROW_SIZE);
busy();
flash.writeBytes(freeRow * SPIFLASH_BIG_ROW_SIZE, &hd, sizeof(hd));
busy(false);
}
else if (minEraseCnt + SNORFS_LEVELING_THRESHOLD < freeEraseCnt)
{
swapRow(minEraseIdx);
LOGV(" for level\n");
}
else
{
LOGV("[no level swap: free %d, min %d]", freeEraseCnt, minEraseCnt);
}
return true;
}