| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 | 
							- /**
 
-  * Copyright (c) 2011-2021 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.
 
-  */
 
- #define DBG_FILE "ExFatPartition.cpp"
 
- #include "../common/DebugMacros.h"
 
- #include "ExFatLib.h"
 
- //------------------------------------------------------------------------------
 
- // return 0 if error, 1 if no space, else start cluster.
 
- uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) {
 
-   uint32_t start = cluster ? cluster - 2 : m_bitmapStart;
 
-   if (start >= m_clusterCount) {
 
-     start = 0;
 
-   }
 
-   uint32_t endAlloc = start;
 
-   uint32_t bgnAlloc = start;
 
-   uint16_t sectorSize = 1 << m_bytesPerSectorShift;
 
-   size_t i = (start >> 3) & (sectorSize - 1);
 
-   uint8_t* cache;
 
-   uint8_t mask = 1 << (start & 7);
 
-   while (true) {
 
-     uint32_t sector = m_clusterHeapStartSector +
 
-                      (endAlloc >> (m_bytesPerSectorShift + 3));
 
-     cache = bitmapCachePrepare(sector, FsCache::CACHE_FOR_READ);
 
-     if (!cache) {
 
-       return 0;
 
-     }
 
-     for (; i < sectorSize; i++) {
 
-       for (; mask; mask <<= 1) {
 
-         endAlloc++;
 
-         if (!(mask & cache[i])) {
 
-           if ((endAlloc - bgnAlloc) == count) {
 
-             if (cluster == 0 && count == 1) {
 
-               // Start at found sector.  bitmapModify may increase this.
 
-               m_bitmapStart = bgnAlloc;
 
-             }
 
-             return bgnAlloc + 2;
 
-           }
 
-         } else {
 
-           bgnAlloc = endAlloc;
 
-         }
 
-         if (endAlloc == start) {
 
-           return 1;
 
-         }
 
-         if (endAlloc >= m_clusterCount) {
 
-           endAlloc = bgnAlloc = 0;
 
-           i = sectorSize;
 
-           break;
 
-         }
 
-       }
 
-       mask = 1;
 
-     }
 
-     i = 0;
 
-   }
 
-   return 0;
 
- }
 
- //------------------------------------------------------------------------------
 
- bool ExFatPartition::bitmapModify(uint32_t cluster,
 
-                                   uint32_t count, bool value) {
 
-   uint32_t sector;
 
-   uint32_t start = cluster - 2;
 
-   size_t i;
 
-   uint8_t* cache;
 
-   uint8_t mask;
 
-   cluster -= 2;
 
-   if ((start + count) > m_clusterCount) {
 
-     DBG_FAIL_MACRO;
 
-     goto fail;
 
-   }
 
-   if (value) {
 
-     if (start  <= m_bitmapStart && m_bitmapStart < (start + count)) {
 
-       m_bitmapStart = (start + count) < m_clusterCount ? start + count : 0;
 
-     }
 
-   } else {
 
-     if (start < m_bitmapStart) {
 
-       m_bitmapStart = start;
 
-     }
 
-   }
 
-   mask = 1 << (start & 7);
 
-   sector = m_clusterHeapStartSector +
 
-                    (start >> (m_bytesPerSectorShift + 3));
 
-   i = (start >> 3) & m_sectorMask;
 
-   while (true) {
 
-     cache = bitmapCachePrepare(sector++, FsCache::CACHE_FOR_WRITE);
 
-     if (!cache) {
 
-       DBG_FAIL_MACRO;
 
-       goto fail;
 
-     }
 
-     for (; i < m_bytesPerSector; i++) {
 
-       for (; mask; mask <<= 1) {
 
-         if (value == static_cast<bool>(cache[i] & mask)) {
 
-           DBG_FAIL_MACRO;
 
-           goto fail;
 
-         }
 
-         cache[i] ^= mask;
 
-         if (--count == 0) {
 
-           return true;
 
-         }
 
-       }
 
-       mask = 1;
 
-     }
 
-     i = 0;
 
-   }
 
-  fail:
 
-   return false;
 
- }
 
- //------------------------------------------------------------------------------
 
- uint32_t ExFatPartition::chainSize(uint32_t cluster) {
 
-   uint32_t n = 0;
 
-   int8_t status;
 
-   do {
 
-     status = fatGet(cluster, & cluster);
 
-     if (status < 0) return 0;
 
-     n++;
 
-   } while (status);
 
-   return n;
 
- }
 
- //------------------------------------------------------------------------------
 
- uint8_t* ExFatPartition::dirCache(DirPos_t* pos, uint8_t options) {
 
-   uint32_t sector = clusterStartSector(pos->cluster);
 
-   sector += (m_clusterMask & pos->position) >> m_bytesPerSectorShift;
 
-   uint8_t* cache = dataCachePrepare(sector, options);
 
-   return cache ? cache + (pos->position & m_sectorMask) : nullptr;
 
- }
 
- //------------------------------------------------------------------------------
 
- // return -1 error, 0 EOC, 1 OK
 
- int8_t ExFatPartition::dirSeek(DirPos_t* pos, uint32_t offset) {
 
-   int8_t status;
 
-   uint32_t tmp = (m_clusterMask & pos->position) + offset;
 
-   pos->position += offset;
 
-   tmp >>= bytesPerClusterShift();
 
-   while (tmp--) {
 
-     if (pos->isContiguous) {
 
-       pos->cluster++;
 
-     } else {
 
-       status = fatGet(pos->cluster, &pos->cluster);
 
-       if (status != 1) {
 
-         return status;
 
-       }
 
-     }
 
-   }
 
-   return 1;
 
- }
 
- //------------------------------------------------------------------------------
 
- // return -1 error, 0 EOC, 1 OK
 
- int8_t ExFatPartition::fatGet(uint32_t cluster, uint32_t* value) {
 
-   uint8_t* cache;
 
-   uint32_t next;
 
-   uint32_t sector;
 
-   if (cluster > (m_clusterCount + 1)) {
 
-     DBG_FAIL_MACRO;
 
-     return -1;
 
-   }
 
-   sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 2));
 
-   cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
 
-   if (!cache) {
 
-     return -1;
 
-   }
 
-   next = getLe32(cache + ((cluster << 2) & m_sectorMask));
 
-   if (next == EXFAT_EOC) {
 
-     return 0;
 
-   }
 
-   *value = next;
 
-   return 1;
 
- }
 
- //------------------------------------------------------------------------------
 
- bool ExFatPartition::fatPut(uint32_t cluster, uint32_t value) {
 
-   uint32_t sector;
 
-   uint8_t* cache;
 
-   if (cluster < 2 || cluster > (m_clusterCount + 1)) {
 
-     DBG_FAIL_MACRO;
 
-     goto fail;
 
-   }
 
-   sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 2));
 
-   cache = dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
 
-   if (!cache) {
 
-     DBG_FAIL_MACRO;
 
-     goto fail;
 
-   }
 
-   setLe32(cache + ((cluster << 2) & m_sectorMask), value);
 
-   return true;
 
-  fail:
 
-   return false;
 
- }
 
- //------------------------------------------------------------------------------
 
- bool ExFatPartition::freeChain(uint32_t cluster) {
 
-   uint32_t next;
 
-   uint32_t start = cluster;
 
-   int8_t status;
 
-   do {
 
-     status = fatGet(cluster, &next);
 
-     if (status < 0) {
 
-       DBG_FAIL_MACRO;
 
-       goto fail;
 
-     }
 
-     if (!fatPut(cluster, 0)) {
 
-       DBG_FAIL_MACRO;
 
-       goto fail;
 
-     }
 
-     if (status == 0 || (cluster + 1) != next) {
 
-       if (!bitmapModify(start, cluster - start + 1, 0)) {
 
-         DBG_FAIL_MACRO;
 
-         goto fail;
 
-       }
 
-       start = next;
 
-     }
 
-     cluster = next;
 
-   } while (status);
 
-   return true;
 
-  fail:
 
-   return false;
 
- }
 
- //------------------------------------------------------------------------------
 
- uint32_t ExFatPartition::freeClusterCount() {
 
-   uint32_t nc = 0;
 
-   uint32_t sector = m_clusterHeapStartSector;
 
-   uint32_t usedCount = 0;
 
-   uint8_t* cache;
 
-   while (true) {
 
-     cache = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
 
-     if (!cache) {
 
-       return 0;
 
-     }
 
-     for (size_t i = 0; i < m_bytesPerSector; i++) {
 
-       if (cache[i] == 0XFF) {
 
-         usedCount+= 8;
 
-       } else if (cache[i]) {
 
-         for (uint8_t mask = 1; mask ; mask <<=1) {
 
-           if ((mask & cache[i])) {
 
-             usedCount++;
 
-           }
 
-         }
 
-       }
 
-       nc += 8;
 
-       if (nc >= m_clusterCount) {
 
-         return m_clusterCount - usedCount;
 
-       }
 
-     }
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part) {
 
-   uint32_t volStart = 0;
 
-   uint8_t* cache;
 
-   pbs_t* pbs;
 
-   BpbExFat_t* bpb;
 
-   MbrSector_t* mbr;
 
-   MbrPart_t* mp;
 
-   m_fatType = 0;
 
-   m_blockDev = dev;
 
-   cacheInit(m_blockDev);
 
-   cache = dataCachePrepare(0, FsCache::CACHE_FOR_READ);
 
-   if (part > 4 || !cache) {
 
-     DBG_FAIL_MACRO;
 
-     goto fail;
 
-   }
 
-   if (part >= 1) {
 
-     mbr = reinterpret_cast<MbrSector_t*>(cache);
 
-     mp = &mbr->part[part - 1];
 
-     if (mp->type == 0) {
 
-       DBG_FAIL_MACRO;
 
-       goto fail;
 
-     }
 
-     volStart = getLe32(mp->relativeSectors);
 
-     cache = dataCachePrepare(volStart, FsCache::CACHE_FOR_READ);
 
-     if (!cache) {
 
-       DBG_FAIL_MACRO;
 
-       goto fail;
 
-     }
 
-   }
 
-   pbs = reinterpret_cast<pbs_t*>(cache);
 
-   if (strncmp(pbs->oemName, "EXFAT", 5)) {
 
-     DBG_FAIL_MACRO;
 
-     goto fail;
 
-   }
 
-   bpb = reinterpret_cast<BpbExFat_t*>(pbs->bpb);
 
-   if (bpb->bytesPerSectorShift != m_bytesPerSectorShift) {
 
-     DBG_FAIL_MACRO;
 
-     goto fail;
 
-   }
 
-   m_fatStartSector = volStart + getLe32(bpb->fatOffset);
 
-   m_fatLength = getLe32(bpb->fatLength);
 
-   m_clusterHeapStartSector = volStart + getLe32(bpb->clusterHeapOffset);
 
-   m_clusterCount = getLe32(bpb->clusterCount);
 
-   m_rootDirectoryCluster = getLe32(bpb->rootDirectoryCluster);
 
-   m_sectorsPerClusterShift = bpb->sectorsPerClusterShift;
 
-   m_bytesPerCluster = 1UL << (m_bytesPerSectorShift + m_sectorsPerClusterShift);
 
-   m_clusterMask = m_bytesPerCluster - 1;
 
-   // Set m_bitmapStart to first free cluster.
 
-   m_bitmapStart = 0;
 
-   bitmapFind(0, 1);
 
-   m_fatType = FAT_TYPE_EXFAT;
 
-   return true;
 
-  fail:
 
-   return false;
 
- }
 
- //------------------------------------------------------------------------------
 
- uint32_t ExFatPartition::rootLength() {
 
-   uint32_t nc = chainSize(m_rootDirectoryCluster);
 
-   return nc << bytesPerClusterShift();
 
- }
 
 
  |