huge work on FAT32, initial support for writing
This commit is contained in:
@@ -15,25 +15,51 @@ namespace FAT32 {
|
||||
BlockDev& dev;
|
||||
AbsOffset offset;
|
||||
|
||||
|
||||
FSDesc desc;
|
||||
Precomputed tmp;
|
||||
bool valid = false;
|
||||
|
||||
#include "FreeClusterIterator.h"
|
||||
FreeClusterIterator fci;
|
||||
|
||||
public:
|
||||
|
||||
#include "File.h"
|
||||
#include "File2.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) {
|
||||
FS(BlockDev& dev, AbsOffset offset) : dev(dev), offset(offset), fci(*this) {
|
||||
init();
|
||||
}
|
||||
|
||||
void setup(uint32_t totalSize) {
|
||||
|
||||
uint8_t buf[512] = {0};
|
||||
buf[0x1FE] = 0x55;
|
||||
buf[0x1FF] = 0xAA;
|
||||
|
||||
FSHeader* header = (FSHeader*) buf;
|
||||
header->bytesPerSector = 512;
|
||||
header->numberOfFATs = 2;
|
||||
header->numReservedSectors = 32;
|
||||
header->rootDirFirstCluster = 2;
|
||||
header->mediaDescriptor = 0xF8; // hard disk
|
||||
header->sectorsInPartition = totalSize / 512;
|
||||
header->sectorsPerCluster = 8;
|
||||
header->sectorsPerFAT = 64; // 8 MB
|
||||
|
||||
dev.write(offset, 512, (const uint8_t*)header);
|
||||
|
||||
init();
|
||||
|
||||
// mark the root-dir cluster as used
|
||||
setNextCluster(2, END_OF_CLUSTERS);
|
||||
|
||||
}
|
||||
|
||||
/** is the detected FS valid? */
|
||||
bool isValid() const {
|
||||
return valid;
|
||||
@@ -45,19 +71,39 @@ namespace FAT32 {
|
||||
}
|
||||
|
||||
/** open the given file for reading*/
|
||||
File open(const DirEntry& de) {
|
||||
return File(*this, de.size, de.getFirstCluster());
|
||||
File open(const DirEntryAt& dea) {
|
||||
return File(*this, dea.getSize(), dea.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();
|
||||
// }
|
||||
// }
|
||||
/** open the given file for reading*/
|
||||
File2 open2(const DirEntryAt& dea) {
|
||||
return File2(*this, dea);
|
||||
}
|
||||
|
||||
/** create a new file for writing, in the given directory */
|
||||
File2 create2(const char* name) {
|
||||
|
||||
ClusterNr dirStartCluster = 2; // TODO
|
||||
|
||||
//if (!dea.isValid()) {Log::addError(NAME, "create2(): not a valid DirEntry");}
|
||||
//if (!dea.isDirectory()) {Log::addError(NAME, "create2(): not a directory");}
|
||||
DirIterator di(*this, dirStartCluster);
|
||||
|
||||
// allocate a new directory entry for the file
|
||||
DirEntryAt dea2 = di.nextFree();
|
||||
dea2.setName(name);
|
||||
dea2.setSize(0);
|
||||
|
||||
// allocate the file's first cluster
|
||||
ClusterNr firstCluster = allocFreeCluster(0);
|
||||
dea2.setFirstCluster(firstCluster);
|
||||
|
||||
// write the file description
|
||||
write(dea2);
|
||||
|
||||
return File2(*this, dea2);
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -102,18 +148,40 @@ namespace FAT32 {
|
||||
}
|
||||
|
||||
/** determine the ClusterNr following the given ClusterNr */
|
||||
ClusterNr getNextCluster(ClusterNr clusterNr) {
|
||||
const AbsPos pos = tmp.startOfFAT + ((clusterNr) * sizeof(uint32_t));
|
||||
ClusterNr getNextCluster(const ClusterNr clusterNr) {
|
||||
const AbsPos pos = tmp.startOfFAT + (clusterNr * sizeof(ClusterNr));
|
||||
ClusterNr next = 0;
|
||||
dev.read(pos, 4, reinterpret_cast<uint8_t*>(&next));
|
||||
Log::addInfo(NAME, "nextCluster(%d) -> %d", clusterNr, next);
|
||||
dev.read(pos, sizeof(ClusterNr), reinterpret_cast<uint8_t*>(&next));
|
||||
Log::addInfo(NAME, "getNextCluster(%d) -> %d", clusterNr, next);
|
||||
return next;
|
||||
}
|
||||
|
||||
/** set the ClusterNr following clusterNr */
|
||||
void setNextCluster(const ClusterNr clusterNr, const ClusterNr next) {
|
||||
const AbsPos pos = tmp.startOfFAT + (clusterNr * sizeof(ClusterNr));
|
||||
dev.write(pos, sizeof(ClusterNr), reinterpret_cast<const uint8_t*>(&next));
|
||||
Log::addInfo(NAME, "setNextCluster(%d) -> %d", clusterNr, next);
|
||||
}
|
||||
|
||||
/** convert ClusterNr into an absolute position on disk */
|
||||
AbsPos clusterToAbsPos(ClusterNr clusterNr) {
|
||||
return tmp.startOfFirstDataCluster + ((clusterNr - 2) * desc.sectorsPerCluster * desc.bytesPerSector);
|
||||
}
|
||||
|
||||
/** allocate a new empty cluster, and register it. if prevNr == 0, it has NO previous cluster (first in line) */
|
||||
ClusterNr allocFreeCluster(ClusterNr prevNr = 0) {
|
||||
ClusterNr newCluster = fci.next(); // get/find a free cluster
|
||||
if (prevNr > 0) {
|
||||
setNextCluster(prevNr, newCluster); // follows the previous cluster (if any)
|
||||
}
|
||||
setNextCluster(newCluster, END_OF_CLUSTERS);// no clusters follow the new cluster
|
||||
return newCluster;
|
||||
}
|
||||
|
||||
/** write the given DirEntry back to disk */
|
||||
void write(const DirEntryAt& dea) {
|
||||
dev.write(dea.posOnDisk, sizeof(DirEntry), (const uint8_t*)&dea.entry);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user