void _FAT_partition_writeFSinfo(PARTITION * partition) { if(partition->filesysType != FS_FAT32) return; uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); if (!sectorBuffer) return; memset(sectorBuffer, 0, partition->bytesPerSector); // Read first sector of disc if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) { _FAT_mem_free(sectorBuffer); return; } if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4)) { _FAT_mem_free(sectorBuffer); return; } u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster); u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster); // Write first sector of disc _FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer); _FAT_mem_free(sectorBuffer); }
void _FAT_partition_readFSinfo(PARTITION * partition) { if(partition->filesysType != FS_FAT32) return; uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); if (!sectorBuffer) return; memset(sectorBuffer, 0, partition->bytesPerSector); // Read first sector of disc if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) { _FAT_mem_free(sectorBuffer); return; } if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4) != 0 || u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0) { //sector does not yet exist, create one! _FAT_partition_createFSinfo(partition); } else { partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster); if(partition->fat.numberFreeCluster == 0xffffffff) { _FAT_updateFS_INFO(partition,sectorBuffer); partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster); } partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster); } _FAT_mem_free(sectorBuffer); }
void _FAT_cache_destructor (CACHE* cache) { unsigned int i; // Clear out cache before destroying it _FAT_cache_flush(cache); // Free memory in reverse allocation order for (i = 0; i < cache->numberOfPages; i++) { _FAT_mem_free (cache->cacheEntries[i].cache); } _FAT_mem_free (cache->cacheEntries); _FAT_mem_free (cache); }
bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize) { PARTITION* partition; devoptab_t* devops; char* nameCopy; devops = _FAT_mem_allocate (sizeof(devoptab_t) + strlen(name) + 1); if (!devops) { return false; } // Use the space allocated at the end of the devoptab struct for storing the name nameCopy = (char*)(devops+1); // Initialize the file system partition = _FAT_partition_constructor (interface, cacheSize, startSector); if (!partition) { _FAT_mem_free (devops); return false; } // Add an entry for this device to the devoptab table memcpy (devops, &dotab_fat, sizeof(dotab_fat)); strcpy (nameCopy, name); devops->name = nameCopy; devops->deviceData = partition; My_AddDevice (devops); return true; }
void fatUnmount (const char* name) { devoptab_t *devops; PARTITION* partition; if(!name) return; devops = (devoptab_t*)GetDeviceOpTab (name); if (!devops) { return; } // Perform a quick check to make sure we're dealing with a libfat controlled device if (devops->open_r != dotab_fat.open_r) { return; } if (RemoveDevice (name) == -1) { return; } partition = (PARTITION*)devops->deviceData; _FAT_partition_destructor (partition); _FAT_mem_free (devops); }
void _FAT_partition_destructor (PARTITION* partition) { FILE_STRUCT* nextFile; _FAT_lock(&partition->lock); // Synchronize open files nextFile = partition->firstOpenFile; while (nextFile) { _FAT_syncToDisc (nextFile); nextFile = nextFile->nextOpenFile; } // Write out the fs info sector _FAT_partition_writeFSinfo(partition); // Free memory used by the cache, writing it to disc at the same time _FAT_cache_destructor (partition->cache); // Unlock the partition and destroy the lock _FAT_unlock(&partition->lock); _FAT_lock_deinit(&partition->lock); // Free memory used by the partition _FAT_mem_free (partition); }
void _FAT_partition_createFSinfo(PARTITION * partition) { if(partition->readOnly || partition->filesysType != FS_FAT32) return; uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); if (!sectorBuffer) return; memset(sectorBuffer, 0, partition->bytesPerSector); int i; for(i = 0; i < 4; ++i) { sectorBuffer[FSIB_SIG1+i] = FS_INFO_SIG1[i]; sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i]; } partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition); u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster); u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster); sectorBuffer[FSIB_bootSig_55] = 0x55; sectorBuffer[FSIB_bootSig_AA] = 0xAA; _FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer); _FAT_mem_free(sectorBuffer); }
void fatGetVolumeLabel (const char* name, char *label) { devoptab_t *devops; PARTITION* partition; char *buf; int namelen,i; if(!name || !label) return; namelen = strlen(name); buf=(char*)_FAT_mem_allocate(sizeof(char)*namelen+2); strcpy(buf,name); if (name[namelen-1] == '/') { buf[namelen-1]='\0'; namelen--; } if (name[namelen-1] != ':') { buf[namelen]=':'; buf[namelen+1]='\0'; } devops = (devoptab_t*)GetDeviceOpTab(buf); for(i=0;buf[i]!='\0' && buf[i]!=':';i++); if (!devops || strncasecmp(buf,devops->name,i)) { _FAT_mem_free(buf); return; } _FAT_mem_free(buf); // Perform a quick check to make sure we're dealing with a libfat controlled device if (devops->open_r != dotab_fat.open_r) { return; } partition = (PARTITION*)devops->deviceData; if(!_FAT_directory_getVolumeLabel(partition, label)) { strncpy(label,partition->label,11); label[11]='\0'; } if(!strncmp(label, "NO NAME", 7)) label[0]='\0'; }
sec_t FindFirstValidPartition(const DISC_INTERFACE* disc) { uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(MAX_SECTOR_SIZE); if (!sectorBuffer) return 0; sec_t ret = FindFirstValidPartition_buf(disc, sectorBuffer); _FAT_mem_free(sectorBuffer); return ret; }
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) { uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(MAX_SECTOR_SIZE); if (!sectorBuffer) return NULL; PARTITION *ret = _FAT_partition_constructor_buf(disc, cacheSize, sectorsPerPage, startSector, sectorBuffer); _FAT_mem_free(sectorBuffer); return ret; }
bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) { PARTITION* partition; struct devoptab_t* devops; //char* nameCopy; if(!name || strlen(name) > 8 || !interface) return false; if(!interface->startup()) return false; if(!interface->isInserted()) return false; //char devname[10]; //sprintf(devname, "%s:", name); //if(FindDevice(devname) >= 0) // return true; devops = (struct devoptab_t*)_FAT_mem_allocate (sizeof(struct devoptab_t) + strlen(name) + 1); if (!devops) { return false; } #ifdef LIBFAT_PC _sole_device = devops; #endif // Use the space allocated at the end of the devoptab struct for storing the name //nameCopy = (char*)(devops+1); // Initialize the file system partition = _FAT_partition_constructor (interface, cacheSize, SectorsPerPage, startSector); if (!partition) { _FAT_mem_free (devops); return false; } // Add an entry for this device to the devoptab table memcpy (devops, &dotab_fat, sizeof(dotab_fat)); //strcpy (nameCopy, name); //devops->name = nameCopy; devops->deviceData = partition; //AddDevice (devops); return true; }
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, unsigned int bytesPerSector) { CACHE* cache; unsigned int i; CACHE_ENTRY* cacheEntries; if (numberOfPages < 2) { numberOfPages = 2; } if (sectorsPerPage < 8) { sectorsPerPage = 8; } cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE)); if (cache == NULL) { return NULL; } cache->disc = discInterface; cache->endOfPartition = endOfPartition; cache->numberOfPages = numberOfPages; cache->sectorsPerPage = sectorsPerPage; cache->bytesPerSector = bytesPerSector; cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages); if (cacheEntries == NULL) { _FAT_mem_free (cache); return NULL; } for (i = 0; i < numberOfPages; i++) { cacheEntries[i].sector = CACHE_FREE; cacheEntries[i].count = 0; cacheEntries[i].last_access = 0; cacheEntries[i].dirty = false; cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * bytesPerSector ); } cache->cacheEntries = cacheEntries; return cache; }
void _FAT_partition_createFSinfo(PARTITION * partition) { if(partition->readOnly || partition->filesysType != FS_FAT32) return; uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); if (!sectorBuffer) return; memset(sectorBuffer, 0, partition->bytesPerSector); int i; for(i = 0; i < 4; ++i) { sectorBuffer[FSIB_SIG1+i] = FS_INFO_SIG1[i]; sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i]; } sectorBuffer[FSIB_bootSig_55] = 0x55; sectorBuffer[FSIB_bootSig_AA] = 0xAA; _FAT_updateFS_INFO(partition,sectorBuffer); _FAT_mem_free(sectorBuffer); }
void fatUnmountDirect (struct devoptab_t *devops) { PARTITION* partition = (PARTITION*)devops->deviceData; _FAT_partition_destructor (partition); _FAT_mem_free (devops); _sole_device = NULL; }
PARTITION* _FAT_partition_constructor_buf (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector, uint8_t *sectorBuffer) { PARTITION* partition; // Read first sector of disc if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } // Make sure it is a valid MBR or boot sector if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA && sectorBuffer[BPB_bootSig_AA] != 0xAB)) { return NULL; } if (startSector != 0) { // We're told where to start the partition, so just accept it } else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check if there is a FAT string, which indicates this is a boot sector startSector = 0; } else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check for FAT32 startSector = 0; } else { startSector = FindFirstValidPartition_buf(disc, sectorBuffer); if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } } if (!isValidMBR(sectorBuffer)) { return NULL; } partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); if (partition == NULL) { return NULL; } // Init the partition lock _FAT_lock_init(&partition->lock); if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT16_volumeLabel), 11); else strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT32_volumeLabel), 11); partition->label[11] = '\0'; // Set partition's disc interface partition->disc = disc; // Store required information about the file system partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); if (partition->fat.sectorsPerFat == 0) { partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); } partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); if (partition->numberOfSectors == 0) { partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); } partition->bytesPerSector = u8array_to_u16(sectorBuffer, BPB_bytesPerSector); if(partition->bytesPerSector < MIN_SECTOR_SIZE || partition->bytesPerSector > MAX_SECTOR_SIZE) { // Unsupported sector size _FAT_mem_free(partition); return NULL; } partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster]; partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); partition->dataStart = partition->rootDirStart + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; //FS info sector partition->fsInfoSector = startSector + (u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) ? u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) : 1); // Store info about FAT uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; partition->fat.firstFree = CLUSTER_FIRST; partition->fat.numberFreeCluster = 0; partition->fat.numberLastAllocCluster = 0; if (clusterCount < CLUSTERS_PER_FAT12) { partition->filesysType = FS_FAT12; // FAT12 volume } else if (clusterCount < CLUSTERS_PER_FAT16) { partition->filesysType = FS_FAT16; // FAT16 volume } else { partition->filesysType = FS_FAT32; // FAT32 volume } if (partition->filesysType != FS_FAT32) { partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; } else { // Set up for the FAT32 way partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); // Check if FAT mirroring is enabled if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) { // Use the active FAT partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); } } // Create a cache to use partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors, partition->bytesPerSector); // Set current directory to the root partition->cwdCluster = partition->rootDirCluster; // Check if this disc is writable, and set the readOnly property appropriately partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); // There are currently no open files on this partition partition->openFileCount = 0; partition->firstOpenFile = NULL; _FAT_partition_readFSinfo(partition); return partition; }