REDSTATUS RedCoreInit()

in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/core.c [84:283]


REDSTATUS RedCoreInit(void)
{
    REDSTATUS       ret = 0;
    uint8_t         bVolNum;
  #if REDCONF_OUTPUT == 1
    static uint8_t  bSignedOn = 0U; /* Whether the sign on has been printed. */

    if(bSignedOn == 0U)
    {
        RedSignOn();
        bSignedOn = 1U;
    }
  #else
    /*  Call RedSignOn() even when output is disabled, to force the copyright
        text to be referenced and pulled into the program data.
    */
    RedSignOn();
  #endif

    RedMemSet(gaRedVolume, 0U, sizeof(gaRedVolume));
    RedMemSet(gaCoreVol, 0U, sizeof(gaCoreVol));

    RedBufferInit();

    for(bVolNum = 0U; bVolNum < REDCONF_VOLUME_COUNT; bVolNum++)
    {
        VOLUME         *pVol = &gaRedVolume[bVolNum];
        COREVOLUME     *pCoreVol = &gaCoreVol[bVolNum];
        const VOLCONF  *pVolConf = &gaRedVolConf[bVolNum];

        if(    (pVolConf->ulSectorSize < SECTOR_SIZE_MIN)
            || ((REDCONF_BLOCK_SIZE % pVolConf->ulSectorSize) != 0U)
            || (pVolConf->ulInodeCount == 0U))
        {
            ret = -RED_EINVAL;
        }
      #if REDCONF_API_POSIX == 1
        else if(pVolConf->pszPathPrefix == NULL)
        {
            ret = -RED_EINVAL;
        }
        else
        {
          #if REDCONF_VOLUME_COUNT > 1U
            uint8_t bCmpVol;

            /*  Ensure there are no duplicate path prefixes.  Check against all
                previous volumes, which are already verified.
            */
            for(bCmpVol = 0U; bCmpVol < bVolNum; bCmpVol++)
            {
                const char *pszCmpPathPrefix = gaRedVolConf[bCmpVol].pszPathPrefix;

                if(RedStrCmp(pVolConf->pszPathPrefix, pszCmpPathPrefix) == 0)
                {
                    ret = -RED_EINVAL;
                    break;
                }
            }
          #endif
        }
      #endif

        if(ret == 0)
        {
            pVol->bBlockSectorShift = 0U;
            while((pVolConf->ulSectorSize << pVol->bBlockSectorShift) < REDCONF_BLOCK_SIZE)
            {
                pVol->bBlockSectorShift++;
            }

            /*  This should always be true since the block size is confirmed to
                be a power of two (checked at compile time) and above we ensured
                that (REDCONF_BLOCK_SIZE % pVolConf->ulSectorSize) == 0.
            */
            REDASSERT((pVolConf->ulSectorSize << pVol->bBlockSectorShift) == REDCONF_BLOCK_SIZE);

            pVol->ulBlockCount = (uint32_t)(pVolConf->ullSectorCount >> pVol->bBlockSectorShift);

            if(pVol->ulBlockCount < MINIMUM_METADATA_BLOCKS)
            {
                ret = -RED_EINVAL;
            }
            else
            {
              #if REDCONF_READ_ONLY == 0
                pVol->ulTransMask = REDCONF_TRANSACT_DEFAULT;
              #endif

                pVol->ullMaxInodeSize = INODE_SIZE_MAX;

                /*  To understand the following code, note that the fixed-
                    location metadata is located at the start of the disk, in
                    the following order:

                    - Master block (1 block)
                    - Metaroots (2 blocks)
                    - External imap blocks (variable * 2 blocks)
                    - Inode blocks (pVolConf->ulInodeCount * 2 blocks)
                */

                /*  The imap needs bits for all inode and allocable blocks.  If
                    that bitmap will fit into the metaroot, the inline imap is
                    used and there are no imap nodes on disk.  The minus 3 is
                    there since the imap does not include bits for the master
                    block or metaroots.
                */
                pCoreVol->fImapInline = (pVol->ulBlockCount - 3U) <= METAROOT_ENTRIES;

                if(pCoreVol->fImapInline)
                {
                  #if REDCONF_IMAP_INLINE == 1
                    pCoreVol->ulInodeTableStartBN = 3U;
                  #else
                    ret = -RED_EINVAL;
                  #endif
                }
                else
                {
                  #if REDCONF_IMAP_EXTERNAL == 1
                    pCoreVol->ulImapStartBN = 3U;

                    /*  The imap does not include bits for itself, so add two to
                        the number of imap entries for the two blocks of each
                        imap node.  This allows us to divide up the remaining
                        space, making sure to round up so all data blocks are
                        covered.
                    */
                    pCoreVol->ulImapNodeCount =
                        ((pVol->ulBlockCount - 3U) + ((IMAPNODE_ENTRIES + 2U) - 1U)) / (IMAPNODE_ENTRIES + 2U);

                    pCoreVol->ulInodeTableStartBN = pCoreVol->ulImapStartBN + (pCoreVol->ulImapNodeCount * 2U);
                  #else
                    ret = -RED_EINVAL;
                  #endif
                }
            }
        }

        if(ret == 0)
        {
            pCoreVol->ulFirstAllocableBN = pCoreVol->ulInodeTableStartBN + (pVolConf->ulInodeCount * 2U);

            if(pCoreVol->ulFirstAllocableBN > pVol->ulBlockCount)
            {
                /*  We can get here if there is not enough space for the number
                    of configured inodes.
                */
                ret = -RED_EINVAL;
            }
            else
            {
                pVol->ulBlocksAllocable = pVol->ulBlockCount - pCoreVol->ulFirstAllocableBN;
            }
        }

        if(ret != 0)
        {
            break;
        }
    }

    /*  Make sure the configured endianness is correct.
    */
    if(ret == 0)
    {
        uint16_t    uValue = 0xFF00U;
        uint8_t     abBytes[2U];

        RedMemCpy(abBytes, &uValue, sizeof(abBytes));

      #if REDCONF_ENDIAN_BIG == 1
        if(abBytes[0U] != 0xFFU)
      #else
        if(abBytes[0U] != 0x00U)
      #endif
        {
            ret = -RED_EINVAL;
        }
    }

    if(ret == 0)
    {
        ret = RedOsClockInit();

      #if REDCONF_TASK_COUNT > 1U
        if(ret == 0)
        {
            ret = RedOsMutexInit();

            if(ret != 0)
            {
                (void)RedOsClockUninit();
            }
        }
      #endif
    }

    return ret;
}