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;
}