worked on FileSystem, started to migrate logging class

This commit is contained in:
2021-02-14 15:29:21 +01:00
parent faf6e55bc5
commit 6aa951190e
19 changed files with 612 additions and 241 deletions

View File

@@ -1,45 +1,79 @@
class DirIterator {
static constexpr const char* NAME = "FAT32_DirI";
FS& fs;
ClusterNr nextCluster;
int curEntryInCluster;
ClusterNr curCluster;
uint8_t curEntryInSector; // current DirEntry within the current sector
uint8_t curSectorInCluster; // current Sector within the current cluster
uint8_t buf[512];
public:
DirIterator(FS& fs, ClusterNr clusterNr) : fs(fs), nextCluster(clusterNr), curEntryInCluster(255) {
DirIterator(FS& fs, ClusterNr clusterNr) : fs(fs), curCluster(clusterNr), curEntryInSector(0), curSectorInCluster(0) {
Log::addInfo(NAME, "init @ Cluster %d", curCluster);
// read the first sector in the first cluster
read(curCluster, 0);
}
bool hasNext() {
DirEntry* next() {
while(true) {
++curEntryInCluster;
// end of sector reached?
if (curEntryInSector >= fs.tmp.dirEntriesPerSector) {
// next sector
++curSectorInCluster;
curEntryInSector = 0;
// end of cluster reached?
if (curSectorInCluster >= fs.desc.sectorsPerCluster) {
// find next cluster
curCluster = fs.getNextCluster(curCluster); // number of the next cluster (if any)
curSectorInCluster = 0;
}
// fetch from disk
read(curCluster, curSectorInCluster);
// reached end of cluster? load the next one
if (curEntryInCluster > fs.tmp.dirEntriesPerSector) {
fs.dev.read(fs.clusterToAbsPos(nextCluster), 512, buf);
nextCluster = fs.getNextCluster(nextCluster);
curEntryInCluster = 0;
}
DirEntry* desc = reinterpret_cast<DirEntry*>(buf + (sizeof(DirEntry) * curEntryInCluster));
// the current entry
DirEntry* dirEntry = reinterpret_cast<DirEntry*>(buf + (sizeof(DirEntry) * curEntryInSector));
++curEntryInSector;
if (desc->isLongFileName()) {continue;}
if (desc->isUnused()) {continue;}
if (desc->isEndOfDirectory()) {return false;}
// check it
if (dirEntry->isLongFileName()) {continue;}
if (dirEntry->isUnused()) {continue;}
if (dirEntry->isEndOfDirectory()) {
return nullptr;
}
return true;
// usable!
return dirEntry;
}
}
DirEntry next() {
DirEntry* de = reinterpret_cast<DirEntry*>(buf + (sizeof(DirEntry) * curEntryInCluster));
return *de;
private:
/** fetch one sector within a cluster */
void read(ClusterNr clusterNr, uint8_t sectorInCluster) {
Log::addInfo(NAME, "fetching sector %d in clusterNr %d", sectorInCluster, clusterNr) ;
const AbsPos pos = fs.clusterToAbsPos(clusterNr) + (curSectorInCluster * fs.desc.bytesPerSector);
fs.dev.read(pos, fs.desc.bytesPerSector, buf);
}
};

View File

@@ -1,6 +1,8 @@
#pragma once
#include <cstdint>
#include <functional>
#include "Structs.h"
// https://www.pjrc.com/tech/8051/ide/fat32.html
@@ -23,6 +25,9 @@ namespace FAT32 {
#include "File.h"
#include "DirIterator.h"
#include "WriteFile.h"
#include "FreeClusterIterator.h"
/** ctor with the absolute offset addr (in bytes) */
FS(BlockDev& dev, AbsOffset offset) : dev(dev), offset(offset) {
@@ -41,14 +46,25 @@ namespace FAT32 {
/** open the given file for reading*/
File open(const DirEntry& de) {
return File(*this, de.getFirstCluster(), de.size);
return File(*this, de.size, de.getFirstCluster());
}
// /** create a new file for writing, in the given directory */
// WriteFile newFile(DirEntry& de, const uint32_t size) {
// if (!de.isDirectory()) {return nullptr;}
// uint32_t allocSize = 0;
// FreeClusterIterator fci(*this);
// while(allocSize < size) {
// ClusterNr = fci.next();
// }
// }
private:
void init() {
debugMod3(NAME")
Log::addInfo(NAME, "init @ %d", offset);
uint8_t buf[512];
dev.read(offset, 512, buf);
@@ -68,6 +84,8 @@ namespace FAT32 {
tmp.startOfFirstRootDirCluster = clusterToAbsPos(desc.rootDirFirstCluster);
tmp.dirEntriesPerSector = desc.bytesPerSector / sizeof(DirEntry);
Log::addInfo(NAME, "Bytes/Sector: %d, Sector/Cluster: %d, FATs: %d, RootDir: %d", desc.bytesPerSector, desc.sectorsPerCluster, desc.numberOfFATs, desc.rootDirFirstCluster);
/*
std::cout << (int)desc.bytesPerSector << std::endl;
std::cout << (int)desc.sectorsPerCluster << std::endl;
@@ -86,8 +104,9 @@ namespace FAT32 {
/** determine the ClusterNr following the given ClusterNr */
ClusterNr getNextCluster(ClusterNr clusterNr) {
const AbsPos pos = tmp.startOfFAT + ((clusterNr) * sizeof(uint32_t));
ClusterNr next;
int read = dev.read(pos, 4, reinterpret_cast<uint8_t*>(&next));
ClusterNr next = 0;
dev.read(pos, 4, reinterpret_cast<uint8_t*>(&next));
Log::addInfo(NAME, "nextCluster(%d) -> %d", clusterNr, next);
return next;
}

View File

@@ -1,100 +0,0 @@
#pragma once
#include <cstdint>
#include "Structs.h"
// https://www.pjrc.com/tech/8051/ide/fat32.html
namespace FAT32 {
template <typename BlockDev> class FS {
static constexpr const char* NAME = "FAT32";
BlockDev& dev;
AbsOffset offset;
FSDesc desc;
Precomputed tmp;
bool valid = false;
public:
#include "File.h"
#include "DirIterator.h"
/** ctor with the absolute offset addr (in bytes) */
FS(BlockDev& dev, AbsOffset offset) : dev(dev), offset(offset) {
init();
}
/** is the detected FS valid? */
bool isValid() const {
return valid;
}
/** get an iterator for the root directory */
DirIterator getRoot() {
return DirIterator(*this, desc.rootDirFirstCluster);
}
/** open the given file for reading*/
File open(const DirEntry& de) {
return File(*this, de.getFirstCluster(), de.size);
}
private:
void init() {
debugMod3(NAME)
uint8_t buf[512];
dev.read(offset, 512, buf);
desc.bytesPerSector = getU16(&buf[0x0B]);
desc.sectorsPerCluster = getU8(&buf[0x0D]);
desc.numReservedSectors = getU16(&buf[0x0E]);
desc.numberOfFATs = getU8(&buf[0x10]);
desc.sectorsPerFAT = getU32(&buf[0x24]);
desc.rootDirFirstCluster = getU32(&buf[0x2C]);
// basic sanity check based on constants
valid = (desc.bytesPerSector == 512) && (desc.numberOfFATs == 2) && (getU16(&buf[0x1FE]) == 0xAA55);
tmp.bytesPerCluster = desc.sectorsPerCluster * desc.bytesPerSector;
tmp.startOfFAT = offset + (desc.numReservedSectors * desc.bytesPerSector);
tmp.startOfFirstDataCluster = offset + (desc.numReservedSectors * desc.bytesPerSector) + (desc.numberOfFATs * desc.sectorsPerFAT * desc.bytesPerSector);
tmp.startOfFirstRootDirCluster = clusterToAbsPos(desc.rootDirFirstCluster);
tmp.dirEntriesPerSector = desc.bytesPerSector / sizeof(DirEntry);
/*
std::cout << (int)desc.bytesPerSector << std::endl;
std::cout << (int)desc.sectorsPerCluster << std::endl;
std::cout << (int)desc.numReservedSectors << std::endl;
std::cout << (int)desc.numberOfFATs << std::endl;
std::cout << (int)desc.sectorsPerFAT << std::endl;
std::cout << (int)desc.rootDirFirstCluster << std::endl;
std::cout << tmp.startOfFAT << std::endl;
std::cout << tmp.startOfFirstDataCluster << std::endl;
std::cout << tmp.startOfFirstRootDirCluster << std::endl;
*/
}
/** determine the ClusterNr following the given ClusterNr */
ClusterNr getNextCluster(ClusterNr clusterNr) {
const AbsPos pos = tmp.startOfFAT + ((clusterNr) * sizeof(uint32_t));
ClusterNr next;
int read = dev.read(pos, 4, reinterpret_cast<uint8_t*>(&next));
return next;
}
/** convert ClusterNr into an absolute position on disk */
AbsPos clusterToAbsPos(ClusterNr clusterNr) {
return tmp.startOfFirstDataCluster + ((clusterNr - 2) * desc.sectorsPerCluster * desc.bytesPerSector);
}
};
}

View File

@@ -1,6 +1,7 @@
class File {
static constexpr const int32_t F_EOF = -1;
static constexpr const char* NAME = "FAT32_File";
static constexpr const uint32_t F_EOF = 0xFFFFFFFF;
FS& fs;
uint32_t totalSize;
@@ -12,23 +13,33 @@ class File {
public:
File(FS& fs, uint32_t firstCluster, uint32_t size) : fs(fs), totalSize(size), curCluster(firstCluster) {
File(FS& fs, uint32_t size, uint32_t firstCluster) : fs(fs), totalSize(size), curCluster(firstCluster) {
Log::addInfo(NAME, "init @ cluster %d", firstCluster);
}
/** the file's size */
uint32_t getSize() const {return totalSize;}
uint32_t read(uint32_t size, uint8_t* dst) {
uint32_t total = 0;
while(true) {
const uint32_t read = _read(size, dst);
if (read == F_EOF) {break;}
size -= read;
uint32_t read(uint32_t size, uint8_t* dst, std::function<void(int)> callback) {
Log::addInfo(NAME, "read %d bytes", size);
uint32_t remaining = size;
uint32_t totalRead = 0;
while(remaining) {
const uint32_t read = _read(remaining, dst);
if (read == F_EOF) {
Log::addInfo(NAME, "EOF"); break;
}
remaining -= read;
dst += read;
total += read;
totalRead += read;
callback(totalRead*100/size);
}
return total;
return totalRead;
}
private:
@@ -44,6 +55,7 @@ private:
if (posInCluster == fs.tmp.bytesPerCluster) {
curCluster = fs.getNextCluster(curCluster);
posInCluster = 0;
Log::addInfo(NAME, "next cluster %d", curCluster);
}
// how many bytes are left in the current cluster?

View File

@@ -0,0 +1,14 @@
#pragma once
/** helper class to iterate all free clusters of the Filesystem */
class FreeClusterIterator {
FS& fs;
public:
FreeClusterIterator(FS& fs) : fs(fs) {
}
};

View File

@@ -1,13 +1,11 @@
#pragma once
#include <cstdint>
#include <string>
#include "Types.h"
namespace FAT32 {
using ClusterNr = uint32_t;
using AbsOffset = uint32_t;
using AbsPos = uint32_t;
struct FSDesc {
uint16_t bytesPerSector;
@@ -23,7 +21,7 @@ namespace FAT32 {
AbsPos startOfFAT; // absolute byte offset where the FAT begins
AbsPos startOfFirstDataCluster; // absolute byte offset where the first cluster is
AbsPos startOfFirstRootDirCluster; // absolute byte offset where the first root dir cluster is
uint32_t dirEntriesPerSector;
uint32_t dirEntriesPerSector; // number of directory entries that fit into a sector
};
union Attributes {
@@ -63,7 +61,7 @@ namespace FAT32 {
uint8_t pos = 0;
for (uint8_t i = 0; i < 8; ++i) {if (name[i] != ' ') {buf[pos++] = name[i];}}
buf[pos++] = '.';
for (uint8_t i = 0; i < 8; ++i) {if ( ext[i] != ' ') {buf[pos++] = ext[i];}}
for (uint8_t i = 0; i < 3; ++i) {if ( ext[i] != ' ') {buf[pos++] = ext[i];}}
buf[pos] = 0;
return std::string(buf);
}

5
ext/sd/fat32/WriteFile.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
class WriteFile {
};