Mcucpp
514 строк · 11.0 Кб
1#include <filesystem/fat.h>2#include <memory_stream.h>3#include <filesystem/file.h>4#include <template_utils.h>5#include <utf8.h>6#include <data_buffer.h>7#include <new>8
9namespace Mcucpp10{
11namespace Fat12{
13using namespace Mcucpp::Fs;14
15size_t DecodeShortName(const uint8_t* shortName, uint8_t *name)16{17size_t nameLen = 0;18for(int i = 0; i < 11; i++)19{20if(i == 8)21{22*name++ = '.';23nameLen++;24}25if(*shortName == 0x20)26{27shortName++;28continue;29}30*name++ = *shortName++;31nameLen++;32}33if(name[-1] == '.')34{35name--;36nameLen--;37}38*name = 0;39return nameLen;40}41
42uint8_t ShortNameCheckSum(const uint8_t* dirEntryName)43{44uint8_t result = 0;45for (int i = 0; i < 11; i++)46{47result = ((result & 1) ? 0x80 : 0) + (result >> 1) + dirEntryName[i];48}49return result;50}51
52uint32_t FatFs::ClusterToSector(uint32_t cluster)53{54return (cluster - 2) * _fat.sectorPerCluster + _fat.firstDataSector;55}56
57uint32_t FatFs::SectorToClaster(uint32_t sector)58{59return (sector - _fat.firstDataSector) / _fat.sectorPerCluster + 2;60}61
62FatFs::FatFs(IBlockDevice &device)63:_device(device),64_lastError(ErrOK),65_cachedSector(0xffffffff),66_sectorBuffer(nullptr)67{68
69}70
71MemoryStream FatFs::ReadSector(uint32_t sector)72{73if(_cachedSector != sector)74{75if(!_device.ReadPage(sector, _sectorBuffer, _fat.bytesPerSector, 0))76{77_lastError = ErrIoFailed;78}79_cachedSector = sector;80}81return MemoryStream(_sectorBuffer, _fat.bytesPerSector);82}83
84ErrorCode FatFs::GetError()85{86return _lastError;87}88
89bool FatFs::EndOfFile(Fs::FsNode node)90{91return node >= _fat.eocMarker;92}93
94FsNode FatFs::RootDirectory()95{96return FsNode(_fat.rootSector);97}98
99bool FatFs::ListDirectory(FsNode dir, DirectoryLister &directoryLister)100{101BinaryStream<Fs::File> drectory(*this, dir, -1);102
103int lfnChecksum = -1;104DataBuffer lfnBuffer;105
106for(TFileSize dirEntryIndex = 0; !drectory.EndOfFile(); dirEntryIndex += DIR_ENTRY_SIZE)107{108drectory.Seek(dirEntryIndex);109uint8_t marker = drectory.Read();110if(marker == DELETED)111{112continue;113}114if(marker == EMPTY)115{116_lastError = ErrOK;117return true;118}119
120drectory.Seek(dirEntryIndex + 11);121uint8_t attr = drectory.Read();122if(attr == 0xff)123{124continue;125}126drectory.Seek(dirEntryIndex);127FileSystemEntry entry;128
129if(attr == ATTR_LONG_NAME) // long name entry130{131lfnChecksum = ReadLfnEntry(drectory, lfnBuffer);132continue;133}134else135{136if(!ReadDirEntry(drectory, entry, lfnChecksum, lfnBuffer))137{138return false;139}140lfnChecksum = -1;141}142lfnBuffer.Clear();143bool stop = !directoryLister.DirectoryEntry(entry);144
145if(stop)146{147_lastError = ErrOK;148return true;149}150}151_lastError = ErrOK;152return true;153}154
155int FatFs::ReadLfnEntry(BinaryStream<Fs::File> &reader, DataBuffer &lfnBuffer)156{157uint8_t lfnSequence = reader.Read();158if ((lfnSequence & 0x1F) == 0)159{160return -1;161}162if((lfnSequence & 0x40) != 0) // last LFN entry for item163{164lfnBuffer.Clear();165lfnSequence &= 0x1F;166lfnBuffer.InsertFront(lfnSequence * LfnNameChunkBytes);167}168
169lfnBuffer.Seek((lfnSequence - 1) * LfnNameChunkBytes);170
171for(int i = 0; i < 5; i++)172{173lfnBuffer.WriteU16Le( reader.ReadU16Le());174}175
176reader.Read(); // attributes177uint8_t type = reader.Read();178if(type != 0) // not type LFN entry179{180return -1;181}182int lfnChecksum = reader.Read();183
184for(int i = 0; i < 6; i++)185{186lfnBuffer.WriteU16Le(reader.ReadU16Le());187}188
189/*uint16_t fstClusLO = */reader.ReadU16Le(); // always 0190for(int i = 0; i < 2; i++)191{192lfnBuffer.WriteU16Le(reader.ReadU16Le());193}194return lfnChecksum;195}196
197bool FatFs::ReadDirEntry(BinaryStream<Fs::File> &reader, FileSystemEntry &entry, int lfnChecksum, DataBuffer &lfnBuffer)198{199uint8_t shortName[12];200reader.Read(shortName, 11);201shortName[11] = 0;202if(shortName[0] == 0x05)203{204shortName[0] = 0xE5;205}206uint8_t entryNameCecksum = ShortNameCheckSum(shortName);207if(lfnChecksum >= 0 && entryNameCecksum == lfnChecksum)208{209size_t lfnSize = lfnBuffer.Size() / 2;210lfnBuffer.Seek(0);211size_t utf8Size = 0;212for (size_t i = 0; i < lfnSize; i++)213{214uint16_t c = lfnBuffer.ReadU16Le();215if (!c)216{217break;218}219utf8Size += Utf8Encoding<uint16_t>::EncodedLen(c);220}221
222lfnBuffer.Seek(0);223uint8_t *utf8Buffer = new (std::nothrow) uint8_t[utf8Size + 1];224uint8_t *utf8ptr = utf8Buffer;225for (size_t i = 0; i < lfnSize; i++)226{227uint16_t c = lfnBuffer.ReadU16Le();228if (!c)229{230break;231}232Utf8Encoding<uint16_t>::Encode(utf8ptr,c);233}234utf8Buffer[utf8Size] = 0;235entry.SetName(utf8Buffer, utf8Size, false);236}else237{238uint8_t decodedName[12];239size_t nameLen = DecodeShortName(shortName, decodedName);240entry.SetName(decodedName, nameLen);241}242
243uint8_t attr = reader.Read();244uint8_t NTRes = reader.Read();245uint8_t crtTimeTenth = reader.Read();246uint16_t crtTime = reader.ReadU16Le();247uint16_t crtDate = reader.ReadU16Le();248uint16_t lstAccDate = reader.ReadU16Le();249uint16_t fstClusHI = reader.ReadU16Le();250uint16_t wrtTime = reader.ReadU16Le();251uint16_t wrtDate = reader.ReadU16Le();252uint16_t fstClusLO = reader.ReadU16Le();253uint32_t size = reader.ReadU32Le();254
255entry.SetSize(size);256entry.SetAttributes((Fs::FileAttributes)attr);257entry.SetNode(ClusterToSector(fstClusLO | (((uint32_t)fstClusHI) << 16)));258return true;259}260
261uint32_t FatFs::ReadFat(uint32_t sector, unsigned fatNum)262{263if(sector == _fat.eocMarker)264return _fat.eocMarker;265
266uint32_t cluster = SectorToClaster(sector);267uint32_t fatEntryOffset;268if(_fat.type == Fat12)269{270fatEntryOffset = cluster + cluster / 2;271} else if(_fat.type == Fat16)272{273fatEntryOffset = cluster * 2;274}else275{276fatEntryOffset = cluster * 4;277}278
279uint32_t fatEntrySector = _fat.reservedSectorCount +280(fatEntryOffset / _fat.bytesPerSector) +281fatNum * _fat.FATsize;282uint32_t fatEntryOffsetInSector = fatEntryOffset % _fat.bytesPerSector;283
284MemoryStream reader = ReadSector(fatEntrySector);285if(GetError() != ErrOK)286{287return _fat.eocMarker;288}289reader.Seek(fatEntryOffsetInSector);290uint32_t result = _fat.eocMarker;291
292if(_fat.type == Fat12)293{294if(fatEntryOffsetInSector == uint32_t(_fat.bytesPerSector - 1))295{296result = reader.Read();297MemoryStream reader = ReadSector(fatEntrySector + 1);298result |= uint16_t(reader.Read()) << 8;299}else{300result = reader.ReadU16Le();301}302
303if((cluster & 1) != 0)304{305result >>= 4;306}307result &= 0X0fff;308} else if(_fat.type == Fat16)309{310result = reader.ReadU16Le();311}else312{313result = reader.ReadU32Le() & 0x0fffffff;314}315result = ClusterToSector(result);316return result;317}318
319bool WriteFat(uint32_t cluster, uint32_t nextCluster)320{321return false;322}323
324uint32_t FatFs::GetParameter(FsParams param)325{326switch(param)327{328case BlockSize: return _fat.bytesPerSector;329case ChunkSize: return _fat.bytesPerSector * _fat.sectorPerCluster;330case BlocksInChunk: return _fat.sectorPerCluster;331case TotalBlocks:332case UsedBlocks:333default: return 0;334}335}336
337uint32_t FatFs::GetBlocksPerNode(Fs::FsNode node)338{339bool fat12_16_rootDir = _fat.rootDirSectors > 0 && node == RootDirectory();340if(fat12_16_rootDir)341{342return _fat.rootDirSectors;343}344return _fat.sectorPerCluster;345}346
347FsNode FatFs::GetNextChunk(FsNode node)348{349return ReadFat((uint32_t)node, 0);350}351
352FsNode FatFs::AllocNextChunk(FsNode parentNode)353{354return FsNode(0);355}356
357FsNode FatFs::CreateNode(FsNode parentDir, Fs::FileAttributes attributes, uint8_t *nodeName)358{359return FsNode(0);360}361
362bool FatFs::ReadBlock(FsNode node, uint8_t *buffer)363{364if(!_device.ReadPage((uint32_t)node, buffer, _fat.bytesPerSector, 0))365{366_lastError = ErrIoFailed;367return false;368}369_lastError = ErrOK;370return true;371}372
373bool FatFs::WriteBlock(FsNode node, const uint8_t *buffer)374{375if(!_device.WritePage((uint32_t)node, buffer, _fat.bytesPerSector, 0))376{377_lastError = ErrIoFailed;378return false;379}380_lastError = ErrOK;381return true;382}383
384void FatFs::Unmount()385{386if(_sectorBuffer)387{388delete [] _sectorBuffer;389}390_sectorBuffer = nullptr;391_fat = FatInfo();392}393
394bool FatFs::Mount()395{396_fat = FatInfo();397if(!_device.Enable())398{399_lastError = ErrDeviceNotReady;400return false;401}402
403if(_sectorBuffer)404{405delete [] _sectorBuffer;406}407
408_fat.firstSector = 0;409_fat.bytesPerSector = SectorSize;410_sectorBuffer = new (std::nothrow) uint8_t[_fat.bytesPerSector];411
412// read boot sector413MemoryStream reader = ReadSector(_fat.firstSector);414if(GetError() != ErrOK)415{416return false;417}418reader.Seek(0);419uint8_t c = reader.Read();420if(c != 0xE9 && c != 0xEB) // first setor is MBR421{422reader.Seek(446 + 8);423_fat.firstSector = reader.ReadU32Le();424reader.Seek(510);425uint16_t sig = reader.ReadU16Le();426
427if(sig != BootSignatureVal)428{429_lastError = ErrInvalidFs;430return false;431}432
433reader = ReadSector(_fat.firstSector);434if(GetError() != ErrOK)435{436return false;437}438uint8_t c = reader.Read();439if(c != 0xE9 && c != 0xEB)440{441_lastError = ErrInvalidFs;442return false;443}444}445reader.Seek(11);446_fat.bytesPerSector = reader.ReadU16Le();447_fat.sectorPerCluster = reader.Read();448_fat.reservedSectorCount = reader.ReadU16Le();449_fat.numberofFATs = reader.Read();450_fat.rootEntCnt = reader.ReadU16Le();451_fat.totalSectors = reader.ReadU16Le();452/*uint8_t mediaType = */reader.Read();453_fat.FATsize = reader.ReadU16Le();454/*uint16_t sectorsPerTrack = */reader.ReadU16Le();455/*uint16_t numberofHeads = */reader.ReadU16Le();456_fat.hiddenSectors = reader.ReadU32Le();457uint32_t totalSectors_F32 = reader.ReadU32Le();458
459if(_fat.bytesPerSector > SectorSize)460{461delete [] _sectorBuffer;462_sectorBuffer = new (std::nothrow) uint8_t[_fat.bytesPerSector];463}464
465if(_fat.totalSectors == 0)466_fat.totalSectors = totalSectors_F32;467
468uint32_t fat32RootCluster = 0;469if(_fat.FATsize == 0)470{471_fat.FATsize = reader.ReadU32Le();472/*uint16_t extFlags = */reader.ReadU16Le();473/*uint16_t FSversion = */reader.ReadU16Le();474fat32RootCluster = reader.ReadU32Le();475}476reader.Seek(510);477uint16_t sig = reader.ReadU16Le();478if(sig != 0xaa55)479{480_lastError = ErrInvalidFs;481return false;482}483
484_fat.rootDirSectors = (_fat.rootEntCnt * 32 + _fat.bytesPerSector - 1) / _fat.bytesPerSector;485_fat.firstDataSector = _fat.rootDirSectors + _fat.reservedSectorCount + _fat.FATsize * _fat.numberofFATs;486uint32_t dataSec = _fat.totalSectors - (_fat.reservedSectorCount + _fat.FATsize * _fat.numberofFATs + _fat.rootDirSectors);487_fat.countofClusters = dataSec / _fat.sectorPerCluster;488if(fat32RootCluster == 0)489{490_fat.rootSector = (_fat.reservedSectorCount + _fat.FATsize * _fat.numberofFATs);491}else492{493_fat.rootSector = ClusterToSector(fat32RootCluster);494}495
496if(_fat.countofClusters < 4085)497{498_fat.type = Fat12;499_fat.eocMarker = 0x0FF8;500} else if(_fat.countofClusters < 65525)501{502_fat.type = Fat16;503_fat.eocMarker = 0xFFF8;504} else505{506_fat.type = Fat32;507_fat.eocMarker = 0x0FFFFFF8;508}509
510return true;511}512
513}
514}
515