FF_Error_t FF_Partition()

in ff_format.c [916:1076]


FF_Error_t FF_Partition( FF_Disk_t * pxDisk,
                         FF_PartitionParameters_t * pParams )
{
    FF_Error_t xReturn = FF_ERR_NONE;
    struct xPartitionSet xSet;
    BaseType_t xNeedExtended;    /* When more than 4 partitions are requested, extended partitions are needed. */
    uint32_t ulAvailable;        /* The number of sectors available. */
    BaseType_t xPartitionNumber;
    uint32_t ulSummedSizes = 0U; /* Summed sizes as a percentage or as number of sectors. */
    uint32_t ulReservedSpace;    /**< Space needed for the extended partitions. */

    memset( &( xSet ), 0, sizeof( xSet ) );

    /* Hidden space between 2 extended partitions */
    xSet.ulInterSpace = pParams->ulInterSpace ? pParams->ulInterSpace : 2048;
    /* The +FAT IO-manager. */
    xSet.pxIOManager = pxDisk->pxIOManager;


    /* Clear caching without flushing first. */
    FF_IOMAN_InitBufferDescriptors( xSet.pxIOManager );

    /* Avoid sanity checks by FF_BlockRead/Write. */
    xSet.pxIOManager->xPartition.ulTotalSectors = 0;

    /* Get the sum of sizes and number of actual partitions. */
    for( xPartitionNumber = 0; xPartitionNumber < ffconfigMAX_PARTITIONS; xPartitionNumber++ )
    {
        if( pParams->xSizes[ xPartitionNumber ] > 0 )
        {
            xSet.xPartitionCount++;
            ulSummedSizes += pParams->xSizes[ xPartitionNumber ];
        }
    }

    /* xSet.xPartitionCount is at most 'ffconfigMAX_PARTITIONS' */
    if( xSet.xPartitionCount == 0 )
    {
        xSet.xPartitionCount = 1;

        /* 'ffconfigMAX_PARTITIONS' must be 1 or more. */
        if( pParams->eSizeType == eSizeIsSectors )
        {
            pParams->xSizes[ 0 ] = pParams->ulSectorCount;
        }
        else
        {
            pParams->xSizes[ 0 ] = 100;
        }

        ulSummedSizes = pParams->xSizes[ 0 ];
    }

    /* Correct PrimaryCount if necessary. */
    if( pParams->xPrimaryCount > ( ( xSet.xPartitionCount > 4 ) ? 3 : xSet.xPartitionCount ) )
    {
        pParams->xPrimaryCount = ( xSet.xPartitionCount > 4 ) ? 3 : xSet.xPartitionCount;
    }

    /* Now see if extended is necessary. */
    xNeedExtended = ( xSet.xPartitionCount > pParams->xPrimaryCount ) ? pdTRUE : pdFALSE;

    if( xNeedExtended != pdFALSE )
    {
        if( pParams->ulHiddenSectors < 4096 )
        {
            pParams->ulHiddenSectors = 4096;
        }

        ulReservedSpace = xSet.ulInterSpace * ( xSet.xPartitionCount - pParams->xPrimaryCount );
    }
    else
    {
        /* There must be at least 1 hidden sector. */
        if( pParams->ulHiddenSectors < 1 )
        {
            pParams->ulHiddenSectors = 1;
        }

        ulReservedSpace = 0;
    }

    ulAvailable = pParams->ulSectorCount - pParams->ulHiddenSectors - ulReservedSpace;

    /* Check validity of Sizes */
    switch( pParams->eSizeType )
    {
        case eSizeIsQuota: /* Assign a quotum (sum of Sizes is free, all disk space will be allocated) */
            break;

        case eSizeIsPercent: /* Assign a percentage of the available space (sum of Sizes must be <= 100) */

            if( ulSummedSizes > 100 )
            {
                return FF_FORMATPARTITION | FF_ERR_IOMAN_BAD_MEMSIZE;
            }

            ulSummedSizes = 100;
            break;

        case eSizeIsSectors: /* Assign fixed number of sectors (512 byte each) */

            if( ulSummedSizes > ulAvailable )
            {
                return FF_FORMATPARTITION | FF_ERR_IOMAN_BAD_MEMSIZE;
            }

            break;
    }

    {
        uint32_t ulRemaining = ulAvailable;
        uint32_t ulLBA = pParams->ulHiddenSectors;

        /* Divide the available sectors among the partitions: */

        for( xPartitionNumber = 0; xPartitionNumber < xSet.xPartitionCount; xPartitionNumber++ )
        {
            if( pParams->xSizes[ xPartitionNumber ] > 0 )
            {
                uint32_t ulSize;

                switch( pParams->eSizeType )
                {
                    case eSizeIsQuota:   /* Assign a quotum (sum of Sizes is free, all disk space will be allocated) */
                    case eSizeIsPercent: /* Assign a percentage of the available space (sum of Sizes must be <= 100) */
                        ulSize = ( uint32_t ) ( ( ( uint64_t ) pParams->xSizes[ xPartitionNumber ] * ulAvailable ) / ulSummedSizes );
                        break;

                    case eSizeIsSectors: /* Assign fixed number of sectors (512 byte each) */
                    default:             /* Just for the compiler(s) */
                        ulSize = pParams->xSizes[ xPartitionNumber ];
                        break;
                }

                if( ulSize > ulRemaining )
                {
                    ulSize = ulRemaining;
                }

                ulRemaining -= ulSize;
                xSet.pxPartitions[ xPartitionNumber ].ulSectorCount = ulSize;
                xSet.pxPartitions[ xPartitionNumber ].ucActive = 0x80;
                xSet.pxPartitions[ xPartitionNumber ].ulStartLBA = ulLBA; /* ulStartLBA might still change for logical partitions */
                xSet.pxPartitions[ xPartitionNumber ].ucPartitionID = 0x0B;
                ulLBA += ulSize;
            }
        }
    }

    if( xNeedExtended == pdFALSE )
    {
        xReturn = prvPartitionPrimary( &( xSet ) );
    }
    else
    {
        xReturn = prvPartitionExtended( &( xSet ), pParams );
    }

    return xReturn;
}