115 lines
3.2 KiB
C++
115 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <string.h>
|
|
#include <string>
|
|
#include "../Types.h"
|
|
|
|
namespace FAT32 {
|
|
|
|
static inline uint16_t getU8(const uint8_t* src) {return src[0];}
|
|
static inline uint16_t getU16(const uint8_t* src) {return src[0]<<0 | src[1]<<8;}
|
|
static inline uint32_t getU32(const uint8_t* src) {return src[0]<<0 | src[1]<<8 | src[2]<<16 | src[3]<<24;}
|
|
static inline size_t min(size_t a, size_t b) {return (a<b) ? a : b;}
|
|
|
|
/** describes a uint32_t Cluster Number and typical helper functions */
|
|
struct ClusterNr {
|
|
|
|
uint32_t val;
|
|
|
|
ClusterNr() : val(0) {}
|
|
ClusterNr(uint32_t val) : val(val) {}
|
|
|
|
void operator = (const uint32_t val) {this->val = val;}
|
|
|
|
operator uint32_t() const {return val;}
|
|
|
|
inline bool isEndOfClusters() const {
|
|
return (val & 0x0FFFFFFF) >= 0xFFFFFF8; // only the lower 28 bits are used
|
|
}
|
|
|
|
inline bool isFree() const {
|
|
return val == 0;
|
|
}
|
|
|
|
void operator ++() {++val;}
|
|
|
|
};
|
|
|
|
const ClusterNr END_OF_CLUSTERS = 0x0FFFFFF8;
|
|
|
|
|
|
/** FAT32: header within the first 512 bytes of the Filesystem */
|
|
struct FSHeader { // https://www.easeus.com/resource/fat32-disk-structure.htm
|
|
uint8_t dummy1[11];
|
|
uint16_t bytesPerSector; // @0x0B;
|
|
uint8_t sectorsPerCluster; // @0x0D;
|
|
uint16_t numReservedSectors; // @0x0E;
|
|
uint8_t numberOfFATs; // @0x10;
|
|
uint8_t dummy2[4];
|
|
uint8_t mediaDescriptor; // @0x15;
|
|
uint8_t dummy3[10];
|
|
uint32_t sectorsInPartition; // @0x20;
|
|
uint32_t sectorsPerFAT; // @0x24; // home many sectors does each of the 2 FATs contain?
|
|
uint8_t dummy4[4];
|
|
uint32_t rootDirFirstCluster; // @0x2C
|
|
} __attribute__((packed));
|
|
|
|
/** FAT32: attributes of a DirEntry */
|
|
union Attributes {
|
|
uint8_t raw;
|
|
struct {
|
|
uint8_t readOnly : 1;
|
|
uint8_t hidden : 1;
|
|
uint8_t system : 1;
|
|
uint8_t volumeID : 1;
|
|
uint8_t directory : 1;
|
|
uint8_t archive : 1;
|
|
uint8_t unused1 : 1;
|
|
uint8_t unused2 : 1;
|
|
} bits;
|
|
} __attribute__((packed));
|
|
|
|
/** FAT32: structure for a DirectoryEntry as defined in the FAT standard */
|
|
struct DirEntry {
|
|
union {
|
|
unsigned char name83[8+3];
|
|
struct {
|
|
unsigned char name[8];
|
|
unsigned char ext[3];
|
|
} __attribute__((packed));
|
|
} __attribute__((packed));
|
|
Attributes attr;
|
|
uint8_t dummy1[8];
|
|
uint16_t firstClusterHi;
|
|
uint8_t dummy2[4];
|
|
uint16_t firstClusterLo;
|
|
uint32_t size; // file size in bytes
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
|
|
/** only the important parts of above header (to save space) */
|
|
struct FSDesc {
|
|
uint16_t bytesPerSector;
|
|
uint8_t sectorsPerCluster;
|
|
uint16_t numReservedSectors;
|
|
uint8_t numberOfFATs;
|
|
uint32_t sectorsPerFAT;
|
|
ClusterNr rootDirFirstCluster;
|
|
};
|
|
|
|
/** additional pre-computed values, to reduce calculations */
|
|
struct Precomputed {
|
|
uint32_t bytesPerCluster;
|
|
AbsPos startOfFAT1; // absolute byte offset where the FAT1 begins
|
|
AbsPos startOfFAT2; // absolute byte offset where the FAT2 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 entriesPerFAT; // number of entries (cluster pointers) within each FAT
|
|
uint32_t dirEntriesPerSector; // number of directory entries that fit into a sector
|
|
};
|
|
|
|
}
|