Пример #1
0
static FF_Error_t prvPartitionAndFormatDisk( FF_Disk_t *pxDisk )
{
FF_PartitionParameters_t xPartition;
FF_Error_t xError;

	/* Create a single partition that fills all available space on the disk. */
	memset( &xPartition, '\0', sizeof( xPartition ) );
	xPartition.ulSectorCount = pxDisk->ulNumberOfSectors;
	xPartition.ulHiddenSectors = ramHIDDEN_SECTOR_COUNT;
	xPartition.xPrimaryCount = ramPRIMARY_PARTITIONS;
	xPartition.eSizeType = eSizeIsQuota;

	/* Partition the disk */
	xError = FF_Partition( pxDisk, &xPartition );
	FF_PRINTF( "FF_Partition: %s\n", ( const char * ) FF_GetErrMessage( xError ) );

	if( FF_isERR( xError ) == pdFALSE )
	{
		/* Format the partition. */
		xError = FF_Format( pxDisk, 0, pdTRUE, pdTRUE );
		FF_PRINTF( "FF_RAMDiskInit: FF_Format: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
	}

	return xError;
}
Пример #2
0
FF_T_SINT32 FF_BlockWrite(FF_IOMAN *pIoman, FF_T_UINT32 ulSectorLBA, FF_T_UINT32 ulNumSectors, void *pBuffer, FF_T_BOOL aSemLocked) {
	FF_T_SINT32 slRetVal = 0;

	if(pIoman->pPartition->TotalSectors) {
		if((ulSectorLBA + ulNumSectors) > (pIoman->pPartition->TotalSectors + pIoman->pPartition->BeginLBA)) {
			return (FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_BLOCKWRITE);
		}
	}
	
	if(pIoman->pBlkDevice->fnpWriteBlocks) do {	// Make sure we don't execute a NULL.
#ifdef	FF_BLKDEV_USES_SEM
		if (!aSemLocked || pIoman->pSemaphore != pIoman->pBlkDevSemaphore)
			FF_PendSemaphore(pIoman->pBlkDevSemaphore);
#endif
		slRetVal = pIoman->pBlkDevice->fnpWriteBlocks(pBuffer, ulSectorLBA, ulNumSectors, pIoman->pBlkDevice->pParam);
#ifdef	FF_BLKDEV_USES_SEM
		if (!aSemLocked || pIoman->pSemaphore != pIoman->pBlkDevSemaphore)
			FF_ReleaseSemaphore(pIoman->pBlkDevSemaphore);
#endif
		if(!FF_isERR(slRetVal) && FF_GETERROR(slRetVal) != FF_ERR_DRIVER_BUSY) {
			break;
		}
		FF_Sleep(FF_DRIVER_BUSY_SLEEP);
	} while (FF_TRUE);

	return slRetVal;
}
Пример #3
0
const FF_T_INT8 *FF_GetErrDescription(FF_ERROR iErrorCode, char *apBuf, int aMaxlen) {
	if (FF_isERR(iErrorCode)) {
		snprintf (apBuf, aMaxlen, "%s::%s::%s",
			FF_GetErrModule(iErrorCode),
			FF_GetErrFunction(iErrorCode),
			FF_GetErrMessage(iErrorCode));
	} else {
		snprintf (apBuf, aMaxlen, "No error");
	}
	return apBuf;
}
Пример #4
0
FF_ERROR FF_IncreaseFreeClusters(FF_IOMAN *pIoman, FF_T_UINT32 Count) {

	FF_ERROR Error;

#ifdef FF_WRITE_FREE_COUNT
	FF_BUFFER *pBuffer;
#endif

	if(!pIoman->pPartition->FreeClusterCount) {
		 pIoman->pPartition->FreeClusterCount = FF_CountFreeClusters(pIoman, &Error);
		 if(FF_isERR(Error)) {
			  return Error;
		 }
	} else {
		 pIoman->pPartition->FreeClusterCount += Count;
	}
#ifdef FF_WRITE_FREE_COUNT
	// FAT32 update the FSINFO sector.
	if(pIoman->pPartition->Type == FF_T_FAT32) {
		 // Find the FSINFO sector.
		 pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FSInfoLBA, FF_MODE_WRITE);
		 {
			  if(!pBuffer) {
					return FF_ERR_DEVICE_DRIVER_FAILED | FF_INCREASEFREECLUSTERS;
			  }

			  if(FF_getLong(pBuffer->pBuffer, 0) == 0x41615252 && FF_getLong(pBuffer->pBuffer, 484) == 0x61417272) {
					// FSINFO sector magic nums we're verified. Safe to write.
					FF_putLong(pBuffer->pBuffer, 488, pIoman->pPartition->FreeClusterCount);
					FF_putLong(pBuffer->pBuffer, 492, pIoman->pPartition->LastFreeCluster);
			  }
		 }
		 Error = FF_ReleaseBuffer(pIoman, pBuffer);
		 if(FF_isERR(Error)) {
			 return Error;
		 }
	}
#endif

	return FF_ERR_NONE;
}
Пример #5
0
/**
 *	@public
 *	@brief	Unmounts the active partition.
 *
 *	@param	pIoman	FF_IOMAN Object.
 *
 *	@return FF_ERR_NONE on success.
 **/
FF_ERROR FF_UnmountPartition(FF_IOMAN *pIoman) {
	FF_ERROR RetVal = FF_ERR_NONE;
#ifdef FF_MIRROR_FATS_UMOUNT
	FF_T_UINT i, y;
	FF_BUFFER *pBuffer;
#endif 

	if(!pIoman || !pIoman->pPartition) {
		return FF_ERR_NULL_POINTER | FF_UNMOUNTPARTITION;
	}
	if (!pIoman->pPartition->PartitionMounted)
		return FF_ERR_NONE;

	FF_PendSemaphore(pIoman->pSemaphore);	// Ensure that there are no File Handles
	{
		if(!FF_ActiveHandles(pIoman)) {
			if(pIoman->FirstFile == NULL) {
				// Release Semaphore to call this function!
				FF_ReleaseSemaphore(pIoman->pSemaphore);
				RetVal = FF_FlushCache(pIoman);			// Flush any unwritten sectors to disk.
				if(FF_isERR(RetVal)) {
					return RetVal;
				}
				// Reclaim Semaphore
				FF_PendSemaphore(pIoman->pSemaphore);
				pIoman->pPartition->PartitionMounted = FF_FALSE;

#ifdef FF_MIRROR_FATS_UMOUNT
				FF_ReleaseSemaphore(pIoman->pSemaphore);
				for(i = 0; i < pIoman->pPartition->SectorsPerFAT; i++) {
					 pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA + i, FF_MODE_READ);
					 if(!pBuffer) {
						  RetVal = FF_ERR_DEVICE_DRIVER_FAILED | FF_UNMOUNTPARTITION;
						  break;
					 }
					 for(y = 0; y < pIoman->pPartition->NumFATS; y++) {
						  FF_BlockWrite(pIoman, pIoman->pPartition->FatBeginLBA + (y*pIoman->pPartition->SectorsPerFAT) + i, 1, pBuffer->pBuffer, FF_FALSE);
					 }					 
				}
				FF_PendSemaphore(pIoman->pSemaphore);
#endif
			} else {
				RetVal = FF_ERR_IOMAN_ACTIVE_HANDLES | FF_UNMOUNTPARTITION;
			}
		} else {
			RetVal = FF_ERR_IOMAN_ACTIVE_HANDLES | FF_UNMOUNTPARTITION;	// Active handles found on the cache.
		}
	}
	FF_ReleaseSemaphore(pIoman->pSemaphore);

	return RetVal;
}
Пример #6
0
/**
 *	@private
 *	@brief	Releases a buffer resource.
 *
 *	@param	pIoman	Pointer to an FF_IOMAN object.
 *	@param	pBuffer	Pointer to an FF_BUFFER object.
 *
 **/
FF_ERROR FF_ReleaseBuffer(FF_IOMAN *pIoman, FF_BUFFER *pBuffer) {
	FF_ERROR Error = FF_ERR_NONE;
	
	// Protect description changes with a semaphore.
	FF_PendSemaphore(pIoman->pSemaphore);
	{
		if (pBuffer->NumHandles) {
			pBuffer->NumHandles--;
		} else {
			//printf ("FF_ReleaseBuffer: buffer not claimed\n");
		}
#ifdef FF_CACHE_WRITE_THROUGH
		if(pBuffer->Modified == FF_TRUE) {
			Error = FF_BlockWrite(pIoman, pBuffer->Sector, 1, pBuffer->pBuffer, FF_TRUE);
			if(!FF_isERR(Error)) {				// Ensure if an error occurs its still possible to write the block again.
				pBuffer->Modified = FF_FALSE;
			}
		}
#endif
	}
	FF_ReleaseSemaphore(pIoman->pSemaphore);

	return Error;
}
Пример #7
0
/**
 *	@public
 *	@brief	Mounts the Specified partition, the volume specified by the FF_IOMAN object provided.
 *
 *	The device drivers must adhere to the specification provided by
 *	FF_WRITE_BLOCKS and FF_READ_BLOCKS.
 *
 *	@param	pIoman			FF_IOMAN object.
 *	@param	PartitionNumber	The primary partition number to be mounted. (0 - 3).
 *
 *	@return	0 on success.
 *	@return FF_ERR_NULL_POINTER if a pIoman object wasn't provided.
 *	@return FF_ERR_IOMAN_INVALID_PARTITION_NUM if the partition number is out of range.
 *	@return FF_ERR_IOMAN_NO_MOUNTABLE_PARTITION if no partition was found.
 *	@return FF_ERR_IOMAN_INVALID_FORMAT if the master boot record or partition boot block didn't provide sensible data.
 *	@return FF_ERR_IOMAN_NOT_FAT_FORMATTED if the volume or partition couldn't be determined to be FAT. (@see ff_config.h)
 *
 **/
FF_ERROR FF_MountPartition(FF_IOMAN *pIoman, FF_T_UINT8 PartitionNumber) {
	FF_PARTITION	*pPart;
	FF_BUFFER		*pBuffer = 0;
	FF_ERROR		Error;

	FF_T_UINT8		ucPartitionType;
#ifdef FF_HASH_CACHE
	FF_T_INT        i;
#endif
	int partCount;

	if(!pIoman) {
		return FF_ERR_NULL_POINTER | FF_MOUNTPARTITION;
	}

	/*if(PartitionNumber > 3) {
		return FF_ERR_IOMAN_INVALID_PARTITION_NUM;
	}*/

	pPart = pIoman->pPartition;

	memset (pIoman->pBuffers, '\0', sizeof(FF_BUFFER) * pIoman->CacheSize);
	memset (pIoman->pCacheMem, '\0', pIoman->BlkSize * pIoman->CacheSize);

#ifdef FF_HASH_CACHE
	for(i = 0; i < FF_HASH_CACHE_DEPTH; i++) {
		FF_ClearHashTable(pIoman->HashCache[i].pHashTable);
	}
#endif

	FF_IOMAN_InitBufferDescriptors(pIoman);
	pIoman->FirstFile = 0;

	pBuffer = FF_GetBuffer(pIoman, 0, FF_MODE_READ);
	if(!pBuffer) {
		return FF_ERR_DEVICE_DRIVER_FAILED | FF_MOUNTPARTITION;
	}

	partCount = FF_PartitionCount (pBuffer->pBuffer);

	pPart->BlkSize = FF_getShort(pBuffer->pBuffer, FF_FAT_BYTES_PER_SECTOR);

	if (partCount == 0) { //(pPart->BlkSize % 512) == 0 && pPart->BlkSize > 0) {
		// Volume is not partitioned (MBR Found)
		pPart->BeginLBA = 0;
	} else {
		
		ucPartitionType = FF_getChar(pBuffer->pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_ID);	// Ensure its not an EFI partition!

		if(ucPartitionType != 0xEE) {

			if(PartitionNumber > 3) {
				Error = FF_ReleaseBuffer(pIoman, pBuffer);	// Already returning an error, but an error from ReleaseBuf would override it.
				if(FF_isERR(Error)) {
					return Error;
				}
				return FF_ERR_IOMAN_INVALID_PARTITION_NUM | FF_MOUNTPARTITION;
			}

			// Primary Partitions to deal with!
			pPart->BeginLBA = FF_getLong(pBuffer->pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_LBA + (16 * PartitionNumber));
		}
		Error = FF_ReleaseBuffer(pIoman, pBuffer);
		if(FF_isERR(Error)) {
			return Error;
		}

		if(ucPartitionType == 0xEE) {
			pPart->BeginLBA = FF_getLong(pBuffer->pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_LBA);
			Error = FF_GetEfiPartitionEntry(pIoman, PartitionNumber);

			if(FF_isERR(Error)) {
				return Error;
			}
		}

		if(!pPart->BeginLBA) {
			return FF_ERR_IOMAN_NO_MOUNTABLE_PARTITION | FF_MOUNTPARTITION;
		}
		// Now we get the Partition sector.
		pBuffer = FF_GetBuffer(pIoman, pPart->BeginLBA, FF_MODE_READ);
		if(!pBuffer) {
			return FF_ERR_DEVICE_DRIVER_FAILED | FF_MOUNTPARTITION;
		}
		pPart->BlkSize = FF_getShort(pBuffer->pBuffer, FF_FAT_BYTES_PER_SECTOR);
		if((pPart->BlkSize % 512) != 0 || pPart->BlkSize == 0) {
			Error = FF_ReleaseBuffer(pIoman, pBuffer);	// An error here should override the current error, as its likely fatal.
			if(FF_isERR(Error)) {
				return Error;
			}
			return FF_ERR_IOMAN_INVALID_FORMAT | FF_MOUNTPARTITION;
		}
	}

	// Assume FAT16, then we'll adjust if its FAT32
	pPart->ReservedSectors = FF_getShort(pBuffer->pBuffer, FF_FAT_RESERVED_SECTORS);
	pPart->FatBeginLBA = pPart->BeginLBA + pPart->ReservedSectors;

	pPart->NumFATS = (FF_T_UINT8) FF_getShort(pBuffer->pBuffer, FF_FAT_NUMBER_OF_FATS);
	pPart->SectorsPerFAT = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FF_FAT_16_SECTORS_PER_FAT);

	pPart->SectorsPerCluster = FF_getChar(pBuffer->pBuffer, FF_FAT_SECTORS_PER_CLUS);

	pPart->BlkFactor = (FF_T_UINT8) (pPart->BlkSize / pIoman->BlkSize);    // Set the BlockFactor (How many real-blocks in a fake block!).

	if(pPart->SectorsPerFAT == 0) {	// FAT32
		pPart->SectorsPerFAT	= FF_getLong(pBuffer->pBuffer, FF_FAT_32_SECTORS_PER_FAT);
		pPart->RootDirCluster	= FF_getLong(pBuffer->pBuffer, FF_FAT_ROOT_DIR_CLUSTER);
		pPart->ClusterBeginLBA	= pPart->BeginLBA + pPart->ReservedSectors + (pPart->NumFATS * pPart->SectorsPerFAT);
		pPart->TotalSectors		= (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FF_FAT_16_TOTAL_SECTORS);
		if(pPart->TotalSectors == 0) {
			pPart->TotalSectors = FF_getLong(pBuffer->pBuffer, FF_FAT_32_TOTAL_SECTORS);
		}
		memcpy (pPart->VolLabel, pBuffer->pBuffer + FF_FAT_32_VOL_LABEL, sizeof pPart->VolLabel);
	} else {	// FAT16
		pPart->ClusterBeginLBA	= pPart->BeginLBA + pPart->ReservedSectors + (pPart->NumFATS * pPart->SectorsPerFAT);
		pPart->TotalSectors		= (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FF_FAT_16_TOTAL_SECTORS);
		pPart->RootDirCluster	= 1; // 1st Cluster is RootDir!
		if(pPart->TotalSectors == 0) {
			pPart->TotalSectors = FF_getLong(pBuffer->pBuffer, FF_FAT_32_TOTAL_SECTORS);
		}
		memcpy (pPart->VolLabel, pBuffer->pBuffer + FF_FAT_16_VOL_LABEL, sizeof pPart->VolLabel);
	}
#ifdef FF_WRITE_FREE_COUNT
	pPart->FSInfoLBA = pPart->BeginLBA + FF_getShort(pBuffer->pBuffer, 48);
#endif

	Error = FF_ReleaseBuffer(pIoman, pBuffer);	// Release the buffer finally!
	if(FF_isERR(Error)) {
		return Error;
	}

	if(!pPart->BlkSize) {
		return FF_ERR_IOMAN_INVALID_FORMAT | FF_MOUNTPARTITION;
	}

	pPart->RootDirSectors	= ((FF_getShort(pBuffer->pBuffer, FF_FAT_ROOT_ENTRY_COUNT) * 32) + pPart->BlkSize - 1) / pPart->BlkSize;
	pPart->FirstDataSector	= pPart->ClusterBeginLBA + pPart->RootDirSectors;
	pPart->DataSectors		= pPart->TotalSectors - (pPart->ReservedSectors + (pPart->NumFATS * pPart->SectorsPerFAT) + pPart->RootDirSectors);

	if(!pPart->SectorsPerCluster) {
		return FF_ERR_IOMAN_INVALID_FORMAT | FF_MOUNTPARTITION;
	}
	
	pPart->NumClusters = pPart->DataSectors / pPart->SectorsPerCluster;

	Error = FF_DetermineFatType(pIoman);
	
	if(FF_isERR(Error)) {
		return Error;
	}
	pPart->PartitionMounted = FF_TRUE;
	pPart->LastFreeCluster	= 0;
#ifdef FF_MOUNT_FIND_FREE
	pPart->LastFreeCluster	= FF_FindFreeCluster(pIoman, &Error);
	if(FF_isERR(Error)) {
		 return Error;
	}
	pPart->FreeClusterCount = FF_CountFreeClusters(pIoman, &Error);
	if(FF_isERR(Error)) {
		 return Error;
	}
#else
	pPart->FreeClusterCount = 0;
#endif

	return FF_ERR_NONE;
}
Пример #8
0
static FF_ERROR FF_GetEfiPartitionEntry(FF_IOMAN *pIoman, FF_T_UINT32 ulPartitionNumber) {
	// Continuing on from FF_MountPartition() pPartition->BeginLBA should be the sector of the GPT Header
	FF_BUFFER		*pBuffer;
	FF_PARTITION	*pPart = pIoman->pPartition;

	FF_T_UINT32		ulBeginGPT;
	FF_T_UINT32		ulEntrySector;
	FF_T_UINT32		ulSectorOffset;
	FF_T_UINT32		ulPartitionEntrySize;
	FF_T_UINT32		ulGPTHeadCRC, ulGPTCrcCheck, ulGPTHeadLength;

	FF_ERROR Error;

	if(ulPartitionNumber >= 128) {
		return FF_ERR_IOMAN_INVALID_PARTITION_NUM | FF_GETEFIPARTITIONENTRY;
	}

	pBuffer = FF_GetBuffer(pIoman, pPart->BeginLBA, FF_MODE_READ);
	{
		if(!pBuffer) {
			return FF_ERR_DEVICE_DRIVER_FAILED | FF_GETEFIPARTITIONENTRY;
		}

		// Verify this is an EFI header
		if(memcmp(pBuffer->pBuffer, "EFI PART", 8) != 0) {
			Error = FF_ReleaseBuffer(pIoman, pBuffer);	// Already returning an error, but this error would override the current one.
			if(FF_isERR(Error)) {
				return Error;
			}
			return FF_ERR_IOMAN_INVALID_FORMAT | FF_GETEFIPARTITIONENTRY;
		}

		ulBeginGPT					= FF_getLong(pBuffer->pBuffer, FF_GPT_HEAD_PART_ENTRY_LBA);
		
		ulPartitionEntrySize		= FF_getLong(pBuffer->pBuffer, FF_GPT_HEAD_ENTRY_SIZE);
		ulGPTHeadCRC				= FF_getLong(pBuffer->pBuffer, FF_GPT_HEAD_CRC);
		ulGPTHeadLength				= FF_getLong(pBuffer->pBuffer, FF_GPT_HEAD_LENGTH);

		// Calculate Head CRC

		// Blank CRC field
		FF_putLong(pBuffer->pBuffer, FF_GPT_HEAD_CRC, 0x00000000);

		// Calculate CRC
		ulGPTCrcCheck = FF_GetCRC32(pBuffer->pBuffer, ulGPTHeadLength);

		// Restore The CRC field
		FF_putLong(pBuffer->pBuffer, FF_GPT_HEAD_CRC, ulGPTHeadCRC);
	}
	Error = FF_ReleaseBuffer(pIoman, pBuffer);
	if(FF_isERR(Error)) {
		return Error;
	}

	// Check CRC
	if(ulGPTHeadCRC != ulGPTCrcCheck) {
		return FF_ERR_IOMAN_GPT_HEADER_CORRUPT | FF_GETEFIPARTITIONENTRY;
	}
	
	// Calculate Sector Containing the Partition Entry we want to use.

	ulEntrySector	= ((ulPartitionNumber * ulPartitionEntrySize) / pIoman->BlkSize) + ulBeginGPT;
	ulSectorOffset	= (ulPartitionNumber % (pIoman->BlkSize / ulPartitionEntrySize)) * ulPartitionEntrySize;
	
	pBuffer = FF_GetBuffer(pIoman, ulEntrySector, FF_MODE_READ);
	{
		if(!pBuffer) {
			return FF_ERR_DEVICE_DRIVER_FAILED | FF_GETEFIPARTITIONENTRY;
		}

		pPart->BeginLBA = FF_getLong(pBuffer->pBuffer, ulSectorOffset + FF_GPT_ENTRY_FIRST_SECTOR_LBA);
	}
	Error = FF_ReleaseBuffer(pIoman, pBuffer);
	if(FF_isERR(Error)) {
		return Error;
	}

	if(!pPart->BeginLBA) {
		return FF_ERR_IOMAN_INVALID_PARTITION_NUM | FF_GETEFIPARTITIONENTRY;
	}

	return FF_ERR_NONE;
}
Пример #9
0
/**
 *	@private
 **/
static FF_ERROR FF_DetermineFatType(FF_IOMAN *pIoman) {

	FF_PARTITION	*pPart;
	FF_BUFFER		*pBuffer;
	FF_T_UINT32		testLong;
	FF_ERROR Error;
	if(pIoman) {
		pPart = pIoman->pPartition;

		if(pPart->NumClusters < 4085) {
			// FAT12
			pPart->Type = FF_T_FAT12;
#ifdef FF_FAT_CHECK
#ifdef FF_FAT12_SUPPORT
			pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA, FF_MODE_READ);
			{
				if(!pBuffer) {
					return FF_ERR_DEVICE_DRIVER_FAILED | FF_DETERMINEFATTYPE;
				}
				testLong = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, 0x0000);
			}
			Error = FF_ReleaseBuffer(pIoman, pBuffer);
			if(FF_isERR(Error)) {
				return Error;
			}
			if((testLong & 0x3FF) != 0x3F8) {
				return FF_ERR_IOMAN_NOT_FAT_FORMATTED | FF_DETERMINEFATTYPE;
			}
#else
			return FF_ERR_IOMAN_NOT_FAT_FORMATTED | FF_DETERMINEFATTYPE;
#endif
#endif
#ifdef FF_FAT12_SUPPORT
			return FF_ERR_NONE;
#endif
		} else if(pPart->NumClusters < 65525) {
			// FAT 16
			pPart->Type = FF_T_FAT16;
#ifdef FF_FAT_CHECK
			pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA, FF_MODE_READ);
			{
				if(!pBuffer) {
					return FF_ERR_DEVICE_DRIVER_FAILED | FF_DETERMINEFATTYPE;
				}
				testLong = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, 0x0000);
			}
			Error = FF_ReleaseBuffer(pIoman, pBuffer);
			if(FF_isERR(Error)) {
				return Error;
			}
			
			if(testLong == 0xFFF8)
				return FF_ERR_NONE;
#endif
		}
		else {
			// FAT 32!
			pPart->Type = FF_T_FAT32;
#ifdef FF_FAT_CHECK
			pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA, FF_MODE_READ);
			{
				if(!pBuffer) {
					return FF_ERR_DEVICE_DRIVER_FAILED | FF_DETERMINEFATTYPE;
				}
				testLong = FF_getLong(pBuffer->pBuffer, 0x0000);
			}
			Error = FF_ReleaseBuffer(pIoman, pBuffer);
			if(FF_isERR(Error)) {
				return Error;
			}

			if((testLong & 0x0FFFFFF8) != 0x0FFFFFF8 && (testLong & 0x0FFFFFF8) != 0x0FFFFFF0) {
				// HT:
				// I had an SD-card which worked well in Linux/W32
				// but FullFAT returned me this error
				// So for me I left out this check (just issue a warning for now)
				return FF_ERR_NONE; // FF_ERR_IOMAN_NOT_FAT_FORMATTED;
			}
#endif
			return FF_ERR_NONE;
		}
	}

	return FF_ERR_IOMAN_NOT_FAT_FORMATTED | FF_DETERMINEFATTYPE;
}
Пример #10
0
/* This is the prototype of the function used to initialise the RAM disk driver.
Other media drivers do not have to have the same prototype.

In this example:
 + pcName is the name to give the disk within FreeRTOS+FAT's virtual file system.
 + pucDataBuffer is the start of the RAM to use as the disk.
 + ulSectorCount is effectively the size of the disk, each sector is 512 bytes.
 + xIOManagerCacheSize is the size of the IO manager's cache, which must be a
   multiple of the sector size, and at least twice as big as the sector size.
*/
FF_Disk_t *FF_RAMDiskInit( char *pcName, uint8_t *pucDataBuffer, uint32_t ulSectorCount, size_t xIOManagerCacheSize )
{
FF_Error_t xError;
FF_Disk_t *pxDisk = NULL;
FF_CreationParameters_t xParameters;

	/* Check the validity of the xIOManagerCacheSize parameter. */
	configASSERT( ( xIOManagerCacheSize % ramSECTOR_SIZE ) == 0 );
	configASSERT( ( xIOManagerCacheSize >= ( 2 * ramSECTOR_SIZE ) ) );

	/* Attempt to allocated the FF_Disk_t structure. */
	pxDisk = ( FF_Disk_t * ) pvPortMalloc( sizeof( FF_Disk_t ) );

	if( pxDisk != NULL )
	{
		/* Start with every member of the structure set to zero. */
		memset( pxDisk, '\0', sizeof( FF_Disk_t ) );
		
		/* Clear the entire space. */
		memset( pucDataBuffer, '\0', ulSectorCount * ramSECTOR_SIZE );

		/* The pvTag member of the FF_Disk_t structure allows the structure to be
		extended to also include media specific parameters.  The only media
		specific data that needs to be stored in the FF_Disk_t structure for a
		RAM disk is the location of the RAM buffer itself - so this is stored
		directly in the FF_Disk_t's pvTag member. */
		pxDisk->pvTag = ( void * ) pucDataBuffer;

		/* The signature is used by the disk read and disk write functions to
		ensure the disk being accessed is a RAM disk. */
		pxDisk->ulSignature = ramSIGNATURE;

		/* The number of sectors is recorded for bounds checking in the read and
		write functions. */
		pxDisk->ulNumberOfSectors = ulSectorCount;

		/* Create the IO manager that will be used to control the RAM disk. */
		memset( &xParameters, '\0', sizeof xParameters );
		xParameters.pucCacheMemory = NULL;
		xParameters.ulMemorySize = xIOManagerCacheSize;
		xParameters.ulSectorSize = ramSECTOR_SIZE;
		xParameters.fnWriteBlocks = prvWriteRAM;
		xParameters.fnReadBlocks = prvReadRAM;
		xParameters.pxDisk = pxDisk;

		/* Driver is reentrant so xBlockDeviceIsReentrant can be set to pdTRUE.
		In this case the semaphore is only used to protect FAT data
		structures. */
		xParameters.pvSemaphore = ( void * ) xSemaphoreCreateRecursiveMutex();
		xParameters.xBlockDeviceIsReentrant = pdFALSE;

		pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xError );

		if( ( pxDisk->pxIOManager != NULL ) && ( FF_isERR( xError ) == pdFALSE ) )
		{
			/* Record that the RAM disk has been initialised. */
			pxDisk->xStatus.bIsInitialised = pdTRUE;

			/* Create a partition on the RAM disk.  NOTE!  The disk is only
			being partitioned here because it is a new RAM disk.  It is
			known that the disk has not been used before, and cannot already
			contain any partitions.  Most media drivers will not perform
			this step because the media will have already been partitioned. */
			xError = prvPartitionAndFormatDisk( pxDisk );

			if( FF_isERR( xError ) == pdFALSE )
			{
				/* Record the partition number the FF_Disk_t structure is, then
				mount the partition. */
				pxDisk->xStatus.bPartitionNumber = ramPARTITION_NUMBER;

				/* Mount the partition. */
				xError = FF_Mount( pxDisk, ramPARTITION_NUMBER );
				FF_PRINTF( "FF_RAMDiskInit: FF_Mount: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
			}

			if( FF_isERR( xError ) == pdFALSE )
			{
				/* The partition mounted successfully, add it to the virtual
				file system - where it will appear as a directory off the file
				system's root directory. */
				FF_FS_Add( pcName, pxDisk );
			}
		}
		else
		{
			FF_PRINTF( "FF_RAMDiskInit: FF_CreateIOManger: %s\n", ( const char * ) FF_GetErrMessage( xError ) );

			/* The disk structure was allocated, but the disk's IO manager could
			not be allocated, so free the disk again. */
			FF_RAMDiskDelete( pxDisk );
			pxDisk = NULL;
		}
	}
	else
	{
		FF_PRINTF( "FF_RAMDiskInit: Malloc failed\n" );
	}

	return pxDisk;
}