Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dynamic FAT variant detection #55 #56

Merged
merged 8 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ elseif((FREERTOS_PLUS_FAT_PORT STREQUAL "A_CUSTOM_PORT") AND (NOT TARGET freerto
" freertos_plus_fat)")
endif()

# This library requires access to a heap
# FreeRTOS/FreeRTOS-Kernel previously defaulted to heap4.c
if(NOT DEFINED FREERTOS_HEAP)
message(STATUS "FREERTOS_HEAP not set, setting FREERTOS_HEAP=4")
set(FREERTOS_HEAP 4)
endif()

# Select the appropriate Build Test configuration
# This is only used when freertos_config is not defined, otherwise the build test will be performed
Expand Down
62 changes: 41 additions & 21 deletions ff_ioman.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,18 +705,21 @@ static uint8_t ucAssumeFATType = 0;
*
* In practice however, this does not always seem to be a correct assumption.
*
* The first 12 or 16 bits in the FAT table may also help to determine the
* The end-of-chain value in the FAT table may also help to determine the
* correct FAT-type:
*
* FAT-12: ( firstWord & 0x3FF ) == 0x3F8 )
* FAT-16: ( firstWord == 0xFFF8 )
* ulFirstCluster = the first 32-bit of the FAT.
* FAT-12: endOfChain == 0x00000FF8 - 12 bits
* FAT-16: endOfChain == 0x0000FFF8 - 16 bits
* FAT-32: endOfChain == 0x0FFFFFF8 - 32 bits
*/

static FF_Error_t prvDetermineFatType( FF_IOManager_t * pxIOManager )
{
FF_Partition_t * pxPartition;
FF_Buffer_t * pxBuffer;
uint32_t ulFirstWord = 0ul;
/* The first 32-bits of the FAT. */
uint32_t ulFirstCluster = 0U;
FF_Error_t xError = FF_ERR_NONE;

pxPartition = &( pxIOManager->xPartition );
Expand Down Expand Up @@ -751,7 +754,8 @@ static FF_Error_t prvDetermineFatType( FF_IOManager_t * pxIOManager )
}
else
{
ulFirstWord = ( uint32_t ) FF_getShort( pxBuffer->pucBuffer, 0x0000 );
/* Read the first 4 bytes at offset 0. */
ulFirstCluster = FF_getLong( pxBuffer->pucBuffer, 0U );
xError = FF_ReleaseBuffer( pxIOManager, pxBuffer );
}
}
Expand All @@ -764,13 +768,23 @@ static FF_Error_t prvDetermineFatType( FF_IOManager_t * pxIOManager )
/* FAT12 */
pxPartition->ucType = FF_T_FAT12;
#if ( ffconfigFAT_CHECK != 0 )
if( ( ulFirstWord & 0x3FF ) != 0x3F8 )
/* Keep bits 4..11 */

/* MS-DOS/PC DOS 3.3 and higher treats a value of 0xFF0 on FAT12.
* See https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system
*/
ulFirstCluster &= 0xFF0U;

if( ulFirstCluster != 0xFF0U )
{
xError = FF_createERR( FF_ERR_IOMAN_NOT_FAT_FORMATTED, FF_DETERMINEFATTYPE );
FF_PRINTF( "FAT_CHECK: FAT12 Partition has unexpected FAT data %04lX\n",
ulFirstCluster );
}
else
#endif /* ffconfigFAT_CHECK */
{
/* FAT12 entry OK. */
xError = FF_ERR_NONE;
}
}
Expand All @@ -783,20 +797,24 @@ static FF_Error_t prvDetermineFatType( FF_IOManager_t * pxIOManager )
pxPartition->ucType = FF_T_FAT16;
#if ( ffconfigFAT_CHECK != 0 )
{
if( ulFirstWord == 0xFFF8 )
/* Keep bits 4..15 */
ulFirstCluster &= 0xFFF8U;

if( ulFirstCluster == 0xFFF8U )
{
/* FAT16 entry OK. */
xError = FF_ERR_NONE;
}
else
{
if( ( ulFirstWord & 0x3FF ) != 0x3F8 )
if( ( ulFirstCluster & 0xFF8U ) == 0xFF8U )
{
FF_PRINTF( "Part at %lu is probably a FAT12\n", pxIOManager->xPartition.ulFATBeginLBA );
FF_PRINTF( "FAT_CHECK: FAT16 Part at %lu is probably a FAT12\n", pxIOManager->xPartition.ulFATBeginLBA );
}
else
{
FF_PRINTF( "Partition at %lu has strange FAT data %08lX\n",
pxIOManager->xPartition.ulFATBeginLBA, ulFirstWord );
FF_PRINTF( "FAT_CHECK: FAT16 Partition has unexpected FAT data %08lX\n",
ulFirstCluster );
}

xError = FF_createERR( FF_ERR_IOMAN_INVALID_FORMAT, FF_DETERMINEFATTYPE );
Expand All @@ -809,19 +827,21 @@ static FF_Error_t prvDetermineFatType( FF_IOManager_t * pxIOManager )
/* FAT 32! */
pxPartition->ucType = FF_T_FAT32;
#if ( ffconfigFAT_CHECK != 0 )
if( ( ( ulFirstWord & 0x0FFFFFF8 ) != 0x0FFFFFF8 ) &&
( ( ulFirstWord & 0x0FFFFFF8 ) != 0x0FFFFFF0 ) )
/* Keep bits 4..27 */
ulFirstCluster &= 0x0FFFFFF8UL;

if( ulFirstCluster != 0x0FFFFFF8UL )
{
/* _HT_
* I had an SD-card which worked well in Linux/W32
* but FreeRTOS+FAT returned me this error
* So for me I left out this check (just issue a warning for now)
*/
FF_PRINTF( "prvDetermineFatType: firstWord %08lX\n", ulFirstWord );
xError = FF_ERR_NONE; /* FF_ERR_IOMAN_NOT_FAT_FORMATTED; */
FF_PRINTF( "FAT_CHECK: FAT32 Partition at %lu has unexpected FAT data %08lX\n",
pxIOManager->xPartition.ulFATBeginLBA, ulFirstCluster );
xError = FF_ERR_IOMAN_NOT_FAT_FORMATTED;
}
else
#endif /* ffconfigFAT_CHECK */
xError = FF_ERR_NONE;
{
/* FAT32 entry OK. */
xError = FF_ERR_NONE;
}
}
}

Expand Down
Loading