6 #include "FsPartition.hpp"
8 #include "LibEndian.hpp"
10 FsPartition::FsPartition(
class FsDrive* drive,
int indexOnDrive) {
13 mIndexOnDrive = indexOnDrive;
16 uint32_t FsPartition::getRootClusterLba() {
17 return getClusterBeginLba(mRootDirFirstCluster);
20 uint32_t FsPartition::getFatSectorLba(uint32_t cluster) {
21 return mFatBeginLba + (cluster >> 7);
24 uint32_t FsPartition::getFatSectorIndex(uint32_t cluster) {
25 return (cluster & 0x7F);
28 uint32_t FsPartition::getClusterBeginLba(uint32_t cluster) {
29 return mClusterBeginLba + (cluster - 2) * mSectorsPerCluster;
32 uint32_t FsPartition::getClusterFromLba(uint32_t lba) {
33 return ((lba - mClusterBeginLba) / mSectorsPerCluster) + 2;
39 FsDefs::RESULT FsPartition::initFromBootSector(FsDefs::BOOT_SECTOR* bootSector, uint32_t partitionBeginLba) {
40 uint16_t rootEntCnt = LibEndian::leToHw(bootSector->rootEntCnt);
41 uint16_t bytsPerSec = LibEndian::leToHw(bootSector->bytsPerSec);
43 uint32_t rootDirSectors = ((rootEntCnt * 32) + (bytsPerSec - 1)) / bytsPerSec;
46 uint32_t fatSz = LibEndian::leToHw(bootSector->fatSz16);
48 fatSz = LibEndian::leToHw(bootSector->type.fat32.fatSz32);
50 uint32_t totSectors = LibEndian::leToHw(bootSector->totSec16);
52 totSectors = LibEndian::leToHw(bootSector->totSec32);
55 uint16_t rsvdSecCnt = LibEndian::leToHw(bootSector->rsvdSecCnt);
56 uint32_t dataSectorsCount = totSectors - rsvdSecCnt + (bootSector->numFats * fatSz) + rootDirSectors;
57 uint32_t clustersCount = dataSectorsCount / bootSector->secPerClus;
58 uint32_t fatBeginLba = LibEndian::leToHw(mFatBeginLba);
59 uint32_t bigSectorsPerFat = LibEndian::leToHw(bootSector->fatSz16);
60 mRootDirFirstCluster = 2;
61 if (clustersCount < 4085) {
62 mFatType = FsPartition::FAT12;
64 else if (clustersCount < 65525) {
65 mFatType = FsPartition::FAT16;
68 mInfoSectorLba = fatBeginLba + LibEndian::leToHw(bootSector->type.fat32.fsInfo);
69 mBackupBootSectorLba = fatBeginLba + LibEndian::leToHw(bootSector->type.fat32.bkBootSec);
70 bigSectorsPerFat = LibEndian::leToHw(bootSector->type.fat32.fatSz32);
71 mRootDirFirstCluster = LibEndian::leToHw(bootSector->type.fat32.rootClus);
72 mFatType = FsPartition::FAT32;
75 mFatBeginLba = partitionBeginLba + rsvdSecCnt;
76 mClusterBeginLba = mFatBeginLba + ((uint32_t) bootSector->numFats * bigSectorsPerFat);
77 mSectorsPerCluster = bootSector->secPerClus;
78 mClustersCount = clustersCount;
79 mNumFats = bootSector->numFats;
81 mInfoFreeClusterCount = 0xFFFFFFFF;
82 mInfoNextFreeCluster = 0xFFFFFFFF;
86 if (mFatType == FsPartition::FAT32) {
87 if (!mDrive->readBlocks((FsDefs::SECTOR*) bootSector, mInfoSectorLba, 1)) {
88 return FsDefs::RES_DISK_ERROR;
90 FsDefs::FS_INFO* fsInfo = (FsDefs::FS_INFO*) bootSector;
91 mInfoFreeClusterCount = LibEndian::leToHw(fsInfo->freeCount);
92 mInfoNextFreeCluster = LibEndian::leToHw(fsInfo->nextFree);
94 return FsDefs::RES_SUCCESS;
97 FsDefs::RESULT FsPartition::getNextBlockLba(FsDefs::SECTOR* sector, uint32_t* lba) {
98 if ((++*lba - mClusterBeginLba) % mSectorsPerCluster) {
99 return FsDefs::RES_SUCCESS;
102 uint32_t currentCluster = getClusterFromLba(*lba - 1);
104 if (!mDrive->readBlocks(sector, getFatSectorLba(currentCluster), 1)) {
106 return FsDefs::RES_DISK_ERROR;
108 uint32_t nextCluster = sector->dwords[FsPartition::getFatSectorIndex(currentCluster)];
109 if (nextCluster >= 0xFFFFFFF8 || nextCluster == 0) {
111 return FsDefs::RES_EOF;
114 *lba = getClusterBeginLba(nextCluster);
115 return FsDefs::RES_SUCCESS;
118 return FsDefs::RES_SUCCESS;
121 FsDefs::RESULT FsPartition::getNextFreeCluster(FsDefs::SECTOR* sector, uint32_t* cluster) {
122 if (mInfoSectorLba) {
123 *cluster = mInfoNextFreeCluster;
126 *cluster = mRootDirFirstCluster;
129 *cluster = mRootDirFirstCluster;
130 if (!mDrive->readBlocks(sector, getFatSectorLba(*cluster), 1)) {
131 return FsDefs::RES_DISK_ERROR;
133 for (
unsigned int i = 0; i < mClustersCount; i++) {
134 if (sector->dwords[FsPartition::getFatSectorIndex(*cluster)] == 0) {
135 mInfoNextFreeCluster = *cluster;
136 return FsDefs::RES_SUCCESS;
139 if (*cluster >= mClustersCount) {
140 *cluster = mRootDirFirstCluster;
142 if ((FsPartition::getFatSectorIndex(*cluster)) == 0) {
143 if (!mDrive->readBlocks(sector, getFatSectorLba(*cluster), 1)) {
144 return FsDefs::RES_DISK_ERROR;
148 return FsDefs::RES_DISK_FULL;
151 FsDefs::RESULT FsPartition::appendFreeCluster(FsDefs::SECTOR* sector, uint32_t* cluster) {
152 uint32_t freeCluster;
153 FsDefs::RESULT result = getNextFreeCluster(sector, &freeCluster);
154 if (result != FsDefs::RES_SUCCESS) {
157 result = setFatValue(sector, *cluster, freeCluster);
158 if (result != FsDefs::RES_SUCCESS) {
161 result = setFatValue(sector, freeCluster, FsDefs::FAT_LAST_CLUSTER);
162 if (result != FsDefs::RES_SUCCESS) {
165 if (mInfoFreeClusterCount > 0) {
166 mInfoFreeClusterCount--;
169 *cluster = freeCluster;
170 return FsDefs::RES_SUCCESS;
173 FsDefs::RESULT FsPartition::setFatValue(FsDefs::SECTOR* sector, uint32_t cluster, uint32_t value) {
174 if (!mDrive->readBlocks(sector, getFatSectorLba(cluster), 1)) {
175 return FsDefs::RES_DISK_ERROR;
177 sector->dwords[FsPartition::getFatSectorIndex(cluster)] = LibEndian::hwToLe(value);
178 return writeFatSector(sector, cluster);
181 FsDefs::RESULT FsPartition::writeFatSector(FsDefs::SECTOR* sector, uint32_t cluster) {
182 for (uint32_t i = 0, lba = getFatSectorLba(cluster); i < mNumFats; i++) {
183 if (!mDrive->writeBlocks(sector, lba, 1)) {
184 return FsDefs::RES_DISK_ERROR;
186 lba += lba + (i * mClustersCount >> 7);
188 return FsDefs::RES_SUCCESS;
191 FsDefs::RESULT FsPartition::freeClusterChain(FsDefs::SECTOR* sector, uint32_t cluster) {
192 if ((cluster == FsDefs::FAT_FREE_CLUSTER) || (cluster == 0)) {
193 return FsDefs::RES_SUCCESS;
196 uint32_t lba = getFatSectorLba(cluster);
197 if (!mDrive->readBlocks(sector, lba, 1)) {
198 return FsDefs::RES_DISK_ERROR;
202 uint16_t index = getFatSectorIndex(cluster);
203 uint32_t nextCluster = sector->dwords[index];
204 mInfoFreeClusterCount++;
205 if ((nextCluster > FsDefs::FAT_MAX_CLUSTER_VALUE) || (nextCluster == 0)) {
206 sector->dwords[index] = FsDefs::FAT_FREE_CLUSTER;
207 FsDefs::RESULT result = writeFatSector(sector, cluster);
208 if (result != FsDefs::RES_SUCCESS) {
214 sector->dwords[index] = FsDefs::FAT_FREE_CLUSTER;
215 uint32_t nextLba = getFatSectorLba(nextCluster);
216 if (nextLba != lba) {
217 FsDefs::RESULT result = writeFatSector(sector, cluster);
218 if (result != FsDefs::RES_SUCCESS) {
221 if (!mDrive->readBlocks(sector, lba, 1)) {
222 return FsDefs::RES_DISK_ERROR;
226 cluster = nextCluster;
230 return FsDefs::RES_SUCCESS;
233 FsDefs::RESULT FsPartition::updateInfo(FsDefs::SECTOR* sector) {
234 if (mInfoSectorLba == 0) {
235 return FsDefs::RES_SUCCESS;
237 if (!mDrive->readBlocks(sector, mInfoSectorLba, 1)) {
238 return FsDefs::RES_DISK_ERROR;
240 FsDefs::FS_INFO* fsInfo = (FsDefs::FS_INFO*) sector;
241 fsInfo->nextFree = LibEndian::hwToLe(mInfoNextFreeCluster);
242 fsInfo->freeCount = LibEndian::hwToLe(mInfoFreeClusterCount);
243 if (!mDrive->writeBlocks(sector, mInfoSectorLba, 1)) {
244 return FsDefs::RES_DISK_ERROR;
246 return FsDefs::RES_SUCCESS;
249 bool FsPartition::readBlocks(FsDefs::SECTOR* buffer,
unsigned int blockNumber,
unsigned int blockCount) {
250 return mDrive->readBlocks(buffer, blockNumber, blockCount);
253 bool FsPartition::writeBlocks(
const FsDefs::SECTOR* buffer,
unsigned int blockNumber,
unsigned int blockCount) {
254 return mDrive->writeBlocks(buffer, blockNumber, blockCount);
257 void FsPartition::lock() {
261 void FsPartition::unlock() {