123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /**
- * Copyright (c) 2011-2022 Bill Greiman
- * This file is part of the SdFat library for SD memory cards.
- *
- * MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- #ifndef ExFatPartition_h
- #define ExFatPartition_h
- /**
- * \file
- * \brief ExFatPartition include file.
- */
- #include "../common/FsBlockDevice.h"
- #include "../common/FsCache.h"
- #include "../common/FsStructs.h"
- #include "../common/SysCall.h"
- /** Set EXFAT_READ_ONLY non-zero for read only */
- #ifndef EXFAT_READ_ONLY
- #define EXFAT_READ_ONLY 0
- #endif // EXFAT_READ_ONLY
- /** Type for exFAT partition */
- const uint8_t FAT_TYPE_EXFAT = 64;
- class ExFatFile;
- //------------------------------------------------------------------------------
- /**
- * \struct DirPos_t
- * \brief Internal type for position in directory file.
- */
- struct DirPos_t {
- /** current cluster */
- uint32_t cluster;
- /** offset */
- uint32_t position;
- /** directory is contiguous */
- bool isContiguous;
- };
- //==============================================================================
- /**
- * \class ExFatPartition
- * \brief Access exFat partitions on raw file devices.
- */
- class ExFatPartition {
- public:
- ExFatPartition() = default;
- /** \return the number of bytes in a cluster. */
- uint32_t bytesPerCluster() const { return m_bytesPerCluster; }
- /** \return the power of two for bytesPerCluster. */
- uint8_t bytesPerClusterShift() const {
- return m_bytesPerSectorShift + m_sectorsPerClusterShift;
- }
- /** \return the number of bytes in a sector. */
- uint16_t bytesPerSector() const { return m_bytesPerSector; }
- /** \return the power of two for bytesPerSector. */
- uint8_t bytesPerSectorShift() const { return m_bytesPerSectorShift; }
- /** Clear the cache and returns a pointer to the cache. Not for normal apps.
- * \return A pointer to the cache buffer or zero if an error occurs.
- */
- uint8_t* cacheClear() { return m_dataCache.clear(); }
- /** \return the cluster count for the partition. */
- uint32_t clusterCount() const { return m_clusterCount; }
- /** \return the cluster heap start sector. */
- uint32_t clusterHeapStartSector() const { return m_clusterHeapStartSector; }
- /** End access to volume
- * \return pointer to sector size buffer for format.
- */
- uint8_t* end() {
- m_fatType = 0;
- return cacheClear();
- }
- /** \return the FAT length in sectors */
- uint32_t fatLength() const { return m_fatLength; }
- /** \return the FAT start sector number. */
- uint32_t fatStartSector() const { return m_fatStartSector; }
- /** \return Type FAT_TYPE_EXFAT for exFAT partition or zero for error. */
- uint8_t fatType() const { return m_fatType; }
- /** \return free cluster count or -1 if an error occurs. */
- int32_t freeClusterCount();
- /** Initialize a exFAT partition.
- * \param[in] dev The blockDevice for the partition.
- * \param[in] part The partition to be used. Legal values for \a part are
- * 1-4 to use the corresponding partition on a device formatted with
- * a MBR, Master Boot Record, or zero if the device is formatted as
- * a super floppy with the FAT boot sector in sector volStart.
- * \param[in] volStart location of volume if part is zero.
- *
- * \return true for success or false for failure.
- */
- bool init(FsBlockDevice* dev, uint8_t part, uint32_t volStart = 0);
- /**
- * Check for device busy.
- *
- * \return true if busy else false.
- */
- bool isBusy() { return m_blockDev->isBusy(); }
- /** \return the root directory start cluster number. */
- uint32_t rootDirectoryCluster() const { return m_rootDirectoryCluster; }
- /** \return the root directory length. */
- uint32_t rootLength();
- /** \return the number of sectors in a cluster. */
- uint32_t sectorsPerCluster() const { return 1UL << m_sectorsPerClusterShift; }
- #ifndef DOXYGEN_SHOULD_SKIP_THIS
- uint32_t __attribute__((error("use sectorsPerCluster()"))) blocksPerCluster();
- #endif // DOXYGEN_SHOULD_SKIP_THIS
- /** \return the power of two for sectors per cluster. */
- uint8_t sectorsPerClusterShift() const { return m_sectorsPerClusterShift; }
- //----------------------------------------------------------------------------
- #ifndef DOXYGEN_SHOULD_SKIP_THIS
- void checkUpcase(print_t* pr);
- bool printDir(print_t* pr, ExFatFile* file);
- void dmpBitmap(print_t* pr);
- void dmpCluster(print_t* pr, uint32_t cluster, uint32_t offset,
- uint32_t count);
- void dmpFat(print_t* pr, uint32_t start, uint32_t count);
- void dmpSector(print_t* pr, uint32_t sector);
- bool printVolInfo(print_t* pr);
- void printFat(print_t* pr);
- void printUpcase(print_t* pr);
- #endif // DOXYGEN_SHOULD_SKIP_THIS
- //----------------------------------------------------------------------------
- private:
- /** ExFatFile allowed access to private members. */
- friend class ExFatFile;
- uint32_t bitmapFind(uint32_t cluster, uint32_t count);
- bool bitmapModify(uint32_t cluster, uint32_t count, bool value);
- //----------------------------------------------------------------------------
- // Cache functions.
- uint8_t* bitmapCachePrepare(uint32_t sector, uint8_t option) {
- #if USE_EXFAT_BITMAP_CACHE
- return m_bitmapCache.prepare(sector, option);
- #else // USE_EXFAT_BITMAP_CACHE
- return m_dataCache.prepare(sector, option);
- #endif // USE_EXFAT_BITMAP_CACHE
- }
- void cacheInit(FsBlockDevice* dev) {
- #if USE_EXFAT_BITMAP_CACHE
- m_bitmapCache.init(dev);
- #endif // USE_EXFAT_BITMAP_CACHE
- m_dataCache.init(dev);
- }
- bool cacheSync() {
- #if USE_EXFAT_BITMAP_CACHE
- return m_bitmapCache.sync() && m_dataCache.sync() && syncDevice();
- #else // USE_EXFAT_BITMAP_CACHE
- return m_dataCache.sync() && syncDevice();
- #endif // USE_EXFAT_BITMAP_CACHE
- }
- void dataCacheDirty() { m_dataCache.dirty(); }
- void dataCacheInvalidate() { m_dataCache.invalidate(); }
- uint8_t* dataCachePrepare(uint32_t sector, uint8_t option) {
- return m_dataCache.prepare(sector, option);
- }
- uint32_t dataCacheSector() { return m_dataCache.sector(); }
- bool dataCacheSync() { return m_dataCache.sync(); }
- //----------------------------------------------------------------------------
- uint32_t clusterMask() const { return m_clusterMask; }
- uint32_t clusterStartSector(uint32_t cluster) {
- return m_clusterHeapStartSector +
- ((cluster - 2) << m_sectorsPerClusterShift);
- }
- uint8_t* dirCache(DirPos_t* pos, uint8_t options);
- int8_t dirSeek(DirPos_t* pos, uint32_t offset);
- int8_t fatGet(uint32_t cluster, uint32_t* value);
- bool fatPut(uint32_t cluster, uint32_t value);
- uint32_t chainSize(uint32_t cluster);
- bool freeChain(uint32_t cluster);
- uint16_t sectorMask() const { return m_sectorMask; }
- bool syncDevice() { return m_blockDev->syncDevice(); }
- bool cacheSafeRead(uint32_t sector, uint8_t* dst) {
- return m_dataCache.cacheSafeRead(sector, dst);
- }
- bool cacheSafeWrite(uint32_t sector, const uint8_t* src) {
- return m_dataCache.cacheSafeWrite(sector, src);
- }
- bool cacheSafeRead(uint32_t sector, uint8_t* dst, size_t count) {
- return m_dataCache.cacheSafeRead(sector, dst, count);
- }
- bool cacheSafeWrite(uint32_t sector, const uint8_t* src, size_t count) {
- return m_dataCache.cacheSafeWrite(sector, src, count);
- }
- bool readSector(uint32_t sector, uint8_t* dst) {
- return m_blockDev->readSector(sector, dst);
- }
- bool writeSector(uint32_t sector, const uint8_t* src) {
- return m_blockDev->writeSector(sector, src);
- }
- //----------------------------------------------------------------------------
- static const uint8_t m_bytesPerSectorShift = 9;
- static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift;
- static const uint16_t m_sectorMask = m_bytesPerSector - 1;
- //----------------------------------------------------------------------------
- #if USE_EXFAT_BITMAP_CACHE
- FsCache m_bitmapCache;
- #endif // USE_EXFAT_BITMAP_CACHE
- FsCache m_dataCache;
- uint32_t m_bitmapStart;
- uint32_t m_fatStartSector;
- uint32_t m_fatLength;
- uint32_t m_clusterHeapStartSector;
- uint32_t m_clusterCount;
- uint32_t m_rootDirectoryCluster;
- uint32_t m_clusterMask;
- uint32_t m_bytesPerCluster;
- FsBlockDevice* m_blockDev;
- uint8_t m_fatType = 0;
- uint8_t m_sectorsPerClusterShift;
- };
- #endif // ExFatPartition_h
|