+FAT – Incorrect Volume Label

Hello! I`am started to using FreeRTOS with +FAT file system and want to thank its authors for their hard work! And here is an issue I have encountered. The Volume Label acquired by FF_Mount function in pxIOManager->xPartition.pcVolumeLabel structure member is invalid/outdated. This label is copied directly from partition sector, but there is another place for it – root directory entry with the attribute ATTRVOLUMEID, which holds an actual volume label. So, in my case (Windows 10), SD card with the label “SD CARD”, has the wrong (outdated) “NO NAME” label reported by +FAT 🙁 Regards Vladimir

+FAT – Incorrect Volume Label

Hi Vladimir, You are right, +FAT only recognises the 11-byte Volume label as stored in the partition table, found at these offsets: ~~~ #define FFFAT16VOLLABEL 0x02B #define FFFAT32VOLLABEL 0x047 ~~~ The root directory indeed may contain a Volume label, if it has this file-entry attribute: ~~~ #define FFFATATTR_VOLID 0x08 ~~~ The FreeRTOS+FAT library is developed for embedded applications, and the choice was made to ignore these Volume ID entries in the root directory. But, well, here is a read-only version, that needs a minimum of changes to the source code: Replace on line in ff_dir.c around line 1799 : ~~~ – else if( ( pxDirEntry->ucAttrib & FFFATATTRVOLID ) != FFFATATTRVOLID ) + else if( ( pxDirEntry->ucAttrib & FFFATATTRVOLID ) == FFFATATTRVOLID ) + { + #if( ffconfigDIRECTORYVOLIDSUPPORT != 0 ) + { + const sizet uxLength = sizeof( pxIOManager->pcDirectoryVolID ) – ( sizet )1u; + + memcpy( pxIOManager->pcDirectoryVolID, pucEntryBuffer, uxLength ); + pxIOManager->pcDirectoryVolID[ uxLength ] = ‘’; + } + #endif /* ffconfigDIRECTORYVOLIDSUPPORT */ + } + else ~~~ And add a new member in includeff_ioman.h, around line 291: ~~~ uint8t ucPreventFlush; /* Flushing to disk only allowed when 0. */ uint8t ucFlags; /* Bit-Mask: identifying allocated pointers and other flags / #if( ffconfigHASH_CACHE != 0 ) FF_HashTable_t xHashCache[ ffconfigHASH_CACHE_DEPTH ]; #endif +#if( ffconfigDIRECTORY_VOLID_SUPPORT != 0 ) + char pcDirectoryVolID[ 12 ]; / Volume Label of the partition as recorded in the root directory. */ +#endif void *pvFATLockHandle; } FF_IOManager_t; ~~~ Any access to the root directory of the volume will include fetching the new volume ID,

+FAT – Incorrect Volume Label

Hi Hein. Thanks for the help, its very appreciated! I think the best way is to have a dedicated function to extract the label from root directory, using FFInitEntryFetch() and FFFetchEntryWithContext(). Or it might be faster to modify the FF_FindEntryInDir() function, but I do not want to alter original code too much.

+FAT – Incorrect Volume Label

Hi Vladimir, here above I published a quick method that doesn’t hurt at all. It only requires that you call : ~~~ FFFindDatat xFindData; ff_findfirst( “/”, &( xFindData ) ); ~~~ I think that the label is always written as the first entry. If that is true, it would do to just read the first sector of the root directory, and see if the label is present.
using FFInitEntryFetch() and FFFetchEntryWithContext().
You studied the source code well ! As you have seen the library is quite complex because of the user preferences and also because of the many optimisations.

+FAT – Incorrect Volume Label

Hi Hein, just tried: ~~~ FFFindDatat xFindData; ff_findfirst( “/”, &( xFindData ) ); ~~~ and it returns with LFN “System Volume Information” – its a system folder, not a volume label. In disk editor I’ve found actual volume label almost at the end of root directory…
You studied the source code well !
Thank you 🙂 I have found another little bug in ffioman.c file, in function prvDetermineFatType(), where FAT type is being checked. From the line 774 (there is possibly your comments below): ~~~ if( ( ( ulFirstWord & 0x0FFFFFF8 ) != 0x0FFFFFF8 ) && ( ( ulFirstWord & 0x0FFFFFF8 ) != 0x0FFFFFF0 ) ) { /* _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) */ ~~~ This condition will always fail because ulFirstWord was assigned in the code above in line 718 as a short type: ~~~ ulFirstWord = ( uint32_t ) FF_getShort(const uint8_t *pBuffer, uint32_t aOffset) ~~~ To correct this error FF_getShort should be changed to FF_getLong. After that the condition check will successfully pass.

+FAT – Incorrect Volume Label

Hi! Just added a special function which searches in root directory and returns an actual Volume Label: ~~~ const char* ffgetvolumelabel( FFIOManagert *pxIOManager ) { BaseTypet xIndex; const uint8t *pucEntryBuffer = 0; uint8t ucAttrib; FFFetchContextt xFetchContext; FFErrort pxError;
pxError = FF_InitEntryFetch( pxIOManager, pxIOManager->xPartition.ulRootDirCluster, &xFetchContext );
if (!FF_isERR( pxError ))
{
    for ( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ )
    {
        /* Call FF_FetchEntryWithContext only once for every 512-byte block */
        if ( !xIndex || pucEntryBuffer >= xFetchContext.pxBuffer->pucBuffer + ( FF_SIZEOF_SECTOR - FF_SIZEOF_DIRECTORY_ENTRY ) )
        {
            pxError = FF_FetchEntryWithContext( pxIOManager, ( uint32_t ) xIndex, &xFetchContext, 0 );
            if ( FF_isERR( pxError ) )
            {
                break;
            }
            pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer;
        }
        else
        {
            /* Advance 32 bytes to get the next directory entry. */
            pucEntryBuffer += FF_SIZEOF_DIRECTORY_ENTRY;
        }

        if ( FF_isEndOfDir( pucEntryBuffer ) )
        {
            break;
        }
        if (!FF_isDeleted( pucEntryBuffer ))
        {
            ucAttrib = FF_getChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB );
            if ( ucAttrib == FF_FAT_ATTR_VOLID )
            {
                memcpy( pxIOManager->xPartition.pcVolumeLabel, pucEntryBuffer, sizeof(pxIOManager->xPartition.pcVolumeLabel) - 1 );
                break;
            }
        }
    } /* for ( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ ) */
}
FF_CleanupEntryFetch( pxIOManager, &xFetchContext );

return (const char*)pxIOManager->xPartition.pcVolumeLabel;
} ~~~ One should call it from DiskInit routine, right after the calls to FFMount and FFFS_Add.