FF_Error_t FF_Mount()

in ff_ioman.c [1364:1607]


FF_Error_t FF_Mount( FF_Disk_t * pxDisk,
                     BaseType_t xPartitionNumber )
{
    FF_Partition_t * pxPartition;
    FF_Buffer_t * pxBuffer = 0;
    FF_Error_t xError = FF_ERR_NONE;
    int16_t rootEntryCount;
    FF_IOManager_t * pxIOManager = pxDisk->pxIOManager;

/* HT TODO: find a method to safely determine the FAT type: 32/16/12 */
/* other than only counting Clusters */
/*	UBaseType_t		fat32Indicator = 0; */
    FF_Part_t * pxMyPartition;

    #if ( ffconfigHASH_CACHE != 0 )
        BaseType_t i;
    #endif
    FF_Error_t xPartitionCount = 0;
    FF_SPartFound_t partsFound;
    partsFound.iCount = 0;

    do
    {
        if( pxIOManager == NULL )
        {
            xError = FF_ERR_NULL_POINTER | FF_MOUNT;
            break;
        }

        pxPartition = &( pxIOManager->xPartition );

        #if ( ffconfigREMOVABLE_MEDIA != 0 )
            {
                pxIOManager->ucFlags &= ( uint8_t ) ( ~( FF_IOMAN_DEVICE_IS_EXTRACTED ) );
            }
        #endif /* ffconfigREMOVABLE_MEDIA */

        /* FF_IOMAN_InitBufferDescriptors will clear 'pxBuffers' */
        memset( pxIOManager->pucCacheMem, '\0', ( size_t ) pxIOManager->usSectorSize * pxIOManager->usCacheSize );

        #if ( ffconfigHASH_CACHE != 0 )
            {
                memset( pxIOManager->xHashCache, '\0', sizeof( pxIOManager->xHashCache ) );

                for( i = 0; i < ffconfigHASH_CACHE_DEPTH; i++ )
                {
                    /* _HT_ Check why did JW put it to 100? */
                    pxIOManager->xHashCache[ i ].ulMisses = 100;
                }
            }
        #endif
        #if ( ffconfigPATH_CACHE != 0 )
            {
                memset( pxPartition->pxPathCache, '\0', sizeof( pxPartition->pxPathCache ) );
            }
        #endif
        FF_IOMAN_InitBufferDescriptors( pxIOManager );
        pxIOManager->FirstFile = 0;

        xPartitionCount = FF_PartitionSearch( pxIOManager, &partsFound );

        if( FF_isERR( xPartitionCount ) )
        {
            xError = xPartitionCount;
            break;
        }

        if( xPartitionCount == 0 )
        {
            xError = FF_ERR_IOMAN_NO_MOUNTABLE_PARTITION | FF_MOUNT;
            break;
        }

        if( xPartitionNumber >= xPartitionCount )
        {
            xError = FF_ERR_IOMAN_INVALID_PARTITION_NUM | FF_MOUNT;
            break;
        }

        pxMyPartition = &( partsFound.pxPartitions[ xPartitionNumber ] );

        pxPartition->ulBeginLBA = pxMyPartition->ulStartLBA;

        if( pxMyPartition->ucPartitionID == 0xEE )
        {
            xError = FF_GetEfiPartitionEntry( pxIOManager, xPartitionNumber );

            if( FF_isERR( xError ) )
            {
                break;
            }
        }

        /* Now we get the Partition sector. */
        pxBuffer = FF_GetBuffer( pxIOManager, pxPartition->ulBeginLBA, FF_MODE_READ );

        if( pxBuffer == NULL )
        {
            xError = FF_ERR_DEVICE_DRIVER_FAILED | FF_MOUNT;
            break;
        }

        pxPartition->usBlkSize = FF_getShort( pxBuffer->pucBuffer, FF_FAT_BYTES_PER_SECTOR );

        if( ( ( pxPartition->usBlkSize % 512 ) != 0 ) || ( pxPartition->usBlkSize == 0 ) )
        {
            /* An error here should override the current error, as its likely fatal. */
            xError = FF_ReleaseBuffer( pxIOManager, pxBuffer );

            if( FF_isERR( xError ) == pdFALSE )
            {
                xError = FF_ERR_IOMAN_INVALID_FORMAT | FF_MOUNT;
            }

            break;
        }

        /* Assume FAT16, then we'll adjust if its FAT32 */
        pxPartition->usReservedSectors = FF_getShort( pxBuffer->pucBuffer, FF_FAT_RESERVED_SECTORS );
        pxPartition->ulFATBeginLBA = pxPartition->ulBeginLBA + pxPartition->usReservedSectors;

        pxPartition->ucNumFATS = ( uint8_t ) FF_getShort( pxBuffer->pucBuffer, FF_FAT_NUMBER_OF_FATS );
        pxPartition->ulSectorsPerFAT = ( uint32_t ) FF_getShort( pxBuffer->pucBuffer, FF_FAT_16_SECTORS_PER_FAT );

        pxPartition->ulSectorsPerCluster = FF_getChar( pxBuffer->pucBuffer, FF_FAT_SECTORS_PER_CLUS );

        /* Set the BlockFactor (How many real-blocks in a fake block!). */
        pxPartition->ucBlkFactor = ( uint8_t ) ( pxPartition->usBlkSize / pxIOManager->usSectorSize );
        pxPartition->ulTotalSectors = ( uint32_t ) FF_getShort( pxBuffer->pucBuffer, FF_FAT_16_TOTAL_SECTORS );

        if( pxPartition->ulTotalSectors == 0 )
        {
            pxPartition->ulTotalSectors = FF_getLong( pxBuffer->pucBuffer, FF_FAT_32_TOTAL_SECTORS );
        }

        if( pxPartition->ulSectorsPerFAT == 0 )
        {   /* FAT32 */
            pxPartition->ulSectorsPerFAT = FF_getLong( pxBuffer->pucBuffer, FF_FAT_32_SECTORS_PER_FAT );
            pxPartition->ulRootDirCluster = FF_getLong( pxBuffer->pucBuffer, FF_FAT_ROOT_DIR_CLUSTER );
            memcpy( pxPartition->pcVolumeLabel, pxBuffer->pucBuffer + FF_FAT_32_VOL_LABEL, sizeof( pxPartition->pcVolumeLabel ) - 1 );
        }
        else
        {                                      /* FAT16 */
            pxPartition->ulRootDirCluster = 1; /* 1st Cluster is RootDir! */
            memcpy( pxPartition->pcVolumeLabel, pxBuffer->pucBuffer + FF_FAT_16_VOL_LABEL, sizeof( pxPartition->pcVolumeLabel ) - 1 );
        }

        pxPartition->ulClusterBeginLBA = pxPartition->ulFATBeginLBA + ( pxPartition->ucNumFATS * pxPartition->ulSectorsPerFAT );
        #if ( ffconfigWRITE_FREE_COUNT != 0 )
            {
                pxPartition->ulFSInfoLBA = pxPartition->ulBeginLBA + FF_getShort( pxBuffer->pucBuffer, 48 );
            }
        #endif
        FF_ReleaseBuffer( pxIOManager, pxBuffer ); /* Release the buffer finally! */

        if( pxPartition->usBlkSize == 0 )
        {
            xError = FF_ERR_IOMAN_INVALID_FORMAT | FF_MOUNT;
            break;
        }

        rootEntryCount = FF_getShort( pxBuffer->pucBuffer, FF_FAT_ROOT_ENTRY_COUNT );
        pxPartition->ulRootDirSectors = ( ( rootEntryCount * 32 ) + pxPartition->usBlkSize - 1 ) / pxPartition->usBlkSize;
        pxPartition->ulFirstDataSector = pxPartition->ulClusterBeginLBA + pxPartition->ulRootDirSectors;
        pxPartition->ulDataSectors = pxPartition->ulTotalSectors - ( pxPartition->usReservedSectors + ( pxPartition->ucNumFATS * pxPartition->ulSectorsPerFAT ) + pxPartition->ulRootDirSectors );

        /*
         * HT: fat32Indicator not yet used
         * As there is so much confusion about the FAT types
         * I was thinking of collecting indications for either FAT12, 16 or 32
         */

        /*
         * if( FF_getShort( pxBuffer->pucBuffer, FF_FAT_EXT_BOOT_SIGNATURE ) == 0x29 )
         *  fat32Indicator++;
         * if( rootEntryCount == 0 )
         *  fat32Indicator++;
         */
        if( pxPartition->ulSectorsPerCluster == 0 )
        {
            xError = FF_ERR_IOMAN_INVALID_FORMAT | FF_MOUNT;
            break;
        }

        pxPartition->ulNumClusters = pxPartition->ulDataSectors / pxPartition->ulSectorsPerCluster;

        xError = prvDetermineFatType( pxIOManager );

        if( FF_isERR( xError ) )
        {
            break;
        }

        if( !rootEntryCount && ( pxPartition->ucType != FF_T_FAT32 ) )
        {
            FF_PRINTF( "No root dir, must be a FAT32\n" );
            pxPartition->ucType = FF_T_FAT32;
        }

        pxPartition->ucPartitionMounted = pdTRUE;
        pxPartition->ulLastFreeCluster = 0;
        #if ( ffconfigMOUNT_FIND_FREE != 0 )
            {
                FF_LockFAT( pxIOManager );
                {
                    /* The parameter 'pdFALSE' means: do not claim the free cluster found. */
                    pxPartition->ulLastFreeCluster = FF_FindFreeCluster( pxIOManager, &xError, pdFALSE );
                }
                FF_UnlockFAT( pxIOManager );

                if( FF_isERR( xError ) )
                {
                    if( FF_GETERROR( xError ) == FF_ERR_IOMAN_NOT_ENOUGH_FREE_SPACE )
                    {
                        pxPartition->ulLastFreeCluster = 0;
                    }
                    else
                    {
                        break;
                    }
                }

                pxPartition->ulFreeClusterCount = FF_CountFreeClusters( pxIOManager, &xError );

                if( FF_isERR( xError ) )
                {
                    break;
                }
            }
        #else /* if ( ffconfigMOUNT_FIND_FREE != 0 ) */
            {
                pxPartition->ulFreeClusterCount = 0;
            }
        #endif /* ffconfigMOUNT_FIND_FREE */
    }
    while( pdFALSE );

    if( FF_isERR( xError ) == pdFALSE )
    {
        xError = 0;
    }

    return xError;
} /* FF_Mount() */