FF_Error_t FF_PartitionSearch()

in ff_ioman.c [1055:1225]


FF_Error_t FF_PartitionSearch( FF_IOManager_t * pxIOManager,
                               FF_SPartFound_t * pPartsFound )
{
    BaseType_t xPartNr;
    FF_Buffer_t * pxBuffer;
    uint8_t * ucDataBuffer;
    BaseType_t isPBR = pdFALSE;
    FF_Error_t xError = FF_ERR_NONE;
    uint32_t prevTotalSectors = pxIOManager->xPartition.ulTotalSectors;
    FF_Part_t pxPartitions[ 4 ];

    memset( pPartsFound, '\0', sizeof( *pPartsFound ) );

    do
    {
        pxBuffer = FF_GetBuffer( pxIOManager, 0, FF_MODE_READ );

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

        /* Disable sector checking in FF_BlockRead
         * Let user driver return an error is appropriate. */
        pxIOManager->xPartition.ulTotalSectors = 0;
        ucDataBuffer = pxBuffer->pucBuffer;

        /* Check MBR (Master Boot Record) or
         * PBR (Partition Boot Record) signature. */
        if( ( FF_getChar( ucDataBuffer, FF_FAT_MBR_SIGNATURE ) != 0x55 ) ||
            ( FF_getChar( ucDataBuffer, FF_FAT_MBR_SIGNATURE + 1 ) != 0xAA ) )
        {
            /* No MBR, but is it a PBR ?
             * Partition Boot Record */
            if( ( FF_getChar( ucDataBuffer, 0 ) == 0xEB ) && /* PBR Byte 0 */
                ( FF_getChar( ucDataBuffer, 2 ) == 0x90 ) )
            {
                /* PBR Byte 2
                 * No MBR but PBR exist then there is only one partition
                 * Handle this later. */
                isPBR = pdTRUE;
            }
            else
            {
                FF_PRINTF( "FF_PartitionSearch: [%02X,%02X] No signature (%02X %02X), no PBR neither\n",
                           FF_getChar( ucDataBuffer, 0 ),
                           FF_getChar( ucDataBuffer, 2 ),
                           FF_getChar( ucDataBuffer, FF_FAT_MBR_SIGNATURE ),
                           FF_getChar( ucDataBuffer, FF_FAT_MBR_SIGNATURE + 1 ) );

                /* No MBR and no PBR then no partition found. */
                xError = FF_ERR_IOMAN_INVALID_FORMAT | FF_PARTITIONSEARCH;
                break;
            }
        }

        /* Copy the 4 partition records into 'pxPartitions': */
        FF_ReadParts( ucDataBuffer, pxPartitions );

        for( xPartNr = 0; ( xPartNr < 4 ) && ( isPBR == pdFALSE ); xPartNr++ )
        {
            /*		FF_PRINTF ("FF_Part[%d]: id %02X act %02X Start %6lu Len %6lu (sectors)\n", */
            /*			xPartNr, pxPartitions[ xPartNr ].ucPartitionID, */
            /*			pxPartitions[ xPartNr ].ucActive, */
            /*			pxPartitions[ xPartNr ].ulStartLBA, */
            /*			pxPartitions[ xPartNr ].ulSectorCount); */
            if( prvIsExtendedPartition( pxPartitions[ xPartNr ].ucPartitionID ) != pdFALSE )
            {
                continue; /* Do this later */
            }

            /* The first sector must be a MBR, then check the partition entry in the MBR */
            if( ( pxPartitions[ xPartNr ].ucActive != 0x80 ) &&
                ( pxPartitions[ xPartNr ].ucActive != 0x00 ) )
            {
                if( ( xPartNr == 0 ) &&
                    ( FF_getShort( ucDataBuffer, FF_FAT_RESERVED_SECTORS ) != 0 ) &&
                    ( FF_getChar( ucDataBuffer, FF_FAT_NUMBER_OF_FATS ) != 0 ) )
                {
                    isPBR = pdTRUE;
                }
                else
                {
                    xError = FF_ERR_IOMAN_INVALID_FORMAT | FF_PARTITIONSEARCH;
                    break;
                }
            }
            else if( pxPartitions[ xPartNr ].ulSectorCount )
            {
                FF_Part_t * p = &pPartsFound->pxPartitions[ pPartsFound->iCount++ ];
                *p = pxPartitions[ xPartNr ];
                p->bIsExtended = 0;

                if( pPartsFound->iCount >= ffconfigMAX_PARTITIONS )
                {
                    break;
                }
            }
        }

        if( FF_isERR( xError ) || ( pPartsFound->iCount >= ffconfigMAX_PARTITIONS ) )
        {
            break;
        }

        for( xPartNr = 0; xPartNr < 4; xPartNr++ )
        {
            if( prvIsExtendedPartition( pxPartitions[ xPartNr ].ucPartitionID ) )
            {
                xError = FF_ParseExtended( pxIOManager, pxPartitions[ xPartNr ].ulStartLBA,
                                           pxPartitions[ xPartNr ].ulSectorCount, pPartsFound );

                if( ( FF_isERR( xError ) != pdFALSE ) || ( pPartsFound->iCount >= ffconfigMAX_PARTITIONS ) )
                {
                    goto done;
                }
            }
        }

        if( pPartsFound->iCount == 0 )
        {
            FF_PRINTF( "FF_Part: no partitions, try as PBR\n" );
            isPBR = pdTRUE;
        }

        if( isPBR )
        {
            uint8_t media = FF_getChar( ucDataBuffer, FF_FAT_MEDIA_TYPE );
            FF_Part_t * p;

            if( !prvIsValidMedia( media ) )
            {
                FF_PRINTF( "FF_Part: Looks like PBR but media %02X\n", media );
                xError = FF_ERR_IOMAN_NO_MOUNTABLE_PARTITION | FF_PARTITIONSEARCH;
                goto done;
            }

            /* This looks like a PBR because it has a valid media type */
            p = pPartsFound->pxPartitions;
            p->ulStartLBA = 0; /* FF_FAT_PTBL_LBA */
            p->ulSectorCount = ( uint32_t ) FF_getShort( pxBuffer->pucBuffer, FF_FAT_16_TOTAL_SECTORS );

            if( p->ulSectorCount == 0ul )
            {
                p->ulSectorCount = FF_getLong( pxBuffer->pucBuffer, FF_FAT_32_TOTAL_SECTORS );
            }

            p->ucActive = 0x80;      /* FF_FAT_PTBL_ACTIVE */
            p->ucPartitionID = 0x0B; /* FF_FAT_PTBL_ID MSDOS data partition */
            p->bIsExtended = 0;
            pPartsFound->iCount = 1;
        }
    } while( pdFALSE );

done:

    if( pxBuffer )
    {
        FF_Error_t xTempError = FF_ReleaseBuffer( pxIOManager, pxBuffer );

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

    pxIOManager->xPartition.ulTotalSectors = prevTotalSectors;

    return FF_isERR( xError ) ? xError : pPartsFound->iCount;
} /* FF_PartitionSearch() */