Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
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;
}
Example #5
0
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);
}
Example #6
0
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);
}
Example #7
0
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);
}
Example #8
0
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';
}
Example #9
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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);
}
Example #14
0
void fatUnmountDirect (struct devoptab_t *devops) {
	PARTITION* partition = (PARTITION*)devops->deviceData;
	_FAT_partition_destructor (partition);
	_FAT_mem_free (devops);
	_sole_device = NULL;
}
Example #15
0
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;
}