From daf6c04b597705fce36f06e116de3b5464ab9417 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 6 Oct 2020 19:29:47 -0400 Subject: [PATCH] Fix #56, Refactor CDS to use generic pool implementation Rather than having a second pool implementation only for CDS, use the generic pool implementation. This also uses the abstract resource identifiers to identify CDS blocks, rather than a direct reference. --- fsw/cfe-core/src/es/cfe_es_api.c | 34 +- fsw/cfe-core/src/es/cfe_es_cds.c | 949 ++++++++++++--------- fsw/cfe-core/src/es/cfe_es_cds.h | 461 +++++++++- fsw/cfe-core/src/es/cfe_es_cds_mempool.c | 662 ++++---------- fsw/cfe-core/src/es/cfe_es_cds_mempool.h | 60 +- fsw/cfe-core/src/es/cfe_es_global.h | 5 +- fsw/cfe-core/src/es/cfe_es_task.c | 13 +- fsw/cfe-core/src/inc/cfe_error.h | 3 +- fsw/cfe-core/src/inc/cfe_es.h | 21 +- fsw/cfe-core/src/inc/private/cfe_private.h | 4 +- fsw/cfe-core/src/tbl/cfe_tbl_internal.c | 2 +- fsw/cfe-core/unit-test/es_UT.c | 887 +++++++++---------- fsw/cfe-core/unit-test/es_UT.h | 2 +- fsw/cfe-core/unit-test/tbl_UT.c | 6 +- fsw/cfe-core/ut-stubs/ut_es_stubs.c | 14 +- 15 files changed, 1620 insertions(+), 1503 deletions(-) diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index 81fcb98c7..0af796c15 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -1397,7 +1397,7 @@ uint32 CFE_ES_CalculateCRC(const void *DataPtr, uint32 DataLength, uint32 InputC ** Purpose: Allocate a data block for a Critical Data Store. ** */ -int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, int32 BlockSize, const char *Name) +int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, CFE_ES_CDS_Offset_t BlockSize, const char *Name) { int32 Status; size_t NameLen = 0; @@ -1406,6 +1406,9 @@ int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, int32 BlockSize, cons char AppName[OS_MAX_API_NAME] = {"UNKNOWN"}; char CDSName[CFE_ES_CDS_MAX_FULL_NAME_LEN] = {""}; + /* Initialize output to safe value, in case this fails */ + *CDSHandlePtr = CFE_ES_RESOURCEID_UNDEFINED; + /* Check to make sure calling application is legit */ Status = CFE_ES_GetAppID(&ThisAppId); @@ -1413,7 +1416,7 @@ int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, int32 BlockSize, cons { CFE_ES_WriteToSysLog("CFE_CDS:Register-Bad AppId context\n"); } - else if (CFE_ES_Global.CDSVars.MemPoolSize == 0) + else if (!CFE_ES_Global.CDSIsAvailable) { CFE_ES_WriteToSysLog("CFE_CDS:Register-CDS not available\n"); Status = CFE_ES_NOT_IMPLEMENTED; @@ -1441,16 +1444,13 @@ int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, int32 BlockSize, cons /* of the form "AppName.Name" */ CFE_ES_FormCDSName(CDSName, Name, ThisAppId); - /* Make sure the specified size is acceptable */ - if (BlockSize == 0) - { - Status = CFE_ES_CDS_INVALID_SIZE; - CFE_ES_WriteToSysLog("CFE_CDS:Register-CDS %s has size of zero\n", Name); - } - else + /* Create CDS and designate it as NOT being a Critical Table */ + Status = CFE_ES_RegisterCDSEx(CDSHandlePtr, BlockSize, CDSName, false); + + /* If size is unacceptable, log it */ + if (Status == CFE_ES_CDS_INVALID_SIZE) { - /* Create CDS and designate it as NOT being a Critical Table */ - Status = CFE_ES_RegisterCDSEx(CDSHandlePtr, BlockSize, CDSName, false); + CFE_ES_WriteToSysLog("CFE_CDS:Register-CDS %s has invalid size (%lu)\n", Name, (unsigned long)BlockSize); } } } @@ -1479,11 +1479,7 @@ int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, int32 BlockSize, cons */ int32 CFE_ES_CopyToCDS(CFE_ES_CDSHandle_t Handle, void *DataToCopy) { - int32 Status; - - Status = CFE_ES_CDSBlockWrite(CFE_ES_Global.CDSVars.Registry[Handle].MemHandle, DataToCopy); - - return Status; + return CFE_ES_CDSBlockWrite(Handle, DataToCopy); } /* End of CFE_ES_CopyToCDS() */ /* @@ -1494,11 +1490,7 @@ int32 CFE_ES_CopyToCDS(CFE_ES_CDSHandle_t Handle, void *DataToCopy) */ int32 CFE_ES_RestoreFromCDS(void *RestoreToMemory, CFE_ES_CDSHandle_t Handle) { - int32 Status; - - Status = CFE_ES_CDSBlockRead(RestoreToMemory, CFE_ES_Global.CDSVars.Registry[Handle].MemHandle); - - return Status; + return CFE_ES_CDSBlockRead(RestoreToMemory, Handle); } /* End of CFE_ES_RestoreFromCDS() */ /* end of file */ diff --git a/fsw/cfe-core/src/es/cfe_es_cds.c b/fsw/cfe-core/src/es/cfe_es_cds.c index 0fbac201b..43861dda6 100644 --- a/fsw/cfe-core/src/es/cfe_es_cds.c +++ b/fsw/cfe-core/src/es/cfe_es_cds.c @@ -50,176 +50,251 @@ #include #include -/* Define offset addresses for CDS data segments */ -/* Each segment is guaranteed to start at a 4-byte offset boundary */ -#define CDS_REG_SIZE_OFFSET ((sizeof(CFE_ES_Global.CDSVars.ValidityField)+3) & 0xfffffffc) -#define CDS_REG_OFFSET (((CDS_REG_SIZE_OFFSET + sizeof(CFE_ES_Global.CDSVars.MaxNumRegEntries)) + 3) & 0xfffffffc) -#define CDS_POOL_OFFSET (((CDS_REG_OFFSET + (CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES * sizeof(CFE_ES_CDS_RegRec_t))) + 3) & 0xfffffffc) - -/*****************************************************************************/ -/** -** \brief Determines whether a CDS currently exists -** -** \par Description -** Reads a set of bytes from the beginning and end of the CDS memory -** area and determines if a fixed pattern is present, thus determining -** whether the CDS still likely contains valid data or not. -** -** \par Assumptions, External Events, and Notes: -** None -** -** \return #CFE_SUCCESS \copydoc CFE_SUCCESS -** \return #CFE_ES_CDS_INVALID \copydoc CFE_ES_CDS_INVALID -** \return Any of the return values from #CFE_PSP_ReadFromCDS -** -******************************************************************************/ -int32 CFE_ES_ValidateCDS(void); - -/*****************************************************************************/ -/** -** \brief Initializes the contents of the CDS -** -** \par Description -** Stores a fixed pattern at the beginning and end of the CDS memory -** to tag it for future verification following a reset. -** -** \par Assumptions, External Events, and Notes: -** None -** -** \param[in] CDSSize Total size of CDS memory area (in bytes) -** -** \return #OS_SUCCESS \copydoc OS_SUCCESS -** \return Any of the return values from #CFE_PSP_WriteToCDS -** \return Any of the return values from #CFE_ES_CreateCDSPool -** -******************************************************************************/ -int32 CFE_ES_InitializeCDS(uint32 CDSSize); - -/*****************************************************************************/ -/** -** \brief Initializes the CDS Registry -** -** \par Description -** Initializes the data structure used to keep track of CDS blocks and -** who they belong to. -** -** \par Assumptions, External Events, and Notes: -** None -** -** \retval #CFE_SUCCESS \copydoc CFE_SUCCESS -** -******************************************************************************/ -int32 CFE_ES_InitCDSRegistry(void); - - /*****************************************************************************/ -/** -** \brief Rebuilds memory pool for CDS and recovers existing registry -** -** \par Description -** Scans memory for existing CDS and initializes memory pool and registry -** settings accordingly -** -** \par Assumptions, External Events, and Notes: -** -# Assumes the validity of the CDS has already been determined -** -** \return #CFE_SUCCESS \copydoc CFE_SUCCESS -** \return Any of the return values from #CFE_PSP_ReadFromCDS -** -******************************************************************************/ -int32 CFE_ES_RebuildCDS(void); - +/* + * CFE_ES_CDS_EarlyInit + * + * NOTE: For complete prolog information, see 'cfe_es_cds.h' + */ /*****************************************************************************/ -/** -** \brief Initializes CDS data constructs -** -** \par Description -** Locates and validates any pre-existing CDS memory or initializes the -** memory as a fresh CDS. -** -** \par Assumptions, External Events, and Notes: -** None -** -** \par SysLog Messages -** -** -** \return None -** -******************************************************************************/ int32 CFE_ES_CDS_EarlyInit(void) { - uint32 MinRequiredSize = 0; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_Offset_t MinRequiredSize; int32 Status; - /* Compute the minimum size required for the CDS with the current configuration of the cFE */ - MinRequiredSize = (sizeof(CFE_ES_Global.CDSVars.ValidityField) * 2) + /* Minimum size for validity fields */ - (CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES * sizeof(CFE_ES_CDS_RegRec_t)) + /* Minimum size for CDS Registry contents */ - CFE_ES_CDSReqdMinSize(CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES); /* Max # of Min Sized Blocks */ - + CFE_ES_Global.CDSIsAvailable = false; + + /* Create CDS general access mutex */ + Status = OS_MutSemCreate(&CDS->GenMutex, + CFE_ES_CDS_MUT_REG_NAME, CFE_ES_CDS_MUT_REG_VALUE); + if (Status != OS_SUCCESS) + { + CFE_ES_SysLogWrite_Unsync("CFE_ES_CDS_EarlyInit: Failed to create mutex with error %d\n", (int)Status); + return CFE_STATUS_EXTERNAL_RESOURCE_FAIL; + } + /* Get CDS size from OS BSP */ - Status = CFE_PSP_GetCDSSize(&CFE_ES_Global.CDSVars.CDSSize); + Status = CFE_PSP_GetCDSSize(&CDS->TotalSize); + if (Status != CFE_PSP_SUCCESS) + { + /* Error getting the size of the CDS from the BSP */ + CFE_ES_WriteToSysLog("CFE_CDS:EarlyInit-Unable to obtain CDS Size from BSP (Err=0x%08X)\n", (unsigned int)Status); + return Status; + } + + /* Always truncate the size to the nearest 4 byte boundary */ + CDS->TotalSize &= 0xfffffffc; + + /* Compute the minimum size required for the CDS with the current configuration of the cFE */ + MinRequiredSize = CDS_RESERVED_MIN_SIZE; + MinRequiredSize += CFE_ES_CDSReqdMinSize(CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES); /* Max # of Min Sized Blocks */ - /* If the size was obtained successfully and meets the minimum requirements, then check its contents */ - if (Status == CFE_PSP_SUCCESS) + if (CDS->TotalSize < MinRequiredSize) { - /* Always truncate the size to the nearest 4 byte boundary */ - CFE_ES_Global.CDSVars.CDSSize &= 0xfffffffc; - - if (CFE_ES_Global.CDSVars.CDSSize >= MinRequiredSize) + CFE_ES_WriteToSysLog("CFE_CDS:EarlyInit-CDS Size (%lu) less than required (%lu)\n", + (unsigned long)CDS->TotalSize, (unsigned long)MinRequiredSize); + Status = CFE_SUCCESS; + } + else + { + CDS->DataSize = CDS->TotalSize; + CDS->DataSize -= CDS_RESERVED_MIN_SIZE; + + /* If the size was obtained successfully and meets the minimum requirements, then check its contents */ + Status = CFE_ES_ValidateCDS(); + + if (Status == CFE_SUCCESS) { - Status = CFE_ES_ValidateCDS(); - - /* If the CDS is accessible but invalid, then create a new one */ - if (Status == CFE_ES_CDS_INVALID) + /* If a valid CDS was found, rebuild the memory pool */ + Status = CFE_ES_RebuildCDS(); + } + + /* If the CDS is accessible but invalid, then create a new one */ + if (Status == CFE_ES_CDS_INVALID) + { + /* First wipe the entire CDS area */ + Status = CFE_ES_ClearCDS(); + + if (Status == CFE_SUCCESS) { - Status = CFE_ES_InitializeCDS(CFE_ES_Global.CDSVars.CDSSize); + Status = CFE_ES_InitCDSSignatures(); } - else if (Status == CFE_SUCCESS) - { - /* If a valid CDS was found, rebuild the memory pool */ - Status = CFE_ES_RebuildCDS(); - - /* If rebuilding is not possible, then create a new one from scratch */ - if (Status == CFE_ES_CDS_INVALID) - { - Status = CFE_ES_InitializeCDS(CFE_ES_Global.CDSVars.CDSSize); - } - } - else /* Unrecoverable error while reading the CDS */ + + if (Status == CFE_SUCCESS) { - CFE_ES_WriteToSysLog("CFE_CDS:EarlyInit-Read error validating CDS (Err=0x%08X)\n", (unsigned int)Status); - CFE_ES_Global.CDSVars.MemPoolSize = 0; - return Status; + /* Initialize the variables for managing the CDS Memory Pool */ + Status = CFE_ES_CreateCDSPool(CDS->DataSize, CDS_POOL_OFFSET); } if (Status == CFE_SUCCESS) { - /* Create CDS registry access mutex */ - OS_MutSemCreate(&CFE_ES_Global.CDSVars.RegistryMutex, - CFE_ES_CDS_MUT_REG_NAME, - CFE_ES_CDS_MUT_REG_VALUE); - } + Status = CFE_ES_InitCDSRegistry(); + } } - else /* Size < MinRequiredSize */ + + if (Status != CFE_SUCCESS) { - CFE_ES_WriteToSysLog("CFE_CDS:EarlyInit-CDS Size (%d) less than required (%d)\n", - (int)CFE_ES_Global.CDSVars.CDSSize, (int)MinRequiredSize); - CFE_ES_Global.CDSVars.MemPoolSize = 0; - return Status; + /* Unrecoverable error while reading the CDS */ + CFE_ES_WriteToSysLog("CFE_CDS:EarlyInit-error validating/initializing CDS (0x%08lX)\n", (unsigned long)Status); + } + else + { + /* Set the CDS Overall flag to be present/valid */ + CFE_ES_Global.CDSIsAvailable = true; } } - else /* Error getting the size of the CDS from the BSP */ - { - CFE_ES_WriteToSysLog("CFE_CDS:EarlyInit-Unable to obtain CDS Size from BSP (Err=0x%08X)\n", (unsigned int)Status); - CFE_ES_Global.CDSVars.MemPoolSize = 0; - return Status; - } - - - return(CFE_SUCCESS); + + return Status; } /* End of CFE_ES_CDS_EarlyInit() */ +/*******************************************************************/ +/* + * CFE_ES_LocateCDSBlockRecordByID + * + * NOTE: For complete prolog information, see 'cfe_es_cds.h' + */ +/*******************************************************************/ +int32 CFE_ES_CDSBlockID_ToIndex(CFE_ES_ResourceID_t BlockID, uint32 *Idx) +{ + return CFE_ES_ResourceID_ToIndex_Internal( + CFE_ES_ResourceID_ToInteger(BlockID) - CFE_ES_CDSBLOCKID_BASE, + CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES, + Idx); +} + +/*******************************************************************/ +/* + * CFE_ES_LocateCDSBlockRecordByID + * + * NOTE: For complete prolog information, see 'cfe_es_cds.h' + */ +/*******************************************************************/ +CFE_ES_CDS_RegRec_t* CFE_ES_LocateCDSBlockRecordByID(CFE_ES_ResourceID_t BlockID) +{ + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_RegRec_t *CDSRegRecPtr; + uint32 Idx; + + if (CFE_ES_CDSBlockID_ToIndex(BlockID, &Idx) == CFE_SUCCESS) + { + CDSRegRecPtr = &CDS->Registry[Idx]; + } + else + { + CDSRegRecPtr = NULL; + } + + return CDSRegRecPtr; +} + + +/*******************************************************************/ +/* + * CFE_ES_CacheRead() + * + * NOTE: For complete prolog information, see 'cfe_es_cds.h' + */ +/*******************************************************************/ +int32 CFE_ES_CDS_CacheFetch(CFE_ES_CDS_AccessCache_t *Cache, + CFE_ES_CDS_Offset_t Offset, CFE_ES_CDS_Offset_t Size) +{ + int32 Status; + + if (Size > 0 && Size <= sizeof(Cache->Data)) + { + Cache->AccessStatus = CFE_PSP_ReadFromCDS(&Cache->Data, + Offset, Size); + + if (Cache->AccessStatus == CFE_PSP_SUCCESS) + { + Cache->Offset = Offset; + Cache->Size = Size; + Status = CFE_SUCCESS; + } + else + { + Status = CFE_ES_CDS_ACCESS_ERROR; + } + } + else + { + Status = CFE_ES_CDS_INVALID_SIZE; + } + + return Status; +} + +/*******************************************************************/ +/* + * CFE_ES_CDS_CacheFlush() + * + * NOTE: For complete prolog information, see 'cfe_es_cds.h' + */ +/*******************************************************************/ +int32 CFE_ES_CDS_CacheFlush(CFE_ES_CDS_AccessCache_t *Cache) +{ + int32 Status; + + if (Cache->Size > 0 && Cache->Size <= sizeof(Cache->Data)) + { + Cache->AccessStatus = CFE_PSP_WriteToCDS(&Cache->Data, + Cache->Offset, Cache->Size); + + if (Cache->AccessStatus == CFE_PSP_SUCCESS) + { + Status = CFE_SUCCESS; + } + else + { + Status = CFE_ES_CDS_ACCESS_ERROR; + } + } + else + { + Status = CFE_ES_CDS_INVALID_SIZE; + } + + return Status; +} + +/*******************************************************************/ +/* + * CFE_ES_CDS_CachePreload() + * + * NOTE: For complete prolog information, see 'cfe_es_cds.h' + */ +/*******************************************************************/ +int32 CFE_ES_CDS_CachePreload(CFE_ES_CDS_AccessCache_t *Cache, const void *Source, CFE_ES_CDS_Offset_t Offset, CFE_ES_CDS_Offset_t Size) +{ + int32 Status; + + if (Size > 0 && Size <= sizeof(Cache->Data)) + { + if (Source == NULL) + { + /* just zero it out */ + memset(&Cache->Data, 0, Size); + } + else if (Source != &Cache->Data) + { + /* copy from the user-supplied preload data */ + memcpy(&Cache->Data, Source, Size); + } + Cache->Size = Size; + Cache->Offset = Offset; + Status = CFE_SUCCESS; + } + else + { + Status = CFE_ES_CDS_INVALID_SIZE; + } + + return Status; +} + + /******************************************************************* ** ** CFE_ES_RegisterCDSEx @@ -227,94 +302,151 @@ int32 CFE_ES_CDS_EarlyInit(void) ** NOTE: For complete prolog information, see 'cfe_es_cds.h' ********************************************************************/ -int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, int32 BlockSize, const char *Name, bool CriticalTbl) +int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, CFE_ES_CDS_Offset_t UserBlockSize, const char *Name, bool CriticalTbl) { - int32 Status = CFE_SUCCESS; - uint32 RegIndx; - CFE_ES_CDS_RegRec_t *RegRecPtr = NULL; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + int32 Status = CFE_SUCCESS; + int32 RegUpdateStatus = CFE_SUCCESS; + CFE_ES_CDS_RegRec_t *RegRecPtr; + CFE_ES_MemOffset_t BlockOffset; + CFE_ES_MemOffset_t OldBlockSize; + CFE_ES_MemOffset_t NewBlockSize; + bool IsNewEntry = false; + bool IsNewOffset = false; + if (UserBlockSize == 0 || UserBlockSize > CDS_ABS_MAX_BLOCK_SIZE) + { + /* Block size is not supportable */ + return CFE_ES_CDS_INVALID_SIZE; + } + /* Lock Registry for update. This prevents two applications from */ /* trying to register CDSs at the same location at the same time */ - CFE_ES_LockCDSRegistry(); + CFE_ES_LockCDS(); /* Check for duplicate CDS name */ - RegIndx = CFE_ES_FindCDSInRegistry(Name); + RegRecPtr = CFE_ES_FindCDSInRegistry(Name); - /* Check to see if CDS is already in the registry */ - if (RegIndx != CFE_ES_CDS_NOT_FOUND) + /* If not found then make a new entry */ + if (RegRecPtr == NULL) { - /* Get pointer to Registry Record Entry to speed up processing */ - RegRecPtr = &CFE_ES_Global.CDSVars.Registry[RegIndx]; + RegRecPtr = CFE_ES_AllocateNewCDSRegistryEntry(); + IsNewEntry = true; + } - /* If the new CDS is the same size as the old, then no need to reallocate memory */ - if (BlockSize != RegRecPtr->Size) + if (RegRecPtr == NULL) + { + Status = CFE_ES_CDS_REGISTRY_FULL; + } + else + { + /* Account for the extra header which will be added */ + NewBlockSize = UserBlockSize; + NewBlockSize += sizeof(CFE_ES_CDS_BlockHeader_t); + + + /* If a reallocation is needed, the old block may need to be freed first */ + if (Status == CFE_SUCCESS && + RegRecPtr->BlockOffset != 0 && + NewBlockSize != RegRecPtr->BlockSize) { /* If the new size is different, the old CDS must be deleted first */ - /* Free the old memory */ - Status = CFE_ES_PutCDSBlock(RegRecPtr->MemHandle); + Status = CFE_ES_GenPoolPutBlock(&CDS->Pool, &OldBlockSize, RegRecPtr->BlockOffset); + + /* + * Note because CDS puts a signature at the very beginning of the memory, + * valid data offsets are never zero. + */ + if (Status == CFE_SUCCESS) + { + RegRecPtr->BlockOffset = 0; + RegRecPtr->BlockSize = 0; + } } - else + + /* If a new allocation is needed, do it now */ + if (Status == CFE_SUCCESS && RegRecPtr->BlockOffset == 0) { - /* Warn calling application that this is a duplicate registration */ - Status = CFE_ES_CDS_ALREADY_EXISTS; - - /* Return the index into the registry as the handle to the CDS */ - *HandlePtr = RegIndx; + /* Allocate the block for the CDS */ + Status = CFE_ES_GenPoolGetBlock(&CDS->Pool, &BlockOffset, NewBlockSize); + if (Status == CFE_SUCCESS) + { + /* Save the size of the CDS */ + RegRecPtr->BlockOffset = BlockOffset; + RegRecPtr->BlockSize = NewBlockSize; + IsNewOffset = true; + } } - } - else /* CDS not already in registry */ - { - /* Locate empty slot in table registry */ - RegIndx = CFE_ES_FindFreeCDSRegistryEntry(); - - /* Check to make sure we found a free entry in registry */ - if (RegIndx == CFE_ES_CDS_NOT_FOUND) + + if (IsNewEntry) { - Status = CFE_ES_CDS_REGISTRY_FULL; - CFE_ES_WriteToSysLog("CFE_CDS:Register-Registry full\n"); + if (Status == CFE_SUCCESS) + { + /* Save flag indicating whether it is a Critical Table or not */ + RegRecPtr->Table = CriticalTbl; + + /* Save CDS Name in Registry */ + strncpy(RegRecPtr->Name, Name, sizeof(RegRecPtr->Name)-1); + RegRecPtr->Name[sizeof(RegRecPtr->Name)-1] = 0; + } + else + { + /* On failure set it free */ + CFE_ES_CDSBlockRecordSetFree(RegRecPtr); + } } - else + + if (IsNewOffset || IsNewEntry) { - RegRecPtr = &CFE_ES_Global.CDSVars.Registry[RegIndx]; + /* If we succeeded at creating a CDS, save updated registry in the CDS */ + RegUpdateStatus = CFE_ES_UpdateCDSRegistry(); } } - /* If no errors, then initialize the CDS registry entry */ + /* + * Export handle to caller before unlock + */ if (Status == CFE_SUCCESS) { - /* Allocate the memory buffer for the CDS */ - Status = CFE_ES_GetCDSBlock((CFE_ES_CDSBlockHandle_t *)&RegRecPtr->MemHandle, BlockSize); - - if (Status == CFE_SUCCESS) - { - RegRecPtr->Taken = true; - - /* Save the size of the CDS */ - RegRecPtr->Size = BlockSize; - - /* Save flag indicating whether it is a Critical Table or not */ - RegRecPtr->Table = CriticalTbl; - - /* Save CDS Name in Registry */ - strncpy(RegRecPtr->Name, Name, sizeof(RegRecPtr->Name)-1); - RegRecPtr->Name[sizeof(RegRecPtr->Name)-1] = 0; - - /* Return the index into the registry as the handle to the CDS */ - *HandlePtr = RegIndx; - - /* If we succeeded at creating a CDS, save updated registry in the CDS */ - Status = CFE_ES_UpdateCDSRegistry(); - - if (Status != CFE_SUCCESS) - { - CFE_ES_WriteToSysLog("CFE_CDS:RegCDS-Failed to update CDS Registry (Stat=0x%08X)\n", (unsigned int)Status); - } - } + *HandlePtr = CFE_ES_CDSBlockRecordGetID(RegRecPtr); + } + else + { + *HandlePtr = CFE_ES_RESOURCEID_UNDEFINED; } /* Unlock Registry for update */ - CFE_ES_UnlockCDSRegistry(); + CFE_ES_UnlockCDS(); + + /* Log any failures AFTER releasing the lock */ + if (RegUpdateStatus != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("CFE_CDS:RegCDS-Failed to update CDS Registry (Stat=0x%08X)\n", (unsigned int)RegUpdateStatus); + + /* + * Return failure only if this was the primary error, + * do not overwrite a preexisting error. + */ + if (Status == CFE_SUCCESS) + { + Status = RegUpdateStatus; + } + } + if (Status == CFE_SUCCESS && !IsNewOffset) + { + /* + * For backward compatibility, return the + * special non-success success code when + * reallocating an existing CDS. + * + * Note this intentionally needs to return CFE_SUCCESS + * when reusing an exiting entry but changing the size. + */ + Status = CFE_ES_CDS_ALREADY_EXISTS; + } + + return (Status); } /* End of CFE_ES_RegisterCDSEx() */ @@ -328,141 +460,133 @@ int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, int32 BlockSize, const int32 CFE_ES_ValidateCDS(void) { - /* Assume the CDS is invalid */ + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_Offset_t TrailerOffset; + const CFE_ES_CDS_Offset_t SIG_CDS_SIZE = { CFE_ES_CDS_SIGNATURE_LEN }; int32 Status; /* Perform 2 checks to validate the CDS Memory Pool */ /* First, determine if the first validity check field is correct */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_Global.CDSVars.ValidityField, 0, sizeof(CFE_ES_Global.CDSVars.ValidityField)); + Status = CFE_ES_CDS_CacheFetch(&CDS->Cache, CDS_SIG_BEGIN_OFFSET, SIG_CDS_SIZE); + if (Status != CFE_PSP_SUCCESS) + { + CFE_ES_WriteToSysLog("CFE_CDS:Validate-1st ReadFromCDS Failed. Status=0x%X\n", (unsigned int)Status); + return Status; + } - if (Status == CFE_PSP_SUCCESS) + if (strncmp(CDS->Cache.Data.Sig, CFE_ES_CDS_SIGNATURE_BEGIN, CFE_ES_CDS_SIGNATURE_LEN) != 0) { - if (strncmp(CFE_ES_Global.CDSVars.ValidityField, "_CDSBeg_", sizeof(CFE_ES_Global.CDSVars.ValidityField)) == 0) - { - Status = CFE_PSP_ReadFromCDS(&CFE_ES_Global.CDSVars.ValidityField, - (CFE_ES_Global.CDSVars.CDSSize-sizeof(CFE_ES_Global.CDSVars.ValidityField)), - sizeof(CFE_ES_Global.CDSVars.ValidityField)); - - if (Status == CFE_PSP_SUCCESS) - { - if (strncmp(CFE_ES_Global.CDSVars.ValidityField, "_CDSEnd_", sizeof(CFE_ES_Global.CDSVars.ValidityField)) == 0) - { - Status = CFE_SUCCESS; - } - else /* Validity Field failed */ - { - Status = CFE_ES_CDS_INVALID; - } - } - else /* BSP reported an error reading from CDS */ - { - CFE_ES_WriteToSysLog("CFE_CDS:Validate-2nd ReadFromCDS Failed. Status=0x%X\n", (unsigned int)Status); - } - } - else /* Validity Field failed */ - { - Status = CFE_ES_CDS_INVALID; - } + /* Beginning Validity Field failed */ + return CFE_ES_CDS_INVALID; } - else /* BSP reported an error reading from CDS */ + + TrailerOffset = CDS->TotalSize; + TrailerOffset -= sizeof(CFE_ES_CDS_PersistentTrailer_t); + + Status = CFE_ES_CDS_CacheFetch(&CDS->Cache, TrailerOffset, SIG_CDS_SIZE); + if (Status != CFE_PSP_SUCCESS) { - CFE_ES_WriteToSysLog("CFE_CDS:Validate-1st ReadFromCDS Failed. Status=0x%X\n", (unsigned int)Status); + /* BSP reported an error reading from CDS */ + CFE_ES_WriteToSysLog("CFE_CDS:Validate-2nd ReadFromCDS Failed. Status=0x%X\n", (unsigned int)Status); + return Status; + } + + if (strncmp(CDS->Cache.Data.Sig, CFE_ES_CDS_SIGNATURE_END, CFE_ES_CDS_SIGNATURE_LEN) != 0) + { + /* Ending Validity Field failed */ + return CFE_ES_CDS_INVALID; } - return Status; + /* All sanity checks passed */ + return CFE_SUCCESS; } /* End of CFE_ES_ValidateCDS() */ /******************************************************************* ** -** CFE_ES_InitializeCDS +** CFE_ES_ClearCDS ** ** NOTE: For complete prolog information, see prototype above ********************************************************************/ -int32 CFE_ES_InitializeCDS(uint32 CDSSize) +int32 CFE_ES_ClearCDS(void) { - int32 Status = CFE_SUCCESS; - uint32 MemBlock[32]; - uint32 NumWritten=0; - uint32 Uint32Zero=0; - + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_Offset_t RemainSize; + int32 Status; + /* Clear the CDS to ensure everything is gone */ /* Create a block of zeros to write to the CDS */ - memset(MemBlock, 0, sizeof(MemBlock)); - + Status = CFE_ES_CDS_CachePreload(&CDS->Cache, NULL, + 0, sizeof(CDS->Cache.Data.Zero)); + /* While there is space to write another block of zeros, then do so */ - while (((NumWritten + sizeof(MemBlock)) <= CDSSize) && (Status == OS_SUCCESS)) + while (CDS->Cache.Offset < CDS->TotalSize) { - Status = CFE_PSP_WriteToCDS(MemBlock, NumWritten, sizeof(MemBlock)); - - if (Status == CFE_PSP_SUCCESS) + RemainSize = CDS->TotalSize - CDS->Cache.Offset; + if (RemainSize < sizeof(CDS->Cache.Data.Zero)) { - NumWritten += sizeof(MemBlock); + /* partial size */ + CDS->Cache.Size = RemainSize; } - } - - /* While there is space to write a uint32 of zeros, then do so */ - if ((Status == CFE_PSP_SUCCESS) && (NumWritten < CDSSize)) - { - while (((NumWritten + sizeof(uint32)) <= CDSSize) && (Status == CFE_PSP_SUCCESS)) + Status = CFE_ES_CDS_CacheFlush(&CDS->Cache); + if (Status != CFE_SUCCESS) { - Status = CFE_PSP_WriteToCDS(&Uint32Zero, NumWritten, sizeof(uint32)); - - if (Status == CFE_PSP_SUCCESS) - { - NumWritten += sizeof(uint32); - } + break; } + + CDS->Cache.Offset += CDS->Cache.Size; } - if (Status != CFE_PSP_SUCCESS) + if (Status != CFE_SUCCESS) { - CFE_ES_WriteToSysLog("CFE_CDS:Init-Clear CDS failed @ Offset=%d Status=0x%08X\n", (int)NumWritten, (unsigned int)Status); + CFE_ES_WriteToSysLog("CFE_CDS:Init-Clear CDS failed @ Offset=%lu Status=0x%08X\n", + (unsigned long)CDS->Cache.Offset, (unsigned int)CDS->Cache.AccessStatus); } - else + + return Status; +} + +/******************************************************************* +** +** CFE_ES_InitCDSSignatures +** +** NOTE: For complete prolog information, see prototype above +********************************************************************/ + +int32 CFE_ES_InitCDSSignatures(void) +{ + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_Offset_t SigOffset; + int32 Status; + + /* Initialize the Validity Check strings */ + SigOffset = 0; + CFE_ES_CDS_CachePreload(&CDS->Cache, CFE_ES_CDS_SIGNATURE_BEGIN, + SigOffset, CFE_ES_CDS_SIGNATURE_LEN); + Status = CFE_ES_CDS_CacheFlush(&CDS->Cache); + if (Status != CFE_SUCCESS) { - /* Initialize the Validity Check strings */ - Status = CFE_PSP_WriteToCDS("_CDSBeg_", 0, sizeof(CFE_ES_Global.CDSVars.ValidityField)); - if (Status == CFE_PSP_SUCCESS) - { - Status = CFE_PSP_WriteToCDS("_CDSEnd_", - (CDSSize-sizeof(CFE_ES_Global.CDSVars.ValidityField)), - sizeof(CFE_ES_Global.CDSVars.ValidityField)); - if (Status != CFE_PSP_SUCCESS) - { - CFE_ES_WriteToSysLog("CFE_CDS:Init-'_CDSEnd_' write failed. Status=0x%08X\n", (unsigned int)Status); - } - else - { - /* Determine the amount of CDS memory is available for the CDS Memory Pool */ - /* Total CDS Size minus the validity fields and the space for the registry and the registry size */ - if (CDSSize < (CDS_POOL_OFFSET + sizeof(CFE_ES_Global.CDSVars.ValidityField))) - { - /* Invalid - passing zero will cause the CFE_ES_CreateCDSPool() to fail */ - CFE_ES_Global.CDSVars.MemPoolSize = 0; - } - else - { - CFE_ES_Global.CDSVars.MemPoolSize = CDSSize - CDS_POOL_OFFSET - sizeof(CFE_ES_Global.CDSVars.ValidityField); - } + /* BSP reported an error writing to CDS */ + CFE_ES_WriteToSysLog("CFE_CDS:Init-'_CDSBeg_' write failed. Status=0x%08X\n", + (unsigned int)CDS->Cache.AccessStatus); + return Status; + } - /* Initialize the variables for managing the CDS Memory Pool */ - Status = CFE_ES_CreateCDSPool(CFE_ES_Global.CDSVars.MemPoolSize, CDS_POOL_OFFSET); - - if (Status == CFE_SUCCESS) - { - Status = CFE_ES_InitCDSRegistry(); - } - } - } - else /* BSP reported an error writing to CDS */ - { - CFE_ES_WriteToSysLog("CFE_CDS:Init-'_CDSBeg_' write failed. Status=0x%08X\n", (unsigned int)Status); - } + SigOffset = CDS->TotalSize; + SigOffset -= sizeof(CFE_ES_CDS_PersistentTrailer_t); + + CFE_ES_CDS_CachePreload(&CDS->Cache, CFE_ES_CDS_SIGNATURE_END, + SigOffset, CFE_ES_CDS_SIGNATURE_LEN); + Status = CFE_ES_CDS_CacheFlush(&CDS->Cache); + if (Status != CFE_PSP_SUCCESS) + { + CFE_ES_WriteToSysLog("CFE_CDS:Init-'_CDSEnd_' write failed. Status=0x%08X\n", + (unsigned int)CDS->Cache.AccessStatus); + return Status; } - + return Status; -} /* End of CFE_ES_InitializeCDS() */ +} /* End of CFE_ES_InitCDSSignatures() */ /******************************************************************* ** @@ -473,32 +597,26 @@ int32 CFE_ES_InitializeCDS(uint32 CDSSize) int32 CFE_ES_InitCDSRegistry(void) { - int32 Status = CFE_SUCCESS; - uint32 i = 0; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + int32 Status; + uint32 RegSize; /* Initialize the local CDS Registry */ - CFE_ES_Global.CDSVars.MaxNumRegEntries = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES; - for (i=0; iCache, &RegSize, + CDS_REG_SIZE_OFFSET,sizeof(RegSize)); /* Copy the number of registry entries to the CDS */ - Status = CFE_PSP_WriteToCDS(&CFE_ES_Global.CDSVars.MaxNumRegEntries, - CDS_REG_SIZE_OFFSET, - sizeof(CFE_ES_Global.CDSVars.MaxNumRegEntries)); - - if (Status == CFE_PSP_SUCCESS) + Status = CFE_ES_CDS_CacheFlush(&CDS->Cache); + if (Status == CFE_SUCCESS) { + memset(CDS->Registry, 0, sizeof(CDS->Registry)); + Status = CFE_ES_UpdateCDSRegistry(); } else { - CFE_ES_WriteToSysLog("CFE_CDS:InitReg-Failed to write Reg Size. Status=0x%08X\n", (unsigned int)Status); + CFE_ES_WriteToSysLog("CFE_CDS:InitReg-Failed to write Reg Size. Status=0x%08X\n", + (unsigned int)CDS->Cache.AccessStatus); } return Status; @@ -513,16 +631,18 @@ int32 CFE_ES_InitCDSRegistry(void) int32 CFE_ES_UpdateCDSRegistry(void) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; int32 Status; /* Copy the contents of the local registry to the CDS */ - Status = CFE_PSP_WriteToCDS(CFE_ES_Global.CDSVars.Registry, + Status = CFE_PSP_WriteToCDS(CDS->Registry, CDS_REG_OFFSET, - sizeof(CFE_ES_Global.CDSVars.Registry)); + sizeof(CDS->Registry)); - if (Status != OS_SUCCESS) + if (Status != CFE_PSP_SUCCESS) { CFE_ES_WriteToSysLog("CFE_CDS:UpdateReg-Failed to write CDS Registry. Status=0x%08X\n", (unsigned int)Status); + Status = CFE_ES_CDS_ACCESS_ERROR; } return Status; @@ -559,16 +679,22 @@ void CFE_ES_FormCDSName(char *FullCDSName, const char *CDSName, CFE_ES_ResourceI ** NOTE: For complete prolog information, see 'cfe_es_cds.h' ********************************************************************/ -int32 CFE_ES_LockCDSRegistry(void) +int32 CFE_ES_LockCDS(void) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; int32 Status; - Status = OS_MutSemTake(CFE_ES_Global.CDSVars.RegistryMutex); + Status = OS_MutSemTake(CDS->GenMutex); + /* Convert to CFE return code */ if (Status == OS_SUCCESS) { Status = CFE_SUCCESS; } + else + { + Status = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; + } return Status; @@ -582,16 +708,22 @@ int32 CFE_ES_LockCDSRegistry(void) ** NOTE: For complete prolog information, see 'cfe_es_cds.h' ********************************************************************/ -int32 CFE_ES_UnlockCDSRegistry(void) +int32 CFE_ES_UnlockCDS(void) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; int32 Status; - Status = OS_MutSemGive(CFE_ES_Global.CDSVars.RegistryMutex); + Status = OS_MutSemGive(CDS->GenMutex); + /* Convert to CFE return code */ if (Status == OS_SUCCESS) { Status = CFE_SUCCESS; } + else + { + Status = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; + } return Status; @@ -605,30 +737,37 @@ int32 CFE_ES_UnlockCDSRegistry(void) ** NOTE: For complete prolog information, see 'cfe_es_cds.h' ********************************************************************/ -int32 CFE_ES_FindCDSInRegistry(const char *CDSName) +CFE_ES_CDS_RegRec_t *CFE_ES_FindCDSInRegistry(const char *CDSName) { - int32 RegIndx = CFE_ES_CDS_NOT_FOUND; - uint32 i = 0; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_RegRec_t *CDSRegRecPtr; + uint32 NumReg; - while ( (RegIndx == CFE_ES_CDS_NOT_FOUND) && (i < CFE_ES_Global.CDSVars.MaxNumRegEntries) ) + CDSRegRecPtr = CDS->Registry; + NumReg = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES; + while (true) { - /* Check to see if the record is currently being used */ - if (CFE_ES_Global.CDSVars.Registry[i].Taken == true) + if (NumReg == 0) + { + CDSRegRecPtr = NULL; /* not found */ + break; + } + + if (CFE_ES_CDSBlockRecordIsUsed(CDSRegRecPtr)) { /* Perform a case sensitive name comparison */ - if (strcmp(CDSName, CFE_ES_Global.CDSVars.Registry[i].Name) == 0) + if (strcmp(CDSName, CDSRegRecPtr->Name) == 0) { - /* If the names match, then return the index */ - RegIndx = i; + /* If the names match, then stop */ + break; } } - /* Point to next record in the CDS Registry */ - i++; - - }; + ++CDSRegRecPtr; + --NumReg; + } - return RegIndx; + return CDSRegRecPtr; } /* End of CFE_ES_FindCDSInRegistry() */ @@ -639,24 +778,40 @@ int32 CFE_ES_FindCDSInRegistry(const char *CDSName) ** NOTE: For complete prolog information, see 'cfe_es_cds.h' ********************************************************************/ -int32 CFE_ES_FindFreeCDSRegistryEntry(void) +CFE_ES_CDS_RegRec_t *CFE_ES_AllocateNewCDSRegistryEntry() { - int32 RegIndx = CFE_ES_CDS_NOT_FOUND; - uint32 i = 0; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + CFE_ES_CDS_RegRec_t *CDSRegRecPtr; + uint32 NumReg; - while ( (RegIndx == CFE_ES_CDS_NOT_FOUND) && (i < CFE_ES_Global.CDSVars.MaxNumRegEntries) ) + CDSRegRecPtr = CDS->Registry; + NumReg = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES; + while (true) { - if (CFE_ES_Global.CDSVars.Registry[i].Taken == false) + if (NumReg == 0) { - RegIndx = i; + CDSRegRecPtr = NULL; /* not found */ + break; } - else + + if (!CFE_ES_CDSBlockRecordIsUsed(CDSRegRecPtr)) { - i++; + /* Wipe it, just in case of stale data */ + memset(CDSRegRecPtr, 0, sizeof(*CDSRegRecPtr)); + + /* Set the ID which marks it as used */ + CFE_ES_CDSBlockRecordSetUsed(CDSRegRecPtr, + CFE_ES_ResourceID_FromInteger( + (CDSRegRecPtr - CDS->Registry) + + CFE_ES_CDSBLOCKID_BASE)); + break; } + + ++CDSRegRecPtr; + --NumReg; } - return RegIndx; + return CDSRegRecPtr; } /* End of CFE_ES_FindFreeCDSRegistryEntry() */ @@ -669,46 +824,40 @@ int32 CFE_ES_FindFreeCDSRegistryEntry(void) int32 CFE_ES_RebuildCDS(void) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; int32 Status; - int32 PoolOffset; /* First, determine if the CDS registry stored in the CDS is smaller or equal */ /* in size to the CDS registry we are currently configured for */ /* Copy the number of registry entries to the CDS */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_Global.CDSVars.MaxNumRegEntries, - CDS_REG_SIZE_OFFSET, - sizeof(CFE_ES_Global.CDSVars.MaxNumRegEntries)); - - if ((Status == CFE_PSP_SUCCESS) && - (CFE_ES_Global.CDSVars.MaxNumRegEntries <= CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES)) - { - Status = CFE_PSP_ReadFromCDS(&CFE_ES_Global.CDSVars.Registry, - CDS_REG_OFFSET, - (CFE_ES_Global.CDSVars.MaxNumRegEntries * sizeof(CFE_ES_CDS_RegRec_t))); - - if (Status == CFE_PSP_SUCCESS) - { - /* Calculate the starting offset of the memory pool */ - PoolOffset = (CDS_REG_OFFSET + (CFE_ES_Global.CDSVars.MaxNumRegEntries * sizeof(CFE_ES_CDS_RegRec_t)) + 3) & 0xfffffffc;; + Status = CFE_ES_CDS_CacheFetch(&CDS->Cache, CDS_REG_SIZE_OFFSET, sizeof(CDS->Cache.Data.RegistrySize)); + if (Status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("CFE_CDS:Rebuild-PSP Error reading Registry size (%lx)\n", (unsigned long)CDS->Cache.AccessStatus); + return CFE_ES_CDS_INVALID; + } - /* Calculate the size of the memory pool */ - CFE_ES_Global.CDSVars.MemPoolSize = CFE_ES_Global.CDSVars.CDSSize - PoolOffset - sizeof(CFE_ES_Global.CDSVars.ValidityField); - - /* Scan the memory pool and identify the created but currently unused memory blocks */ - Status = CFE_ES_RebuildCDSPool(CFE_ES_Global.CDSVars.MemPoolSize, PoolOffset); - } - else - { - /* Registry in CDS is unreadable */ - Status = CFE_ES_CDS_INVALID; - CFE_ES_WriteToSysLog("CFE_CDS:Rebuild-Registry in CDS is unreadable\n"); - } + if (CDS->Cache.Data.RegistrySize != CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES) + { + /* Registry in CDS is incompatible size to recover */ + CFE_ES_WriteToSysLog("CFE_CDS:Rebuild-Registry in CDS incorrect size (%lu)\n", (unsigned long)CDS->Cache.Data.RegistrySize); + return CFE_ES_CDS_INVALID; + } + + Status = CFE_PSP_ReadFromCDS(&CDS->Registry, + CDS_REG_OFFSET, + sizeof(CDS->Registry)); + + if (Status == CFE_PSP_SUCCESS) + { + /* Scan the memory pool and identify the created but currently unused memory blocks */ + Status = CFE_ES_RebuildCDSPool(CDS->DataSize, CDS_POOL_OFFSET); } else { - /* Registry in CDS is too large to recover */ + /* Registry in CDS is unreadable */ + CFE_ES_WriteToSysLog("CFE_CDS:Rebuild-Registry in CDS is unreadable, PSP error %lx\n", (unsigned long)Status); Status = CFE_ES_CDS_INVALID; - CFE_ES_WriteToSysLog("CFE_CDS:Rebuild-Registry in CDS too large to recover\n"); } return Status; @@ -724,29 +873,27 @@ int32 CFE_ES_RebuildCDS(void) int32 CFE_ES_DeleteCDS(const char *CDSName, bool CalledByTblServices) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; int32 Status; - int32 RegIndx; - CFE_ES_CDS_RegRec_t *RegRecPtr = NULL; + CFE_ES_CDS_RegRec_t *RegRecPtr; char OwnerName[OS_MAX_API_NAME]; CFE_ES_ResourceID_t AppId; uint32 i; char LogMessage[CFE_ES_MAX_SYSLOG_MSG_SIZE]; + CFE_ES_MemOffset_t OldBlockSize; LogMessage[0] = 0; /* Lock Registry for update. This prevents two applications from */ /* trying to change the CDS registry at the same time */ - CFE_ES_LockCDSRegistry(); + CFE_ES_LockCDS(); /* Find CDS name in registry */ - RegIndx = CFE_ES_FindCDSInRegistry(CDSName); + RegRecPtr = CFE_ES_FindCDSInRegistry(CDSName); /* Check to see if CDS is already in the registry */ - if (RegIndx != CFE_ES_CDS_NOT_FOUND) + if (RegRecPtr != NULL) { - /* Get pointer to Registry Record Entry to speed up processing */ - RegRecPtr = &CFE_ES_Global.CDSVars.Registry[RegIndx]; - /* Critical tables are not allowed to be deleted via an ES Command. */ /* They must be deleted by a Table Services Command */ if (RegRecPtr->Table != CalledByTblServices) @@ -771,23 +918,23 @@ int32 CFE_ES_DeleteCDS(const char *CDSName, bool CalledByTblServices) Status = CFE_ES_GetAppIDByName(&AppId, OwnerName); /* If we can't find the name, then things are good */ - if (Status == CFE_ES_ERR_APPNAME) + if (Status != CFE_SUCCESS) { /* Free the registry entry and the CDS memory block associated with it */ - Status = CFE_ES_PutCDSBlock(RegRecPtr->MemHandle); + Status = CFE_ES_GenPoolPutBlock(&CDS->Pool, &OldBlockSize, RegRecPtr->BlockOffset); /* Report any errors incurred while freeing the CDS Memory Block */ - if (Status < 0) + if (Status != CFE_SUCCESS) { CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), "CFE_ES:DeleteCDS-Failed to free CDS Mem Block (Handle=0x%08lX)(Stat=0x%08X)\n", - (unsigned long)RegRecPtr->MemHandle, (unsigned int)Status); + (unsigned long)RegRecPtr->BlockOffset, (unsigned int)Status); } else { /* Remove entry from the CDS Registry */ - RegRecPtr->Taken = false; - + CFE_ES_CDSBlockRecordSetFree(RegRecPtr); + Status = CFE_ES_UpdateCDSRegistry(); if (Status != CFE_SUCCESS) @@ -809,7 +956,7 @@ int32 CFE_ES_DeleteCDS(const char *CDSName, bool CalledByTblServices) } /* Unlock Registry for future updates */ - CFE_ES_UnlockCDSRegistry(); + CFE_ES_UnlockCDS(); /* Output the message to syslog once the CDS registry resource is unlocked */ if (LogMessage[0] != 0) diff --git a/fsw/cfe-core/src/es/cfe_es_cds.h b/fsw/cfe-core/src/es/cfe_es_cds.h index 501a0badb..192df3594 100644 --- a/fsw/cfe-core/src/es/cfe_es_cds.h +++ b/fsw/cfe-core/src/es/cfe_es_cds.h @@ -46,7 +46,7 @@ #include "cfe_es_apps.h" #include "cfe_platform_cfg.h" #include "cfe_es.h" -#include "cfe_es_cds_mempool.h" +#include "cfe_es_generic_pool.h" /* ** Macro Definitions @@ -54,46 +54,413 @@ /** \name Registry Mutex Definitions */ /** \{ */ -#define CFE_ES_CDS_MUT_REG_NAME "CDS_REG_MUT" /**< \brief Name of Mutex controlling CDS Registry Access */ -#define CFE_ES_CDS_MUT_REG_VALUE 0 /**< \brief Initial Value of CDS Registry Access Mutex */ +#define CFE_ES_CDS_MUT_REG_NAME "CDS_MUTEX" /**< \brief Name of Mutex controlling CDS Access */ +#define CFE_ES_CDS_MUT_REG_VALUE 0 /**< \brief Initial Value of CDS Access Mutex */ +/** \} */ -#define CFE_ES_CDS_NOT_FOUND (uint32)(0xffffffff) +/** \name Registry Signature Definitions */ +/** \{ */ +#define CFE_ES_CDS_SIGNATURE_LEN 8 /**< \brief Length of CDS signature field. */ +#define CFE_ES_CDS_SIGNATURE_BEGIN "_CDSBeg_" /**< \brief Fixed signature at beginning of CDS */ +#define CFE_ES_CDS_SIGNATURE_END "_CDSEnd_" /**< \brief Fixed signature at end of CDS */ /** \} */ + +/* + * Space in CDS should be aligned to a multiple of uint32 + * These helper macros round up to a whole number of words + */ +#define CDS_SIZE_TO_U32WORDS(x) (((x) + 3) / sizeof(uint32)) +#define CDS_RESERVE_SPACE(name,size) uint32 name[CDS_SIZE_TO_U32WORDS(size)] + +/* Define offset addresses for CDS data segments */ +#define CDS_SIG_BEGIN_OFFSET offsetof(CFE_ES_CDS_PersistentHeader_t, SignatureBegin) +#define CDS_REG_SIZE_OFFSET offsetof(CFE_ES_CDS_PersistentHeader_t, RegistrySize) +#define CDS_REG_OFFSET offsetof(CFE_ES_CDS_PersistentHeader_t, RegistryContent) +#define CDS_POOL_OFFSET sizeof(CFE_ES_CDS_PersistentHeader_t) + +/* + * Absolute Minimum CDS size conceivably supportable by the implementation. + * This is the space required for the basic signatures and registry information. + * It is not possible to create a CDS with a storage area smaller than this. + */ +#define CDS_RESERVED_MIN_SIZE sizeof(CFE_ES_CDS_PersistentHeader_t) + sizeof(CFE_ES_CDS_PersistentTrailer_t) + +/* + * Absolute Maximum Block size conceivably supportable by the implementation. + * User-defined platform limits (in cfe_platform_cfg.h) may be lower, + * but this is a hard limit to avoid overflow of CFE_ES_CDS_Offset_t. + */ +#define CDS_ABS_MAX_BLOCK_SIZE ((1 << ((8 * sizeof(CFE_ES_CDS_Offset_t))-2)) - sizeof(CFE_ES_CDS_BlockHeader_t)) + + + /* ** Type Definitions */ + +/** + * The structure cached in RAM for each block within the CDS non-volatile memory + * This has the basic runtime info without having to go to CDS. + */ typedef struct { + /* + * Note that the block size and offset stored here are for the + * total block size. The CDS code adds is own extra metadata + * which has a CRC, and therefore the actual user data size is + * less than this. + */ + CFE_ES_ResourceID_t BlockID; /**< Abstract ID associated with this CDS block */ + CFE_ES_CDS_Offset_t BlockOffset; /**< Start offset of the block in CDS memory */ + CFE_ES_CDS_Offset_t BlockSize; /**< Size, in bytes, of the CDS memory block */ char Name[CFE_ES_CDS_MAX_FULL_NAME_LEN]; - CFE_ES_CDSBlockHandle_t MemHandle; - uint32 Size; /**< \brief Size, in bytes, of the CDS memory block */ - bool Taken; /**< \brief Flag that indicates whether the registry record is in use */ - bool Table; /**< \brief Flag that indicates whether CDS contains a Critical Table */ + bool Table; /**< \brief Flag that indicates whether CDS contains a Critical Table */ } CFE_ES_CDS_RegRec_t; +typedef struct CFE_ES_CDSBlockHeader +{ + uint32 Crc; /**< CRC of content */ +} CFE_ES_CDS_BlockHeader_t; + +/* + * A generic buffer to hold the various objects that need + * to be cached in RAM from the CDS non-volatile storage. + */ +typedef union CFE_ES_CDS_AccessCacheData +{ + char Sig[CFE_ES_CDS_SIGNATURE_LEN]; /**< A signature field (beginning or end) */ + uint32 RegistrySize; /**< Registry Size Field */ + uint32 Zero[4]; /**< Used when clearing CDS content */ + CFE_ES_GenPoolBD_t Desc; /**< A generic block descriptor */ + CFE_ES_CDS_BlockHeader_t BlockHeader; /**< A user block header */ + CFE_ES_CDS_RegRec_t RegEntry; /**< A registry entry */ +} CFE_ES_CDS_AccessCacheData_t; + +typedef struct CFE_ES_CDS_AccessCache +{ + CFE_ES_CDS_AccessCacheData_t Data; /**< Cached data (varies in size) */ + CFE_ES_CDS_Offset_t Offset; /**< The offset where Data is cached from */ + CFE_ES_CDS_Offset_t Size; /**< The size of cached Data */ + int32 AccessStatus; /**< The PSP status of the last read/write from CDS memory */ +} CFE_ES_CDS_AccessCache_t; + +/** + * Instance data associated with a CDS + * + * Currently there is just one global CDS instance (i.e. a singleton) + * stored in the CFE_ES_Global structure. + */ typedef struct { - osal_id_t RegistryMutex; /**< \brief Mutex that controls access to CDS Registry */ - uint32 CDSSize; /**< \brief Total size of the CDS as reported by BSP */ - uint32 MemPoolSize; - uint32 MaxNumRegEntries; /**< \brief Maximum number of Registry entries */ + /* + * The generic pool structure + * This must be the first entry in this structure. + */ + CFE_ES_GenPoolRecord_t Pool; + + /* + * Cache of last accessed data block + * Because CDS memory is not memory mapped, this serves + * as temporary holding location for data being actively accessed. + */ + CFE_ES_CDS_AccessCache_t Cache; + + osal_id_t GenMutex; /**< \brief Mutex that controls access to CDS and registry */ + CFE_ES_CDS_Offset_t TotalSize; /**< \brief Total size of the CDS as reported by BSP */ + CFE_ES_CDS_Offset_t DataSize; /**< \brief Size of actual user data pool */ CFE_ES_CDS_RegRec_t Registry[CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES]; /**< \brief CDS Registry (Local Copy) */ - char ValidityField[8]; -} CFE_ES_CDSVariables_t; +} CFE_ES_CDS_Instance_t; + + +/* + * structs representing the intended layout of data + * in the actual CDS/PSP-provided non-volatile memory + * + * All blocks should be multiples of uint32 + * + * NOTE: these aren't necessarily instantiated in RAM, + * just in CDS. Mainly interested in the size of these + * elements, and offset of the various members within. + */ +typedef struct CFE_ES_CDS_PersistentHeader +{ + CDS_RESERVE_SPACE(SignatureBegin, CFE_ES_CDS_SIGNATURE_LEN); + CDS_RESERVE_SPACE(RegistrySize, sizeof(uint32)); + CDS_RESERVE_SPACE(RegistryContent, CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES * sizeof(CFE_ES_CDS_RegRec_t)); +} CFE_ES_CDS_PersistentHeader_t; + +typedef struct CFE_ES_CDS_PersistentTrailer +{ + CDS_RESERVE_SPACE(SignatureEnd, CFE_ES_CDS_SIGNATURE_LEN); +} CFE_ES_CDS_PersistentTrailer_t; + + + /*****************************************************************************/ /* ** Function prototypes */ -/* -** CFE_ES_CDS_EarlyInit -*/ +/** + * @brief Fetch data from the non-volatile storage and store in RAM cache + * + * This fetches a data segment from the PSP and loads it into the + * local CDS cache buffer. The content can be accessed via the + * "Data" member inside the cache structure. + * + * Only one thread can use CDS cache at a given time, so the CDS access + * control mutex must be obtained before calling this function. + * + * @param[inout] Cache the global CDS cache buffer + * @param[in] Offset the CDS offset to fetch + * @param[in] Size the CDS data size to fetch + * @returns #CFE_SUCCESS on success, or appropriate error code. + */ +int32 CFE_ES_CDS_CacheFetch(CFE_ES_CDS_AccessCache_t *Cache, + CFE_ES_CDS_Offset_t Offset, CFE_ES_CDS_Offset_t Size); + +/** + * @brief Write data from the RAM cache back to non-volatile storage + * + * This stores a data segment from the cache into the PSP for + * permanent storage. Data should be loaded into the cache + * prior to invoking this function, either via CFE_ES_CDS_CacheFetch() + * or CFE_ES_CDS_CachePreload(). + * + * Only one thread can use CDS cache at a given time, so the CDS access + * control mutex must be obtained before calling this function. + * + * @param[inout] Cache the global CDS cache buffer + * @returns #CFE_SUCCESS on success, or appropriate error code. + */ +int32 CFE_ES_CDS_CacheFlush(CFE_ES_CDS_AccessCache_t *Cache); + +/** + * @brief Preload the cache data from a local buffer + * + * This loads the CDS cache directly from a provided object/buffer to + * prepare for writing to PSP. The data can then be committed to PSP + * at a later time using CFE_ES_CDS_CacheFlush(). + * + * If Source is NULL, then the cache data will be initialized to zero. + * + * If Source refers to the cache buffer, then no copying will take place, because + * source and destination are the same. No copy is performed, and the data will be + * unchanged. In this mode only the size and offset are updated. + * + * Only one thread can use CDS cache at a given time, so the CDS access + * control mutex must be obtained before calling this function. + * + * + * @param[inout] Cache the global CDS cache buffer + * @param[in] Source the local object to load into cache + * @param[in] Offset the CDS offset to fetch + * @param[in] Size the CDS data size to fetch + * @returns #CFE_SUCCESS on success, or appropriate error code. + */ +int32 CFE_ES_CDS_CachePreload(CFE_ES_CDS_AccessCache_t *Cache, const void *Source, + CFE_ES_CDS_Offset_t Offset, CFE_ES_CDS_Offset_t Size); + +/** + * @brief Get the registry array index correlating with a CDS block ID + * + * Calculates the array position/index of the CDS registry entry for + * the given block ID. + * + * @param[in] BlockID the ID/handle of the CDS block to retrieve + * @param[out] Idx Output buffer to store the index + * @returns #CFE_SUCCESS if conversion successful. @copydoc CFE_SUCCESS + * #CFE_ES_RESOURCE_ID_INVALID if block ID is outside valid range + */ +int32 CFE_ES_CDSBlockID_ToIndex(CFE_ES_ResourceID_t BlockID, uint32 *Idx); + +/** + * @brief Get a registry record within the CDS, given a block ID/handle + * + * Retrieves a pointer to the registry record associated with a CDS block ID/handle + * Returns NULL if the handle is outside the valid range + * + * @note This only does the lookup, it does not validate that the handle + * actually matches the returned record. The caller should lock the CDS and + * confirm that the record is a match to the expected ID before using it. + * + * @param[in] BlockID the ID/handle of the CDS block to retrieve + * @returns Pointer to registry record, or NULL if ID/handle invalid. + */ +CFE_ES_CDS_RegRec_t* CFE_ES_LocateCDSBlockRecordByID(CFE_ES_ResourceID_t BlockID); + +/** + * @brief Check if a Memory Pool record is in use or free/empty + * + * This routine checks if the Pool table entry is in use or if it is free + * + * As this dereferences fields within the record, global data must be + * locked prior to invoking this function. + * + * @param[in] CDSBlockRecPtr pointer to Pool table entry + * @returns true if the entry is in use/configured, or false if it is free/empty + */ +static inline bool CFE_ES_CDSBlockRecordIsUsed(const CFE_ES_CDS_RegRec_t *CDSBlockRecPtr) +{ + return CFE_ES_ResourceID_IsDefined(CDSBlockRecPtr->BlockID); +} + +/** + * @brief Get the ID value from a Memory Pool table entry + * + * This routine converts the table entry back to an abstract ID. + * + * @param[in] CDSBlockRecPtr pointer to Pool table entry + * @returns BlockID of entry + */ +static inline CFE_ES_ResourceID_t CFE_ES_CDSBlockRecordGetID(const CFE_ES_CDS_RegRec_t *CDSBlockRecPtr) +{ + return (CDSBlockRecPtr->BlockID); +} + +/** + * @brief Marks a Memory Pool table entry as used (not free) + * + * This sets the internal field(s) within this entry, and marks + * it as being associated with the given Pool ID. + * + * @param[in] CDSBlockRecPtr pointer to Pool table entry + * @param[in] BlockID the Pool ID of this entry + */ +static inline void CFE_ES_CDSBlockRecordSetUsed(CFE_ES_CDS_RegRec_t *CDSBlockRecPtr, CFE_ES_ResourceID_t BlockID) +{ + CDSBlockRecPtr->BlockID = BlockID; +} + +/** + * @brief Set a Memory Pool record table entry free (not used) + * + * This clears the internal field(s) within this entry, and allows the + * memory to be re-used in the future. + * + * @param[in] CDSBlockRecPtr pointer to Pool table entry + */ +static inline void CFE_ES_CDSBlockRecordSetFree(CFE_ES_CDS_RegRec_t *CDSBlockRecPtr) +{ + CDSBlockRecPtr->BlockID = CFE_ES_RESOURCEID_UNDEFINED; +} + +/** + * @brief Check if a CDS block record is a match for the given BlockID + * + * This routine confirms that the previously-located record is valid + * and matches the expected block ID. + * + * As this dereferences fields within the record, CDS access mutex must be + * locked prior to invoking this function. + * + * @param[in] CDSBlockRecPtr pointer to registry table entry + * @param[in] BlockID expected block ID + * @returns true if the entry matches the given block ID + */ +static inline bool CFE_ES_CDSBlockRecordIsMatch(const CFE_ES_CDS_RegRec_t *CDSBlockRecPtr, CFE_ES_ResourceID_t BlockID) +{ + return (CDSBlockRecPtr != NULL && CFE_ES_ResourceID_Equal(CDSBlockRecPtr->BlockID, BlockID)); +} + +/** + * @brief Gets the data size from a given registry record + * + * This computes the usable data size of the CDS registry entry + * + * As this dereferences fields within the record, CDS access mutex must be + * locked prior to invoking this function. + * + * @note CDS entries include an extra header in addition to the data, + * which contains error checking information. Therefore the usable data + * size is less than the raw block size. + * + * @param[in] CDSBlockRecPtr pointer to registry table entry + * @returns Usable size of the CDS + */ +static inline CFE_ES_MemOffset_t CFE_ES_CDSBlockRecordGetUserSize(const CFE_ES_CDS_RegRec_t *CDSBlockRecPtr) +{ + return (CDSBlockRecPtr->BlockSize - sizeof(CFE_ES_CDS_BlockHeader_t)); +} + + +/*****************************************************************************/ +/** +** \brief Initializes CDS data constructs +** +** \par Description +** Locates and validates any pre-existing CDS memory or initializes the +** memory as a fresh CDS. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \par SysLog Messages +** +** +** \return None +** +******************************************************************************/ int32 CFE_ES_CDS_EarlyInit(void); + +/*****************************************************************************/ +/** +** \brief Determines whether a CDS currently exists +** +** \par Description +** Reads a set of bytes from the beginning and end of the CDS memory +** area and determines if a fixed pattern is present, thus determining +** whether the CDS still likely contains valid data or not. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \return #CFE_SUCCESS \copydoc CFE_SUCCESS +** \return #CFE_ES_CDS_INVALID \copydoc CFE_ES_CDS_INVALID +** \return Any of the return values from #CFE_PSP_ReadFromCDS +** +******************************************************************************/ +int32 CFE_ES_ValidateCDS(void); + +/*****************************************************************************/ +/** +** \brief Initializes the CDS Registry +** +** \par Description +** Initializes the data structure used to keep track of CDS blocks and +** who they belong to. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \retval #CFE_SUCCESS \copydoc CFE_SUCCESS +** +******************************************************************************/ +int32 CFE_ES_InitCDSRegistry(void); + + +/*****************************************************************************/ +/** +** \brief Rebuilds memory pool for CDS and recovers existing registry +** +** \par Description +** Scans memory for existing CDS and initializes memory pool and registry +** settings accordingly +** +** \par Assumptions, External Events, and Notes: +** -# Assumes the validity of the CDS has already been determined +** +** \return #CFE_SUCCESS \copydoc CFE_SUCCESS +** \return Any of the return values from #CFE_PSP_ReadFromCDS +** +******************************************************************************/ +int32 CFE_ES_RebuildCDS(void); + /*****************************************************************************/ /** ** \brief Copies the local version of the CDS Registry to the actual CDS @@ -150,47 +517,50 @@ void CFE_ES_FormCDSName(char *FullCDSName, const char *CDSName, CFE_ES_ResourceI ** \param[in] CDSName - Pointer to character string containing complete ** CDS Name (of the format "AppName.CDSName"). ** -** \retval #CFE_ES_CDS_NOT_FOUND or the Index into Registry for Table with specified name +** \retval NULL if not found, Non null entry pointer on success ** ******************************************************************************/ -int32 CFE_ES_FindCDSInRegistry(const char *CDSName); +CFE_ES_CDS_RegRec_t *CFE_ES_FindCDSInRegistry(const char *CDSName); /*****************************************************************************/ /** -** \brief Locates a free slot in the CDS Registry. +** \brief Locates a free slot in the CDS Registry and configures it for new use. ** ** \par Description -** Locates a free slot in the CDS Registry. +** Locates a free slot in the CDS Registry, assigns an ID, +** and marks the entry as used. ** ** \par Assumptions, External Events, and Notes: ** Note: This function assumes the registry has been locked. ** -** \retval #CFE_ES_CDS_NOT_FOUND or Index into CDS Registry of unused entry +** \retval NULL if registry full, Non null entry pointer on success ******************************************************************************/ -int32 CFE_ES_FindFreeCDSRegistryEntry(void); +CFE_ES_CDS_RegRec_t *CFE_ES_AllocateNewCDSRegistryEntry(void); /*****************************************************************************/ /** -** \brief Locks access to the CDS Registry +** \brief Locks access to the CDS ** ** \par Description -** Locks the CDS Registry to prevent multiple tasks/threads +** Locks the CDS to prevent multiple tasks/threads ** from modifying it at once. ** +** This lock covers both the registry and the data access. +** ** \par Assumptions, External Events, and Notes: ** None ** ** \retval #CFE_SUCCESS \copydoc CFE_SUCCESS ******************************************************************************/ -int32 CFE_ES_LockCDSRegistry(void); +int32 CFE_ES_LockCDS(void); /*****************************************************************************/ /** -** \brief Unlocks access to the CDS Registry +** \brief Unlocks access to the CDS ** ** \par Description -** Unlocks CDS Registry to allow other tasks/threads to -** modify the CDS Registry contents. +** Unlocks CDS to allow other tasks/threads to +** modify the CDS contents. ** ** \par Assumptions, External Events, and Notes: ** None @@ -198,7 +568,7 @@ int32 CFE_ES_LockCDSRegistry(void); ** \retval #CFE_SUCCESS \copydoc CFE_SUCCESS ** ******************************************************************************/ -int32 CFE_ES_UnlockCDSRegistry(void); +int32 CFE_ES_UnlockCDS(void); /*****************************************************************************/ /** @@ -254,7 +624,26 @@ int32 CFE_ES_ValidateCDS(void); /*****************************************************************************/ /** -** \brief Initializes the contents of the CDS +** \brief Clears the contents of the CDS +** +** \par Description +** Writes zeros to the entire CDS storage area +** +** This prevents any stale data that may exist in the +** memory area from being potentially interpreted as valid +** +** \par Assumptions, External Events, and Notes: +** None +** +** \return #CFE_SUCCESS \copydoc CFE_SUCCESS +** \return Any of the return values from #CFE_ES_CDS_CacheFlush +** +******************************************************************************/ +int32 CFE_ES_ClearCDS(void); + +/*****************************************************************************/ +/** +** \brief Initializes the signatures of the CDS area ** ** \par Description ** Stores a fixed pattern at the beginning and end of the CDS memory @@ -263,15 +652,11 @@ int32 CFE_ES_ValidateCDS(void); ** \par Assumptions, External Events, and Notes: ** None ** -** \param[in] CDSSize Total size of CDS memory area (in bytes) -** -** \return #OS_SUCCESS \copydoc OS_SUCCESS -** \return Any of the return values from #CFE_PSP_WriteToCDS -** \return Any of the return values from #CFE_ES_CreateCDSPool +** \return #CFE_SUCCESS \copydoc CFE_SUCCESS +** \return Any of the return values from #CFE_ES_CDS_CacheFlush ** ******************************************************************************/ -int32 CFE_ES_InitializeCDS(uint32 CDSSize); - +int32 CFE_ES_InitCDSSignatures(void); diff --git a/fsw/cfe-core/src/es/cfe_es_cds_mempool.c b/fsw/cfe-core/src/es/cfe_es_cds_mempool.c index aec972d0c..81b68cf5a 100644 --- a/fsw/cfe-core/src/es/cfe_es_cds_mempool.c +++ b/fsw/cfe-core/src/es/cfe_es_cds_mempool.c @@ -34,21 +34,17 @@ /* ** Includes */ +#include +#include +#include + #include "private/cfe_private.h" #include "cfe_es.h" #include "cfe_psp.h" +#include "cfe_es_generic_pool.h" #include "cfe_es_cds_mempool.h" #include "cfe_es_global.h" #include "cfe_es_log.h" -#include - -/*****************************************************************************/ -/* -** Local Macro Definitions -*/ -#define CFE_ES_CDS_CHECK_PATTERN 0x5a5a -#define CFE_ES_CDS_BLOCK_USED 0xaaaa -#define CFE_ES_CDS_BLOCK_UNUSED 0xdddd /*****************************************************************************/ /* @@ -60,10 +56,9 @@ ** File Global Data */ -CFE_ES_CDSPool_t CFE_ES_CDSMemPool; -CFE_ES_CDSBlockDesc_t CFE_ES_CDSBlockDesc; -uint32 CFE_ES_CDSMemPoolDefSize[CFE_ES_CDS_NUM_BLOCK_SIZES] = + +const CFE_ES_MemOffset_t CFE_ES_CDSMemPoolDefSize[CFE_ES_CDS_NUM_BLOCK_SIZES] = { CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE, CFE_PLATFORM_ES_CDS_MEM_BLOCK_SIZE_16, @@ -84,187 +79,84 @@ uint32 CFE_ES_CDSMemPoolDefSize[CFE_ES_CDS_NUM_BLOCK_SIZES] = CFE_PLATFORM_ES_CDS_MEM_BLOCK_SIZE_01 }; -/*****************************************************************************/ -/* -** Local Function Prototypes -*/ -int32 CFE_ES_CDSGetBinIndex(uint32 DesiredSize); - /*****************************************************************************/ /* ** Functions */ /* -** CFE_ES_CreateCDSPool will initialize a pre-allocated memory pool. +** CFE_ES_CDS_PoolRetrieve will obtain a block descriptor from CDS storage. ** -** NOTE: -** This function is only ever called during "Early Init" phase, -** where it is not possible to have contention writing into the syslog. -** Therefore the use of CFE_ES_SysLogWrite_Unsync() is acceptable +** This is a bridge between the generic pool implementation and the CDS cache. */ -int32 CFE_ES_CreateCDSPool(uint32 CDSPoolSize, uint32 StartOffset) +int32 CFE_ES_CDS_PoolRetrieve(CFE_ES_GenPoolRecord_t *GenPoolRecPtr, + CFE_ES_MemOffset_t Offset, + CFE_ES_GenPoolBD_t **BdPtr) { - char MutexName[10] = {"CDS_POOL"}; - uint32 i = 0; - uint32 Size = (CDSPoolSize & 0xfffffffc); - - /* create a semphore to protect this memory pool */ - OS_MutSemCreate(&(CFE_ES_CDSMemPool.MutexId), MutexName, 0); + CFE_ES_CDS_Instance_t *CDS = (CFE_ES_CDS_Instance_t *)GenPoolRecPtr; + CFE_ES_CDS_Offset_t CDSOffset; + CFE_ES_CDS_Offset_t CDSSize; - /* Take the semaphore to ensure the mem pool is not being used during it's creation */ - OS_MutSemTake(CFE_ES_CDSMemPool.MutexId); + /* Type conversions */ + CDSOffset = Offset; + CDSSize = sizeof(CFE_ES_GenPoolBD_t); + *BdPtr = &CDS->Cache.Data.Desc; - CFE_ES_CDSMemPool.Start = StartOffset; - CFE_ES_CDSMemPool.End = StartOffset + Size; - CFE_ES_CDSMemPool.Size = Size; - CFE_ES_CDSMemPool.Current = StartOffset; - CFE_ES_CDSMemPool.SizeIndex = -1; - - CFE_ES_CDSMemPool.CheckErrCntr = 0; - CFE_ES_CDSMemPool.RequestCntr = 0; + return CFE_ES_CDS_CacheFetch(&CDS->Cache, CDSOffset, CDSSize); +} - for (i=0; i=%u\n", - (unsigned int)CDSPoolSize, (unsigned int)(CFE_ES_CDSMemPool.MinBlockSize + sizeof(CFE_ES_CDSBlockDesc_t))); - - /* Give and delete semaphore since CDS Pool creation failed */ - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - OS_MutSemDelete(CFE_ES_CDSMemPool.MutexId); - return(CFE_ES_BAD_ARGUMENT); - } - - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); + CFE_ES_CDS_CachePreload(&CDS->Cache, BdPtr, Offset, + sizeof(CFE_ES_GenPoolBD_t)); - return(CFE_SUCCESS); + return CFE_ES_CDS_CacheFlush(&CDS->Cache); } /* -** Function: -** CFE_ES_RebuildCDSPool -** -** Purpose: +** CFE_ES_CreateCDSPool will initialize a pre-allocated memory pool. ** ** NOTE: ** This function is only ever called during "Early Init" phase, ** where it is not possible to have contention writing into the syslog. ** Therefore the use of CFE_ES_SysLogWrite_Unsync() is acceptable */ -int32 CFE_ES_RebuildCDSPool(uint32 CDSPoolSize, uint32 StartOffset) +int32 CFE_ES_CreateCDSPool(CFE_ES_CDS_Offset_t CDSPoolSize, CFE_ES_CDS_Offset_t StartOffset) { - char MutexName[10] = {"CDS_POOL"}; - uint32 i = 0; - uint32 Size = (CDSPoolSize & 0xfffffffc); - int32 Status = OS_SUCCESS; - uint32 Offset = StartOffset; - int32 BinIndex = 0; - - /* create a semphore to protect this memory pool */ - OS_MutSemCreate(&(CFE_ES_CDSMemPool.MutexId), MutexName, 0); - - /* Take the semaphore to ensure the mem pool is not being used during it's creation */ - OS_MutSemTake(CFE_ES_CDSMemPool.MutexId); - - CFE_ES_CDSMemPool.Start = StartOffset; - CFE_ES_CDSMemPool.End = StartOffset + Size; - CFE_ES_CDSMemPool.Size = Size; - CFE_ES_CDSMemPool.Current = 0; - CFE_ES_CDSMemPool.SizeIndex = -1; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; + int32 Status; + CFE_ES_MemOffset_t SizeCheck; + CFE_ES_MemOffset_t ActualSize; - CFE_ES_CDSMemPool.CheckErrCntr = 0; - CFE_ES_CDSMemPool.RequestCntr = 0; + SizeCheck = CFE_ES_GenPoolCalcMinSize(CFE_ES_CDS_NUM_BLOCK_SIZES, CFE_ES_CDSMemPoolDefSize, 1); + ActualSize = CDSPoolSize; - for (i=0; i=%u\n", - (unsigned int)CDSPoolSize, (unsigned int)(CFE_ES_CDSMemPool.MinBlockSize + sizeof(CFE_ES_CDSBlockDesc_t))); - - /* Give and delete semaphore since CDS Pool rebuild failed */ - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - OS_MutSemDelete(CFE_ES_CDSMemPool.MutexId); - return(CFE_ES_BAD_ARGUMENT); + CFE_ES_SysLogWrite_Unsync("CFE_ES:CreateCDSPool-Pool size(%lu) too small for one CDS Block, need >=%lu\n", + (unsigned long)ActualSize, (unsigned long)SizeCheck); + return CFE_ES_CDS_INVALID_SIZE; } - /* Scan the CDS memory trying to find blocks that were created but are now free */ - while ((Status == OS_SUCCESS) && - (Offset < (CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t))) && - (CFE_ES_CDSMemPool.Current == 0)) - { - /* Read the block descriptor for the first block in the memory pool */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_CDSBlockDesc, Offset, sizeof(CFE_ES_CDSBlockDesc_t)); - - if (Status == CFE_PSP_SUCCESS) - { - /* First, determine if the block is being or has been used */ - if (CFE_ES_CDSBlockDesc.CheckBits == CFE_ES_CDS_CHECK_PATTERN) - { - /* See if the block is currently being used */ - if (CFE_ES_CDSBlockDesc.AllocatedFlag != CFE_ES_CDS_BLOCK_USED) - { - /* If the block is not currently being used, */ - /* then add it to the appropriate linked list in the memory pool */ - BinIndex = CFE_ES_CDSGetBinIndex(CFE_ES_CDSBlockDesc.SizeUsed); - - /* Sanity-check the block descriptor */ - if (BinIndex >= 0) - { - CFE_ES_CDSBlockDesc.Next = CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_UNUSED; - CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top = Offset; - - /* Store the new CDS Block Descriptor in the CDS */ - Status = CFE_PSP_WriteToCDS(&CFE_ES_CDSBlockDesc, Offset, sizeof(CFE_ES_CDSBlockDesc_t)); - - if (Status != CFE_PSP_SUCCESS) - { - CFE_ES_SysLogWrite_Unsync("CFE_ES:RebuildCDS-Err writing to CDS (Stat=0x%08x)\n", (unsigned int)Status); - Status = CFE_ES_CDS_ACCESS_ERROR; - } - } - else - { - CFE_ES_CDSMemPool.CheckErrCntr++; - CFE_ES_SysLogWrite_Unsync("CFE_ES:RebuildCDS-Invalid Block Descriptor \n"); - Status = CFE_ES_CDS_ACCESS_ERROR; - } - } - - /* Skip to the next block of memory */ - Offset = Offset + CFE_ES_CDSBlockDesc.ActualSize + sizeof(CFE_ES_CDSBlockDesc_t); - } - else - { - /* If the block has never been used, then we should save the offset as the current offset */ - /* which in turn will finish the scan of the CDS memory */ - CFE_ES_CDSMemPool.Current = Offset; - } - } - else - { - CFE_ES_SysLogWrite_Unsync("CFE_ES:RebuildCDS-Err reading from CDS (Stat=0x%08x)\n", (unsigned int)Status); - Status = CFE_ES_CDS_ACCESS_ERROR; - } - } /* end while */ - - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); + Status = CFE_ES_GenPoolInitialize(&CDS->Pool, + StartOffset, /* starting offset */ + ActualSize, /* total size */ + 4, /* alignment */ + CFE_ES_CDS_NUM_BLOCK_SIZES, + CFE_ES_CDSMemPoolDefSize, + CFE_ES_CDS_PoolRetrieve, + CFE_ES_CDS_PoolCommit); return Status; } @@ -272,203 +164,41 @@ int32 CFE_ES_RebuildCDSPool(uint32 CDSPoolSize, uint32 StartOffset) /* ** Function: -** CFE_ES_GetCDSBlock +** CFE_ES_RebuildCDSPool ** ** Purpose: -** CFE_ES_GetCDSBlock allocates a block from the CDS memory pool. -*/ -int32 CFE_ES_GetCDSBlock(CFE_ES_CDSBlockHandle_t *BlockHandle, - uint32 BlockSize ) -{ - int32 BinIndex; - int32 Status; - - OS_MutSemTake(CFE_ES_CDSMemPool.MutexId); - - BinIndex = CFE_ES_CDSGetBinIndex(BlockSize); - if (BinIndex < 0) - { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:GetCDSBlock-err:size(%d) > max(%d).\n", (int)BlockSize, CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE); - return(CFE_ES_ERR_MEM_BLOCK_SIZE); - } - - /* - ** Check if any of the requested size are available - */ - if (CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top != 0) - { - /* - ** Get it off the top on the list - */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_CDSBlockDesc, - CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top, - sizeof(CFE_ES_CDSBlockDesc_t)); - - if (Status != CFE_PSP_SUCCESS) - { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:GetCDSBlock-Err reading from CDS (Stat=0x%08x)\n", (unsigned int)Status); - return(CFE_ES_CDS_ACCESS_ERROR); - } - - /* The handle returned is the byte offset of the block in the CDS */ - *BlockHandle = CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top; - - /* A local version of the block descriptor is initialized */ - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; - CFE_ES_CDSBlockDesc.SizeUsed = BlockSize; - CFE_ES_CDSBlockDesc.ActualSize = CFE_ES_CDSMemPool.SizeDesc[BinIndex].MaxSize; - CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top = CFE_ES_CDSBlockDesc.Next; - CFE_ES_CDSBlockDesc.CRC = 0; - CFE_ES_CDSBlockDesc.Next = 0; - } - else /* Create a new block */ - { - if ( (CFE_ES_CDSMemPool.Current == 0) || - (((uint32)CFE_ES_CDSMemPool.Current + - sizeof(CFE_ES_CDSBlockDesc_t) + - CFE_ES_CDSMemPool.SizeDesc[BinIndex].MaxSize ) >= CFE_ES_CDSMemPool.End) ) - { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:GetCDSBlock-err:Request for %d bytes won't fit in remaining memory\n", (int)BlockSize); - return(CFE_ES_ERR_MEM_BLOCK_SIZE); - } - - *BlockHandle = (CFE_ES_CDSBlockHandle_t)CFE_ES_CDSMemPool.Current; - - CFE_ES_CDSMemPool.SizeDesc[BinIndex].NumCreated++; - CFE_ES_CDSMemPool.RequestCntr++; - - /* - ** Initialize the buffer descriptor that will be kept in front of the CDS Block - */ - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; - CFE_ES_CDSBlockDesc.SizeUsed = BlockSize; - CFE_ES_CDSBlockDesc.ActualSize = CFE_ES_CDSMemPool.SizeDesc[BinIndex].MaxSize; - CFE_ES_CDSBlockDesc.CRC = 0; - CFE_ES_CDSBlockDesc.Next = 0; - - /* - ** Adjust pool current pointer to first unallocated byte in CDS - */ - CFE_ES_CDSMemPool.Current = CFE_ES_CDSMemPool.Current - + CFE_ES_CDSBlockDesc.ActualSize - + sizeof(CFE_ES_CDSBlockDesc_t); - } - - /* Store the new CDS Block Descriptor in the CDS */ - Status = CFE_PSP_WriteToCDS(&CFE_ES_CDSBlockDesc, *BlockHandle, sizeof(CFE_ES_CDSBlockDesc_t)); - - if (Status != CFE_PSP_SUCCESS) - { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:GetCDSBlock-Err writing to CDS (Stat=0x%08x)\n", (unsigned int)Status); - return(CFE_ES_CDS_ACCESS_ERROR); - } - - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - - return Status; -} - -/* -** CFE_ES_PutCDSBlock returns a block back to the CDS memory pool. +** +** NOTE: +** This function is only ever called during "Early Init" phase, +** where it is not possible to have contention writing into the syslog. +** Therefore the use of CFE_ES_SysLogWrite_Unsync() is acceptable */ -int32 CFE_ES_PutCDSBlock(CFE_ES_CDSBlockHandle_t BlockHandle) +int32 CFE_ES_RebuildCDSPool(CFE_ES_CDS_Offset_t CDSPoolSize, CFE_ES_CDS_Offset_t StartOffset) { - int32 BinIndex; + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; int32 Status; - /* Perform some sanity checks on the BlockHandle */ - /* First check, is the handle within an acceptable range of CDS offsets */ - if ((BlockHandle < sizeof(CFE_ES_Global.CDSVars.ValidityField)) || - (BlockHandle > (CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t) - - CFE_ES_CDSMemPool.MinBlockSize - sizeof(CFE_ES_Global.CDSVars.ValidityField)))) + /* + * Start by creating the pool in a clean state, as it would be in a non-rebuild. + */ + Status = CFE_ES_CreateCDSPool(CDSPoolSize, StartOffset); + if (Status != CFE_SUCCESS) { - CFE_ES_WriteToSysLog("CFE_ES:PutCDSBlock-Invalid Memory Handle.\n"); - return(CFE_ES_ERR_MEM_HANDLE); + return Status; } - OS_MutSemTake(CFE_ES_CDSMemPool.MutexId); - - /* Read a copy of the contents of the block descriptor being freed */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_CDSBlockDesc, BlockHandle, sizeof(CFE_ES_CDSBlockDesc_t)); + /* Now walk through the CDS memory and attempt to recover existing CDS blocks */ + Status = CFE_ES_GenPoolRebuild(&CDS->Pool); - if (Status != CFE_PSP_SUCCESS) + if (Status != CFE_SUCCESS) { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:PutCDSBlock-Err reading from CDS (Stat=0x%08x)\n", (unsigned int)Status); - return(CFE_ES_CDS_ACCESS_ERROR); + CFE_ES_SysLogWrite_Unsync("CFE_ES:RebuildCDS-Err rebuilding CDS (Stat=0x%08x)\n", (unsigned int)Status); + Status = CFE_ES_CDS_ACCESS_ERROR; } - - /* Make sure the contents of the Block Descriptor look reasonable */ - if ((CFE_ES_CDSBlockDesc.CheckBits != CFE_ES_CDS_CHECK_PATTERN) || - (CFE_ES_CDSBlockDesc.AllocatedFlag != CFE_ES_CDS_BLOCK_USED)) - { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:PutCDSBlock-Invalid Handle or Block Descriptor.\n"); - return(CFE_ES_ERR_MEM_HANDLE); - } - - BinIndex = CFE_ES_CDSGetBinIndex(CFE_ES_CDSBlockDesc.ActualSize); - - /* Final sanity check on block descriptor, is the Actual size reasonable */ - if (BinIndex < 0) - { - CFE_ES_CDSMemPool.CheckErrCntr++; - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:PutCDSBlock-Invalid Block Descriptor\n"); - return(CFE_ES_ERR_MEM_HANDLE); - } - - CFE_ES_CDSBlockDesc.Next = CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_UNUSED; - CFE_ES_CDSMemPool.SizeDesc[BinIndex].Top = BlockHandle; - - /* Store the new CDS Block Descriptor in the CDS */ - Status = CFE_PSP_WriteToCDS(&CFE_ES_CDSBlockDesc, BlockHandle, sizeof(CFE_ES_CDSBlockDesc_t)); - - if (Status != CFE_PSP_SUCCESS) - { - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); - CFE_ES_WriteToSysLog("CFE_ES:PutCDSBlock-Err writing to CDS (Stat=0x%08x)\n", (unsigned int)Status); - return(CFE_ES_CDS_ACCESS_ERROR); - } - - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); return Status; } -/* -** Function: -** CFE_ES_CDSGetBinIndex -** -** Purpose: -** -*/ -int32 CFE_ES_CDSGetBinIndex(uint32 DesiredSize) -{ - int32 i=0; - - if (DesiredSize > CFE_ES_CDSMemPool.SizeDesc[0].MaxSize) - { - return(-1); - } - - /* Look ahead to see if the next bin has a size too small */ - while ((i < (CFE_ES_CDS_NUM_BLOCK_SIZES-1)) && - (DesiredSize <= CFE_ES_CDSMemPool.SizeDesc[i+1].MaxSize)) - { - i++; - } - - return(i); -} - /* ** Function: @@ -477,89 +207,86 @@ int32 CFE_ES_CDSGetBinIndex(uint32 DesiredSize) ** Purpose: ** */ -int32 CFE_ES_CDSBlockWrite(CFE_ES_CDSBlockHandle_t BlockHandle, void *DataToWrite) +int32 CFE_ES_CDSBlockWrite(CFE_ES_CDSHandle_t Handle, const void *DataToWrite) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; char LogMessage[CFE_ES_MAX_SYSLOG_MSG_SIZE]; - int32 Status = CFE_SUCCESS; - int32 BinIndex = 0; - + int32 Status; + CFE_ES_MemOffset_t BlockSize; + CFE_ES_CDS_Offset_t UserDataSize; + CFE_ES_CDS_Offset_t UserDataOffset; + CFE_ES_CDS_RegRec_t *CDSRegRecPtr; + /* Ensure the the log message is an empty string in case it is never written to */ LogMessage[0] = 0; - /* Validate the handle before doing anything */ - if ((BlockHandle < sizeof(CFE_ES_Global.CDSVars.ValidityField)) || - (BlockHandle > (CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t) - - CFE_ES_CDSMemPool.MinBlockSize - sizeof(CFE_ES_Global.CDSVars.ValidityField)))) - { - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkWrite-Invalid Memory Handle.\n"); - Status = CFE_ES_ERR_MEM_HANDLE; - } - else - { - OS_MutSemTake(CFE_ES_CDSMemPool.MutexId); + CDSRegRecPtr = CFE_ES_LocateCDSBlockRecordByID(Handle); - /* Get a copy of the block descriptor associated with the specified handle */ - /* Read the block descriptor for the first block in the memory pool */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_CDSBlockDesc, BlockHandle, sizeof(CFE_ES_CDSBlockDesc_t)); + /* + * A CDS block ID must be accessed by only one thread at a time. + * Checking the validity of the block requires access to the registry. + */ + CFE_ES_LockCDS(); - if (Status != CFE_PSP_SUCCESS) + if (CFE_ES_CDSBlockRecordIsMatch(CDSRegRecPtr, Handle)) + { + /* + * Getting the buffer size via this function retrieves it from the + * internal descriptor, and validates the descriptor as part of the operation. + * This should always agree with the size in the registry for this block. + */ + Status = CFE_ES_GenPoolGetBlockSize(&CDS->Pool, &BlockSize, CDSRegRecPtr->BlockOffset); + if (Status != CFE_SUCCESS) { CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkWrite-Err reading from CDS (Stat=0x%08x)\n", (unsigned int)Status); + "CFE_ES:CDSBlkWrite-Invalid Handle or Block Descriptor.\n"); } - /* Validate the block to make sure it is still active and not corrupted */ - else if ((CFE_ES_CDSBlockDesc.CheckBits != CFE_ES_CDS_CHECK_PATTERN) || - (CFE_ES_CDSBlockDesc.AllocatedFlag != CFE_ES_CDS_BLOCK_USED)) + else if (BlockSize <= sizeof(CFE_ES_CDS_BlockHeader_t) || + BlockSize != CDSRegRecPtr->BlockSize) { CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkWrite-Invalid Handle or Block Descriptor.\n"); - Status = CFE_ES_ERR_MEM_HANDLE; + "CFE_ES:CDSBlkWrite-Block size %lu invalid, expected %lu\n", + (unsigned long)BlockSize, (unsigned long)CDSRegRecPtr->BlockSize); + Status = CFE_ES_CDS_INVALID_SIZE; } else { - BinIndex = CFE_ES_CDSGetBinIndex(CFE_ES_CDSBlockDesc.ActualSize); - - /* Final sanity check on block descriptor, is the Actual size reasonable */ - if (BinIndex < 0) + UserDataSize = CDSRegRecPtr->BlockSize; + UserDataSize -= sizeof(CFE_ES_CDS_BlockHeader_t); + UserDataOffset = CDSRegRecPtr->BlockOffset; + UserDataOffset += sizeof(CFE_ES_CDS_BlockHeader_t); + + CDS->Cache.Data.BlockHeader.Crc = CFE_ES_CalculateCRC( + DataToWrite, UserDataSize, 0, CFE_MISSION_ES_DEFAULT_CRC); + CDS->Cache.Offset = CDSRegRecPtr->BlockOffset; + CDS->Cache.Size = sizeof(CFE_ES_CDS_BlockHeader_t); + + /* Write the new block descriptor for the data coming from the Application */ + Status = CFE_ES_CDS_CacheFlush(&CDS->Cache); + if (Status != CFE_SUCCESS) { - CFE_ES_CDSMemPool.CheckErrCntr++; CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkWrite-Invalid Block Descriptor\n"); - Status = CFE_ES_ERR_MEM_HANDLE; + "CFE_ES:CDSBlkWrite-Err writing header data to CDS (Stat=0x%08x) @Offset=0x%08lx\n", + (unsigned int)CDS->Cache.AccessStatus, (unsigned long)CDSRegRecPtr->BlockOffset); } else { - - /* Use the size specified when the CDS was created to compute the CRC */ - CFE_ES_CDSBlockDesc.CRC = CFE_ES_CalculateCRC(DataToWrite, CFE_ES_CDSBlockDesc.SizeUsed, 0, CFE_MISSION_ES_DEFAULT_CRC); - - /* Write the new block descriptor for the data coming from the Application */ - Status = CFE_PSP_WriteToCDS(&CFE_ES_CDSBlockDesc, BlockHandle, sizeof(CFE_ES_CDSBlockDesc_t)); - - if (Status == CFE_PSP_SUCCESS) - { - /* Write the new data coming from the Application to the CDS */ - Status = CFE_PSP_WriteToCDS(DataToWrite, (BlockHandle + sizeof(CFE_ES_CDSBlockDesc_t)), CFE_ES_CDSBlockDesc.SizeUsed); - - if (Status != CFE_PSP_SUCCESS) - { - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkWrite-Err writing data to CDS (Stat=0x%08x) @Offset=0x%08x\n", - (unsigned int)Status, (unsigned int)(BlockHandle + sizeof(CFE_ES_CDSBlockDesc_t))); - } - } - else + Status = CFE_PSP_WriteToCDS(DataToWrite, UserDataOffset, UserDataSize); + if (Status != CFE_PSP_SUCCESS) { CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkWrite-Err writing BlockDesc to CDS (Stat=0x%08x) @Offset=0x%08x\n", - (unsigned int)Status, (unsigned int)BlockHandle); + "CFE_ES:CDSBlkWrite-Err writing user data to CDS (Stat=0x%08x) @Offset=0x%08lx\n", + (unsigned int)Status, (unsigned long)UserDataOffset); } } } - - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); } + else + { + Status = CFE_ES_RESOURCE_ID_INVALID; + } + + CFE_ES_UnlockCDS(); /* Do the actual syslog if something went wrong */ if (LogMessage[0] != 0) @@ -578,88 +305,84 @@ int32 CFE_ES_CDSBlockWrite(CFE_ES_CDSBlockHandle_t BlockHandle, void *DataToWrit ** Purpose: ** */ -int32 CFE_ES_CDSBlockRead(void *DataRead, CFE_ES_CDSBlockHandle_t BlockHandle) +int32 CFE_ES_CDSBlockRead(void *DataRead, CFE_ES_CDSHandle_t Handle) { + CFE_ES_CDS_Instance_t *CDS = &CFE_ES_Global.CDSVars; char LogMessage[CFE_ES_MAX_SYSLOG_MSG_SIZE]; - int32 Status = CFE_SUCCESS; + int32 Status; uint32 CrcOfCDSData; - int32 BinIndex; - + CFE_ES_MemOffset_t BlockSize; + CFE_ES_CDS_Offset_t UserDataSize; + CFE_ES_CDS_Offset_t UserDataOffset; + CFE_ES_CDS_RegRec_t *CDSRegRecPtr; + /* Validate the handle before doing anything */ LogMessage[0] = 0; - if ((BlockHandle < sizeof(CFE_ES_Global.CDSVars.ValidityField)) || - (BlockHandle > (CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t) - - CFE_ES_CDSMemPool.MinBlockSize - sizeof(CFE_ES_Global.CDSVars.ValidityField)))) - { - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkRd-Invalid Memory Handle.\n"); - Status = CFE_ES_ERR_MEM_HANDLE; - } - else - { - OS_MutSemTake(CFE_ES_CDSMemPool.MutexId); - /* Get a copy of the block descriptor associated with the specified handle */ - /* Read the block descriptor for the first block in the memory pool */ - Status = CFE_PSP_ReadFromCDS(&CFE_ES_CDSBlockDesc, BlockHandle, sizeof(CFE_ES_CDSBlockDesc_t)); - if (Status != CFE_PSP_SUCCESS) - { - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkRd-Err reading from CDS (Stat=0x%08x)\n", - (unsigned int)Status); - } - /* Validate the block to make sure it is still active and not corrupted */ - else if ((CFE_ES_CDSBlockDesc.CheckBits != CFE_ES_CDS_CHECK_PATTERN) || - (CFE_ES_CDSBlockDesc.AllocatedFlag != CFE_ES_CDS_BLOCK_USED)) - { - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkRd-Invalid Handle or Block Descriptor.\n"); - Status = CFE_ES_ERR_MEM_HANDLE; - } - else - { - BinIndex = CFE_ES_CDSGetBinIndex(CFE_ES_CDSBlockDesc.ActualSize); + CDSRegRecPtr = CFE_ES_LocateCDSBlockRecordByID(Handle); + + /* + * A CDS block ID must be accessed by only one thread at a time. + * Checking the validity of the block requires access to the registry. + */ + CFE_ES_LockCDS(); - /* Final sanity check on block descriptor, is the Actual size reasonable */ - if (BinIndex < 0) + if (CFE_ES_CDSBlockRecordIsMatch(CDSRegRecPtr, Handle)) + { + /* + * Getting the buffer size via this function retrieves it from the + * internal descriptor, and validates the descriptor as part of the operation. + * This should always agree with the size in the registry for this block. + */ + Status = CFE_ES_GenPoolGetBlockSize(&CDS->Pool, &BlockSize, CDSRegRecPtr->BlockOffset); + if (Status == CFE_SUCCESS) + { + if (BlockSize <= sizeof(CFE_ES_CDS_BlockHeader_t) || + BlockSize != CDSRegRecPtr->BlockSize) { - CFE_ES_CDSMemPool.CheckErrCntr++; - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkRd-Invalid Block Descriptor\n"); - Status = CFE_ES_ERR_MEM_HANDLE; + Status = CFE_ES_CDS_INVALID_SIZE; } else { - /* Read the old data block */ - Status = CFE_PSP_ReadFromCDS(DataRead, (BlockHandle + sizeof(CFE_ES_CDSBlockDesc_t)), CFE_ES_CDSBlockDesc.SizeUsed); + UserDataSize = CDSRegRecPtr->BlockSize; + UserDataSize -= sizeof(CFE_ES_CDS_BlockHeader_t); + UserDataOffset = CDSRegRecPtr->BlockOffset; + UserDataOffset += sizeof(CFE_ES_CDS_BlockHeader_t); - if (Status == CFE_PSP_SUCCESS) - { - /* Compute the CRC for the data read from the CDS and determine if the data is still valid */ - CrcOfCDSData = CFE_ES_CalculateCRC(DataRead, CFE_ES_CDSBlockDesc.SizeUsed, 0, CFE_MISSION_ES_DEFAULT_CRC); + /* Read the header */ + Status = CFE_ES_CDS_CacheFetch(&CDS->Cache, CDSRegRecPtr->BlockOffset, + (CFE_ES_CDS_Offset_t){sizeof(CFE_ES_CDS_BlockHeader_t)} ); - /* If the CRCs do not match, report an error */ - if (CrcOfCDSData != CFE_ES_CDSBlockDesc.CRC) - { - Status = CFE_ES_CDS_BLOCK_CRC_ERR; - } - else + if (Status == CFE_SUCCESS) + { + /* Read the data block */ + Status = CFE_PSP_ReadFromCDS(DataRead, UserDataOffset, UserDataSize); + if (Status == CFE_PSP_SUCCESS) { - Status = CFE_SUCCESS; + /* Compute the CRC for the data read from the CDS and determine if the data is still valid */ + CrcOfCDSData = CFE_ES_CalculateCRC(DataRead, UserDataSize, 0, CFE_MISSION_ES_DEFAULT_CRC); + + /* If the CRCs do not match, report an error */ + if (CrcOfCDSData != CDS->Cache.Data.BlockHeader.Crc) + { + Status = CFE_ES_CDS_BLOCK_CRC_ERR; + } + else + { + Status = CFE_SUCCESS; + } } } - else - { - CFE_ES_SysLog_snprintf(LogMessage, sizeof(LogMessage), - "CFE_ES:CDSBlkRd-Err reading block from CDS (Stat=0x%08x) @Offset=0x%08x\n", - (unsigned int)Status, (unsigned int)BlockHandle); - } } } - - OS_MutSemGive(CFE_ES_CDSMemPool.MutexId); } + else + { + Status = CFE_ES_RESOURCE_ID_INVALID; + } + + CFE_ES_UnlockCDS(); /* Do the actual syslog if something went wrong */ if (LogMessage[0] != 0) @@ -679,17 +402,8 @@ int32 CFE_ES_CDSBlockRead(void *DataRead, CFE_ES_CDSBlockHandle_t BlockHandle) */ uint32 CFE_ES_CDSReqdMinSize(uint32 MaxNumBlocksToSupport) { - uint32 i; - - for (i=0; i 0) - { - CFE_ES_CDSMemPool.MinBlockSize = CFE_ES_CDSMemPoolDefSize[i]; - } - } - - return (MaxNumBlocksToSupport * (sizeof(CFE_ES_CDSBlockDesc_t)+CFE_ES_CDSMemPool.MinBlockSize)); + return CFE_ES_GenPoolCalcMinSize(CFE_ES_CDS_NUM_BLOCK_SIZES, + CFE_ES_CDSMemPoolDefSize, + MaxNumBlocksToSupport); } diff --git a/fsw/cfe-core/src/es/cfe_es_cds_mempool.h b/fsw/cfe-core/src/es/cfe_es_cds_mempool.h index cb8f827a8..cbe0bcb11 100644 --- a/fsw/cfe-core/src/es/cfe_es_cds_mempool.h +++ b/fsw/cfe-core/src/es/cfe_es_cds_mempool.h @@ -42,59 +42,13 @@ ** Include Files */ #include "private/cfe_private.h" +#include "cfe_es_cds.h" /* ** Macro Definitions */ #define CFE_ES_CDS_NUM_BLOCK_SIZES 17 -/* -** Type Definitions -*/ - -typedef uint32 CFE_ES_CDSBlockHandle_t; - -typedef struct -{ - uint16 CheckBits; - uint16 AllocatedFlag; - uint32 SizeUsed; - uint32 ActualSize; - uint32 CRC; - uint32 Next; -} CFE_ES_CDSBlockDesc_t; - -typedef struct -{ - uint32 Top; - uint32 NumCreated; - uint32 MaxSize; -} CFE_ES_CDSBlockSizeDesc_t; -/* -** Memory Pool Type -*/ -typedef struct { - uint32 Start; - uint32 Size; - uint32 End; - uint32 Current; - int32 SizeIndex; - uint16 CheckErrCntr; - uint16 RequestCntr; - osal_id_t MutexId; - uint32 MinBlockSize; - CFE_ES_CDSBlockSizeDesc_t SizeDesc[CFE_ES_CDS_NUM_BLOCK_SIZES]; -} CFE_ES_CDSPool_t; - -/* - * External variables - * - * Note - these globals should not be modified outside of this module, - * however the unit test code does tweak them directly in order to test specific code paths - */ -extern CFE_ES_CDSPool_t CFE_ES_CDSMemPool; -extern CFE_ES_CDSBlockDesc_t CFE_ES_CDSBlockDesc; - /*****************************************************************************/ /* @@ -115,18 +69,14 @@ extern CFE_ES_CDSBlockDesc_t CFE_ES_CDSBlockDesc; ** \return #CFE_SUCCESS \copydoc CFE_SUCCESS ** ******************************************************************************/ -int32 CFE_ES_CreateCDSPool(uint32 CDSPoolSize, uint32 StartOffset); - - -int32 CFE_ES_RebuildCDSPool(uint32 CDSPoolSize, uint32 StartOffset); +int32 CFE_ES_CreateCDSPool(CFE_ES_CDS_Offset_t CDSPoolSize, CFE_ES_CDS_Offset_t StartOffset); -int32 CFE_ES_GetCDSBlock(CFE_ES_CDSBlockHandle_t *BlockHandle, uint32 BlockSize); -int32 CFE_ES_PutCDSBlock(CFE_ES_CDSBlockHandle_t BlockHandle); +int32 CFE_ES_RebuildCDSPool(CFE_ES_CDS_Offset_t CDSPoolSize, CFE_ES_CDS_Offset_t StartOffset); -int32 CFE_ES_CDSBlockWrite(CFE_ES_CDSBlockHandle_t BlockHandle, void *DataToWrite); +int32 CFE_ES_CDSBlockWrite(CFE_ES_CDSHandle_t Handle, const void *DataToWrite); -int32 CFE_ES_CDSBlockRead(void *DataRead, CFE_ES_CDSBlockHandle_t BlockHandle); +int32 CFE_ES_CDSBlockRead(void *DataRead, CFE_ES_CDSHandle_t Handle); uint32 CFE_ES_CDSReqdMinSize(uint32 MaxNumBlocksToSupport); diff --git a/fsw/cfe-core/src/es/cfe_es_global.h b/fsw/cfe-core/src/es/cfe_es_global.h index 0f73f64ce..6f8a451dc 100644 --- a/fsw/cfe-core/src/es/cfe_es_global.h +++ b/fsw/cfe-core/src/es/cfe_es_global.h @@ -46,6 +46,7 @@ #include "cfe_es_perf.h" #include "cfe_es_generic_pool.h" #include "cfe_es_mempool.h" +#include "cfe_es_cds_mempool.h" #include "cfe_time.h" #include "cfe_platform_cfg.h" #include "cfe_evs.h" @@ -75,6 +76,7 @@ #define CFE_ES_LIBID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+2) << CFE_ES_RESOURCEID_SHIFT)) #define CFE_ES_COUNTID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+3) << CFE_ES_RESOURCEID_SHIFT)) #define CFE_ES_POOLID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+4) << CFE_ES_RESOURCEID_SHIFT)) +#define CFE_ES_CDSBLOCKID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+5) << CFE_ES_RESOURCEID_SHIFT)) /* ** Typedefs @@ -156,7 +158,8 @@ typedef struct /* ** Critical Data Store Management Variables */ - CFE_ES_CDSVariables_t CDSVars; + CFE_ES_CDS_Instance_t CDSVars; + bool CDSIsAvailable; /**< \brief Whether or not the CDS service is active/valid */ /* * Background task for handling long-running, non real time tasks diff --git a/fsw/cfe-core/src/es/cfe_es_task.c b/fsw/cfe-core/src/es/cfe_es_task.c index d00bb55c6..3a1206274 100644 --- a/fsw/cfe-core/src/es/cfe_es_task.c +++ b/fsw/cfe-core/src/es/cfe_es_task.c @@ -1820,17 +1820,15 @@ int32 CFE_ES_DumpCDSRegistryCmd(const CFE_ES_DumpCDSRegistry_t *data) if (Status == sizeof(CFE_FS_Header_t)) { Status = sizeof(CFE_ES_CDSRegDumpRec_t); + RegRecPtr = CFE_ES_Global.CDSVars.Registry; while ((RegIndex < CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES) && (Status == sizeof(CFE_ES_CDSRegDumpRec_t))) { - /* Make a pointer to simplify code look and to remove redundant indexing into registry */ - RegRecPtr = &CFE_ES_Global.CDSVars.Registry[RegIndex]; - /* Check to see if the Registry entry is empty */ - if (RegRecPtr->Taken == true) + if ( CFE_ES_CDSBlockRecordIsUsed(RegRecPtr) ) { /* Fill CDS Registry Dump Record with relevant information */ - DumpRecord.Size = RegRecPtr->Size; - DumpRecord.Handle = RegRecPtr->MemHandle; + DumpRecord.Size = CFE_ES_CDSBlockRecordGetUserSize(RegRecPtr); + DumpRecord.Handle = CFE_ES_CDSBlockRecordGetID(RegRecPtr); DumpRecord.Table = RegRecPtr->Table; DumpRecord.ByteAlignSpare1 = 0; @@ -1848,7 +1846,8 @@ int32 CFE_ES_DumpCDSRegistryCmd(const CFE_ES_DumpCDSRegistry_t *data) } /* Look at the next entry in the Registry */ - RegIndex++; + ++RegIndex; + ++RegRecPtr; } if (Status == sizeof(CFE_ES_CDSRegDumpRec_t)) diff --git a/fsw/cfe-core/src/inc/cfe_error.h b/fsw/cfe-core/src/inc/cfe_error.h index 0a020ec17..e5ca4179b 100644 --- a/fsw/cfe-core/src/inc/cfe_error.h +++ b/fsw/cfe-core/src/inc/cfe_error.h @@ -412,7 +412,8 @@ typedef int32 CFE_Status_t; /** * @brief CDS Invalid Size * - * The Application is requesting a CDS Block with a size of zero. + * The Application is requesting a CDS Block or Pool with a size + * beyond the applicable limits, either too large or too small/zero. * */ #define CFE_ES_CDS_INVALID_SIZE ((int32)0xc4000010) diff --git a/fsw/cfe-core/src/inc/cfe_es.h b/fsw/cfe-core/src/inc/cfe_es.h index aaa383391..6c47987a6 100644 --- a/fsw/cfe-core/src/inc/cfe_es.h +++ b/fsw/cfe-core/src/inc/cfe_es.h @@ -89,7 +89,7 @@ ** NOTE: "+2" is for NULL Character and "." (i.e. - "AppName.CDSName") */ #define CFE_ES_CDS_MAX_FULL_NAME_LEN (CFE_MISSION_ES_CDS_MAX_NAME_LENGTH + CFE_MISSION_MAX_API_LEN + 2) -#define CFE_ES_CDS_BAD_HANDLE (CFE_ES_CDSHandle_t) 0xFFFF +#define CFE_ES_CDS_BAD_HANDLE CFE_ES_RESOURCEID_UNDEFINED /** \} */ #define CFE_ES_NO_MUTEX 0 /**< \brief Indicates that the memory pool selection will not use a semaphore */ @@ -409,7 +409,22 @@ typedef struct CFE_ES_MemPoolStats * * Data type used to hold Handles of Critical Data Stores. See #CFE_ES_RegisterCDS */ -typedef cpuaddr CFE_ES_CDSHandle_t; +typedef CFE_ES_ResourceID_t CFE_ES_CDSHandle_t; + +/** + * Type used for CDS sizes and offsets. + * + * This must match the type used in the PSP CDS API, e.g.: + * CFE_PSP_GetCDSSize() + * CFE_PSP_WriteToCDS() + * CFE_PSP_ReadFromCDS() + * + * It is defined separately from the CFE_ES_MemOffset_t as the type used in + * the PSP CDS access API may be different than the ES Pool API. + * + * In either case this _must_ be an unsigned type. + */ +typedef uint32 CFE_ES_CDS_Offset_t; /** * \brief CDS Register Dump Record @@ -1157,7 +1172,7 @@ void CFE_ES_ProcessAsyncEvent(void); ** \sa #CFE_ES_CopyToCDS, #CFE_ES_RestoreFromCDS ** ******************************************************************************/ -CFE_Status_t CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *HandlePtr, int32 BlockSize, const char *Name); +CFE_Status_t CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *HandlePtr, CFE_ES_CDS_Offset_t BlockSize, const char *Name); /*****************************************************************************/ /** diff --git a/fsw/cfe-core/src/inc/private/cfe_private.h b/fsw/cfe-core/src/inc/private/cfe_private.h index 5f6096737..cc16cd2ee 100644 --- a/fsw/cfe-core/src/inc/private/cfe_private.h +++ b/fsw/cfe-core/src/inc/private/cfe_private.h @@ -292,7 +292,7 @@ extern int32 CFE_TIME_CleanUpApp(CFE_ES_ResourceID_t AppId); ** ** \param[in, out] HandlePtr Pointer Application's variable that will contain the CDS Memory Block Handle. *HandlePtr is the handle of the CDS block that can be used in #CFE_ES_CopyToCDS and #CFE_ES_RestoreFromCDS. ** -** \param[in] BlockSize The number of bytes needed in the CDS. +** \param[in] UserBlockSize The number of bytes needed in the CDS. ** ** \param[in] Name Pointer to character string containing the Application's local name for ** the CDS. @@ -303,7 +303,7 @@ extern int32 CFE_TIME_CleanUpApp(CFE_ES_ResourceID_t AppId); ** \return See return codes for #CFE_ES_RegisterCDS ** ******************************************************************************/ -int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, int32 BlockSize, const char *Name, bool CriticalTbl); +int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, CFE_ES_CDS_Offset_t UserBlockSize, const char *Name, bool CriticalTbl); /*****************************************************************************/ /** diff --git a/fsw/cfe-core/src/tbl/cfe_tbl_internal.c b/fsw/cfe-core/src/tbl/cfe_tbl_internal.c index 7da4f69fb..d5334759d 100644 --- a/fsw/cfe-core/src/tbl/cfe_tbl_internal.c +++ b/fsw/cfe-core/src/tbl/cfe_tbl_internal.c @@ -1431,7 +1431,7 @@ void CFE_TBL_FindCriticalTblInfo(CFE_TBL_CritRegRec_t **CritRegRecPtr, CFE_ES_CD for (i=0; i CDS_RESERVED_MIN_SIZE) + { + OS_MutSemCreate(&CDS->GenMutex, "UT", 0); + CDS->TotalSize = CDS_Size; + CDS->DataSize = CDS->TotalSize; + CDS->DataSize -= CDS_RESERVED_MIN_SIZE; + + CFE_ES_InitCDSSignatures(); + CFE_ES_CreateCDSPool(CDS->DataSize, CDS_POOL_OFFSET); + CFE_ES_InitCDSRegistry(); + + CFE_ES_Global.CDSIsAvailable = true; + } } -void ES_UT_SetupSingleCDSRegistry(const char *CDSName, bool IsTable, + +void ES_UT_SetupSingleCDSRegistry(const char *CDSName, CFE_ES_MemOffset_t BlockSize, bool IsTable, CFE_ES_CDS_RegRec_t **OutRegRec) { CFE_ES_CDS_RegRec_t *LocalRegRecPtr; + CFE_ES_ResourceID_t UtCDSID; + CFE_ES_GenPoolBD_t LocalBD; + uint32 UT_CDS_BufferSize; - /* - * Note - because the "ES_ResetUnitTest()" routine wipes the entire - * global data structure, this runtime var needs to be re-initialized. - */ - CFE_ES_Global.CDSVars.MaxNumRegEntries = - sizeof(CFE_ES_Global.CDSVars.Registry) / sizeof(CFE_ES_CDS_RegRec_t); - LocalRegRecPtr = &CFE_ES_Global.CDSVars.Registry[0]; + /* first time this is done, set up the global */ + if (ES_UT_NumCDS == 0 && CFE_ES_Global.CDSVars.Pool.TailPosition == 0) + { + UT_GetDataBuffer(UT_KEY(CFE_PSP_GetCDSSize), NULL, &UT_CDS_BufferSize, NULL); + if (UT_CDS_BufferSize > (2*CFE_ES_CDS_SIGNATURE_LEN)) + { + /* Use the CDS buffer from ut_support.c if it was configured */ + CFE_ES_Global.CDSVars.Pool.PoolMaxOffset = UT_CDS_BufferSize - CFE_ES_CDS_SIGNATURE_LEN; + CFE_ES_Global.CDSVars.Pool.Retrieve = ES_UT_CDSPoolRetrieve; + CFE_ES_Global.CDSVars.Pool.Commit = ES_UT_CDSPoolCommit; + } + else + { + CFE_ES_Global.CDSVars.Pool.PoolMaxOffset = sizeof(UT_MemPoolIndirectBuffer.Data); + CFE_ES_Global.CDSVars.Pool.Retrieve = ES_UT_PoolIndirectRetrieve; + CFE_ES_Global.CDSVars.Pool.Commit = ES_UT_PoolIndirectCommit; + } + + CFE_ES_Global.CDSVars.Pool.Buckets[0].BlockSize = ES_UT_CDS_BLOCK_SIZE; + CFE_ES_Global.CDSVars.Pool.NumBuckets = 1; + CFE_ES_Global.CDSVars.Pool.TailPosition = CFE_ES_CDS_SIGNATURE_LEN; + CFE_ES_Global.CDSVars.Pool.PoolTotalSize = CFE_ES_Global.CDSVars.Pool.PoolMaxOffset - + CFE_ES_Global.CDSVars.Pool.TailPosition; + } + + UtCDSID = ES_UT_MakeCDSIdForIndex(ES_UT_NumCDS); + ++ES_UT_NumCDS; + + LocalRegRecPtr = CFE_ES_LocateCDSBlockRecordByID(UtCDSID); if (CDSName != NULL) { strncpy(LocalRegRecPtr->Name, CDSName, @@ -418,11 +487,22 @@ void ES_UT_SetupSingleCDSRegistry(const char *CDSName, bool IsTable, { LocalRegRecPtr->Name[0] = 0; } - LocalRegRecPtr->Taken = true; + LocalRegRecPtr->Table = IsTable; + LocalRegRecPtr->BlockOffset = CFE_ES_Global.CDSVars.Pool.TailPosition + sizeof(LocalBD); + LocalRegRecPtr->BlockSize = BlockSize; + + LocalBD.CheckBits = CFE_ES_CHECK_PATTERN; + LocalBD.Allocated = CFE_ES_MEMORY_ALLOCATED + 1; + LocalBD.ActualSize = BlockSize; + LocalBD.NextOffset = 0; + CFE_ES_Global.CDSVars.Pool.Commit(&CFE_ES_Global.CDSVars.Pool, + CFE_ES_Global.CDSVars.Pool.TailPosition, + &LocalBD); + + CFE_ES_Global.CDSVars.Pool.TailPosition = LocalRegRecPtr->BlockOffset + LocalRegRecPtr->BlockSize; - LocalRegRecPtr->MemHandle = - sizeof(CFE_ES_Global.CDSVars.ValidityField); + CFE_ES_CDSBlockRecordSetUsed(LocalRegRecPtr, UtCDSID); if (OutRegRec) { @@ -534,6 +614,7 @@ void ES_ResetUnitTest(void) memset(&CFE_ES_Global, 0, sizeof(CFE_ES_Global)); ES_UT_NumApps = 0; ES_UT_NumPools = 0; + ES_UT_NumCDS = 0; } /* end ES_ResetUnitTest() */ void TestInit(void) @@ -3302,7 +3383,8 @@ void TestTask(void) /* Test failed deletion of specified CDS */ ES_ResetUnitTest(); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", false, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, false, &UtCDSRegRecPtr); + UtCDSRegRecPtr->BlockOffset = 0xFFFFFFFF; /* Fails validation in PutBuf */ memset(&CmdBuf, 0, sizeof(CmdBuf)); strncpy(CmdBuf.DeleteCDSCmd.Payload.CdsName, "CFE_ES.CDS_NAME", @@ -3317,7 +3399,7 @@ void TestTask(void) /* Test failed deletion of specified critical table CDS */ /* NOTE - reuse command from previous test */ ES_ResetUnitTest(); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", true, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, true, NULL); UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_DeleteCDS_t), UT_TPID_CFE_ES_CMD_DELETE_CDS_CC); UT_Report(__FILE__, __LINE__, @@ -3328,13 +3410,9 @@ void TestTask(void) /* Test successful deletion of a specified CDS */ ES_ResetUnitTest(); UT_SetCDSSize(0); /* defeats the "ReadFromCDS" and causes it to use the value here */ - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", false, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, false, NULL); /* Set up the block to read what we need to from the CDS */ - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; - CFE_ES_CDSBlockDesc.ActualSize = 512; - CFE_ES_CDSBlockDesc.SizeUsed = 512; UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_DeleteCDS_t), UT_TPID_CFE_ES_CMD_DELETE_CDS_CC); UT_Report(__FILE__, __LINE__, @@ -3344,7 +3422,7 @@ void TestTask(void) /* Test deletion of a specified CDS with the owning app being active */ ES_ResetUnitTest(); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", false, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, false, NULL); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "CFE_ES", NULL, NULL); UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_DeleteCDS_t), UT_TPID_CFE_ES_CMD_DELETE_CDS_CC); @@ -3355,9 +3433,9 @@ void TestTask(void) /* Test deletion of a specified CDS with the name not found */ ES_ResetUnitTest(); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", false, &UtCDSRegRecPtr); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, false, &UtCDSRegRecPtr); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "CFE_BAD", NULL, NULL); - UtCDSRegRecPtr->Taken = false; + CFE_ES_CDSBlockRecordSetFree(UtCDSRegRecPtr); UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_DeleteCDS_t), UT_TPID_CFE_ES_CMD_DELETE_CDS_CC); UT_Report(__FILE__, __LINE__, @@ -3401,7 +3479,7 @@ void TestTask(void) ES_ResetUnitTest(); memset(&CmdBuf, 0, sizeof(CmdBuf)); UT_SetForceFail(UT_KEY(OS_write), OS_ERROR); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", false, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, false, NULL); UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_DumpCDSRegistry_t), UT_TPID_CFE_ES_CMD_DUMP_CDS_REGISTRY_CC); UT_Report(__FILE__, __LINE__, @@ -3439,22 +3517,6 @@ void TestTask(void) "CFE_ES_TaskPipe", "Invalid ground command"); - /* Test locking the CDS registry with a mutex take failure */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(OS_MutSemTake), 1, OS_ERROR); - UT_Report(__FILE__, __LINE__, - CFE_ES_LockCDSRegistry() == OS_ERROR, - "CFE_ES_LockCDSRegistry", - "Mutex take failed"); - - /* Test unlocking the CDS registry with a mutex give failure */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(OS_MutSemGive), 1, OS_ERROR); - UT_Report(__FILE__, __LINE__, - CFE_ES_UnlockCDSRegistry() == OS_ERROR, - "CFE_ES_UnlockCDSRegistry", - "Mutex give failed"); - /* Test sending a no-op command with an invalid command length */ ES_ResetUnitTest(); UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, 0, @@ -3717,7 +3779,7 @@ void TestTask(void) ES_ResetUnitTest(); memset(&CmdBuf, 0, sizeof(CmdBuf)); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "CFE_ES", NULL, NULL); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", false, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, false, NULL); strncpy(CmdBuf.DumpCDSRegCmd.Payload.DumpFilename, "DumpFile", sizeof(CmdBuf.DumpCDSRegCmd.Payload.DumpFilename)); UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_DumpCDSRegistry_t), @@ -5124,30 +5186,95 @@ void TestCDS() uint8 *CdsPtr; char CDSName[CFE_ES_CDS_MAX_FULL_NAME_LEN + 4]; CFE_ES_CDSHandle_t CDSHandle; + CFE_ES_CDS_RegRec_t *UtCDSRegRecPtr; uint32 i; uint32 TempSize; + uint8 BlockData[ES_UT_CDS_BLOCK_SIZE]; UtPrintf("Begin Test CDS"); + /* Test init with a mutex create failure */ + UT_SetDeferredRetcode(UT_KEY(OS_MutSemCreate), 1, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_EarlyInit() == CFE_STATUS_EXTERNAL_RESOURCE_FAIL, + "CFE_ES_CDS_EarlyInit", + "Mutex create failed"); + + /* Test locking the CDS registry with a mutex take failure */ + UT_SetDeferredRetcode(UT_KEY(OS_MutSemTake), 1, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_LockCDS() == CFE_STATUS_EXTERNAL_RESOURCE_FAIL, + "CFE_ES_LockCDS", + "Mutex take failed"); + + /* Test unlocking the CDS registry with a mutex give failure */ + UT_SetDeferredRetcode(UT_KEY(OS_MutSemGive), 1, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_UnlockCDS() == CFE_STATUS_EXTERNAL_RESOURCE_FAIL, + "CFE_ES_UnlockCDS", + "Mutex give failed"); + /* Set up the PSP stubs for CDS testing */ UT_SetCDSSize(128 * 1024); + /* Test the CDS Cache Fetch/Flush/Load routine error cases */ + ES_ResetUnitTest(); + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_CacheFetch(&CFE_ES_Global.CDSVars.Cache, + 4, + 0) == CFE_ES_CDS_INVALID_SIZE, + "CFE_ES_CDS_CacheFetch", + "Invalid Size"); + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_CacheFlush(&CFE_ES_Global.CDSVars.Cache) == CFE_ES_CDS_INVALID_SIZE, + "CFE_ES_CDS_CacheFlush", + "Invalid Size"); + + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_CachePreload(&CFE_ES_Global.CDSVars.Cache, NULL, + 4, + 0) == CFE_ES_CDS_INVALID_SIZE, + "CFE_ES_CDS_CachePreload", + "Invalid Size"); + TempSize = 5; + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_CachePreload(&CFE_ES_Global.CDSVars.Cache, &TempSize, + 4, + 4) == CFE_SUCCESS, + "CFE_ES_CDS_CachePreload", + "Nominal"); + + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_CacheFetch(&CFE_ES_Global.CDSVars.Cache, + 4, + 4) == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_CDS_CacheFetch", + "Access error"); + + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_CDS_CacheFlush(&CFE_ES_Global.CDSVars.Cache) == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_CDS_CacheFlush", + "Access Error"); + + /* Test CDS registering with a write CDS failure */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "UT", NULL, NULL); - UT_SetCDSSize(50000); - CFE_ES_InitializeCDS(50000); + ES_UT_SetupCDSGlobal(50000); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_RegisterCDS(&CDSHandle, 4, "Name3") == OS_ERROR, + CFE_ES_RegisterCDS(&CDSHandle, + 4, + "Name3") == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_RegisterCDS", "Writing to BSP CDS failure"); /* Test successful CDS registering */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "UT", NULL, NULL); - UT_SetCDSSize(50000); - CFE_ES_InitializeCDS(50000); + ES_UT_SetupCDSGlobal(50000); UT_Report(__FILE__, __LINE__, CFE_ES_RegisterCDS(&CDSHandle, 4, "Name") == CFE_SUCCESS, "CFE_ES_RegisterCDS", @@ -5156,9 +5283,7 @@ void TestCDS() /* Test CDS registering using an already registered name */ /* No reset here -- just attempt to register the same name again */ UT_Report(__FILE__, __LINE__, - CFE_ES_RegisterCDS(&CDSHandle, - 4, - "Name") == CFE_ES_CDS_ALREADY_EXISTS, + CFE_ES_RegisterCDS(&CDSHandle, 4, "Name") == CFE_ES_CDS_ALREADY_EXISTS, "CFE_ES_RegisterCDS", "Retrieve existing CDS"); @@ -5177,9 +5302,7 @@ void TestCDS() /* Test CDS registering with a block size of zero */ UT_Report(__FILE__, __LINE__, - CFE_ES_RegisterCDS(&CDSHandle, - 0, - "Name") == CFE_ES_CDS_INVALID_SIZE, + CFE_ES_RegisterCDS(&CDSHandle, 0, "Name") == CFE_ES_CDS_INVALID_SIZE, "CFE_ES_RegisterCDS", "Block size zero"); @@ -5187,28 +5310,25 @@ void TestCDS() ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "UT", NULL, NULL); UT_Report(__FILE__, __LINE__, - CFE_ES_RegisterCDS(&CDSHandle, - 4, - "Name") == CFE_ES_NOT_IMPLEMENTED, + CFE_ES_RegisterCDS(&CDSHandle, 4, "Name") == CFE_ES_NOT_IMPLEMENTED, "CFE_ES_RegisterCDS", "No memory pool available"); /* Test CDS registering with all the CDS registries taken */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "UT", NULL, NULL); - UT_SetCDSSize(50000); - CFE_ES_InitializeCDS(50000); + ES_UT_SetupCDSGlobal(50000); /* Set all the CDS registries to 'taken' */ - for (i = 0; i < CFE_ES_Global.CDSVars.MaxNumRegEntries; i++) + UtCDSRegRecPtr = CFE_ES_Global.CDSVars.Registry; + for (i = 0; i < CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES; i++) { - CFE_ES_Global.CDSVars.Registry[i].Taken = true; + CFE_ES_CDSBlockRecordSetUsed(UtCDSRegRecPtr, CFE_ES_RESOURCEID_RESERVED); + ++UtCDSRegRecPtr; } UT_Report(__FILE__, __LINE__, - CFE_ES_RegisterCDS(&CDSHandle, - 4, - "Name2") == CFE_ES_CDS_REGISTRY_FULL, + CFE_ES_RegisterCDS(&CDSHandle, 4, "Name2") == CFE_ES_CDS_REGISTRY_FULL, "CFE_ES_RegisterCDS", "No available entries"); @@ -5219,34 +5339,39 @@ void TestCDS() "CFE_ES_RegisterCDS", "Bad application ID"); - /* Register CDS to set up for the copy test */ - ES_ResetUnitTest(); - ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "UT", NULL, NULL); - UT_SetCDSSize(50000); - CFE_ES_InitializeCDS(50000); + /* Test copying to CDS with bad handle */ + CDSHandle = CFE_ES_RESOURCEID_UNDEFINED; UT_Report(__FILE__, __LINE__, - CFE_ES_RegisterCDS(&CDSHandle, 4, "Name") == CFE_SUCCESS, - "CFE_ES_RegisterCDS", - "Register CDS successful (set up for copy test)"); + CFE_ES_CopyToCDS(CDSHandle, &TempSize) == CFE_ES_RESOURCE_ID_INVALID, + "CFE_ES_CopyToCDS", + "Copy to CDS bad handle"); + /* Test restoring from a CDS with bad handle */ + UT_Report(__FILE__, __LINE__, + CFE_ES_RestoreFromCDS(&TempSize, CDSHandle) == CFE_ES_RESOURCE_ID_INVALID, + "CFE_ES_RestoreFromCDS", + "Restore from CDS bad handle"); - /* Test successfully copying to CDS */ + + /* Test successfully copying to a CDS */ + ES_ResetUnitTest(); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_SUCCESS); + ES_UT_SetupSingleCDSRegistry("UT", ES_UT_CDS_BLOCK_SIZE, false, &UtCDSRegRecPtr); + CDSHandle = CFE_ES_CDSBlockRecordGetID(UtCDSRegRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CopyToCDS(CDSHandle, &TempSize) == CFE_SUCCESS, + CFE_ES_CopyToCDS(CDSHandle, &BlockData) == CFE_SUCCESS, "CFE_ES_CopyToCDS", "Copy to CDS successful"); /* Test successfully restoring from a CDS */ UT_Report(__FILE__, __LINE__, - CFE_ES_RestoreFromCDS(&TempSize, CDSHandle) == CFE_SUCCESS, + CFE_ES_RestoreFromCDS(&BlockData, CDSHandle) == CFE_SUCCESS, "CFE_ES_RestoreFromCDS", "Restore from CDS successful"); /* Test CDS registering using a name longer than the maximum allowed */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "UT", NULL, NULL); - UT_SetCDSSize(50000); - CFE_ES_InitializeCDS(50000); + ES_UT_SetupCDSGlobal(50000); for (i = 0; i < CFE_MISSION_ES_CDS_MAX_NAME_LENGTH + 1; i++) { @@ -5264,7 +5389,14 @@ void TestCDS() /* Test unsuccessful CDS registering */ UT_Report(__FILE__, __LINE__, CFE_ES_RegisterCDS(&CDSHandle, - 0xffffffff, + CDS_ABS_MAX_BLOCK_SIZE+1, + "Name") == CFE_ES_CDS_INVALID_SIZE, + "CFE_ES_RegisterCDS", + "Register CDS unsuccessful"); + + UT_Report(__FILE__, __LINE__, + CFE_ES_RegisterCDS(&CDSHandle, + CDS_ABS_MAX_BLOCK_SIZE-1, "Name") == CFE_ES_ERR_MEM_BLOCK_SIZE, "CFE_ES_RegisterCDS", "Register CDS unsuccessful"); @@ -5288,7 +5420,7 @@ void TestCDS() /* Test CDS registry initialization with a CDS write failure */ UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, -1); UT_Report(__FILE__, __LINE__, - CFE_ES_InitCDSRegistry() == -1, + CFE_ES_InitCDSRegistry() == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_InitCDSRegistry", "Failed to write registry size"); @@ -5303,7 +5435,7 @@ void TestCDS() ES_ResetUnitTest(); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, -1); UT_Report(__FILE__, __LINE__, - CFE_ES_CDS_EarlyInit() == -1, + CFE_ES_CDS_EarlyInit() == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_CDS_EarlyInit", "Unrecoverable read error"); @@ -5311,7 +5443,7 @@ void TestCDS() ES_ResetUnitTest(); UT_SetCDSSize(1024); UT_Report(__FILE__, __LINE__, - CFE_ES_CDS_EarlyInit() == OS_SUCCESS && + CFE_ES_CDS_EarlyInit() == CFE_SUCCESS && UT_GetStubCount(UT_KEY(CFE_PSP_GetCDSSize)) == 1, "CFE_ES_CDS_EarlyInit", "CDS size less than minimum"); @@ -5325,89 +5457,111 @@ void TestCDS() "Unable to obtain CDS size"); /* Reset back to a sufficient CDS size */ - UT_SetCDSSize(128 * 1024); + UT_SetCDSSize(128*1024); + UT_GetDataBuffer(UT_KEY(CFE_PSP_ReadFromCDS), (void**)&CdsPtr, &CdsSize, NULL); /* Test CDS initialization with rebuilding not possible */ ES_ResetUnitTest(); - UT_GetDataBuffer(UT_KEY(CFE_PSP_ReadFromCDS), (void**)&CdsPtr, &CdsSize, NULL); - memcpy(CdsPtr, "_CDSBeg_", 8); - memcpy(CdsPtr + CdsSize - 8, "_CDSEnd_", 8); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 3, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_CDS_EarlyInit() == OS_SUCCESS, + CFE_ES_CDS_EarlyInit() == CFE_SUCCESS, "CFE_ES_CDS_EarlyInit", "Rebuilding not possible; create new CDS"); + /* Test CDS validation with first CDS read call failure */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_ValidateCDS() == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_ValidateCDS", + "CDS read (first call) failed"); + /* Test CDS validation with second CDS read call failure */ - ES_ResetUnitTest(); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_ValidateCDS() == OS_ERROR, + CFE_ES_ValidateCDS() == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_ValidateCDS", "CDS read (second call) failed"); /* Test CDS validation with CDS read end check failure */ - ES_ResetUnitTest(); - UT_GetDataBuffer(UT_KEY(CFE_PSP_ReadFromCDS), (void**)&CdsPtr, &CdsSize, NULL); - CFE_ES_Global.CDSVars.CDSSize = CdsSize; - memcpy(CdsPtr + CdsSize - 8, "gibberish", 8); + memset(CdsPtr + CdsSize - CFE_ES_CDS_SIGNATURE_LEN, 'x', CFE_ES_CDS_SIGNATURE_LEN); UT_Report(__FILE__, __LINE__, CFE_ES_ValidateCDS() == CFE_ES_CDS_INVALID, "CFE_ES_ValidateCDS", "Reading from CDS failed end check"); - /* Test CDS validation with first CDS read call failure */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, -1); + /* Test CDS validation with CDS read begin check failure */ + UT_GetDataBuffer(UT_KEY(CFE_PSP_ReadFromCDS), (void**)&CdsPtr, &CdsSize, NULL); + memset(CdsPtr, 'x', CFE_ES_CDS_SIGNATURE_LEN); UT_Report(__FILE__, __LINE__, - CFE_ES_ValidateCDS() == -1, + CFE_ES_ValidateCDS() == CFE_ES_CDS_INVALID, "CFE_ES_ValidateCDS", - "CDS read (first call) failed"); + "Reading from CDS failed begin check"); /* Test CDS initialization where first write call to the CDS fails */ - ES_ResetUnitTest(); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_InitializeCDS(128 * 1024) == OS_ERROR, - "CFE_ES_InitializeCDS", - "Clear CDS failed"); + CFE_ES_InitCDSSignatures() == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_InitCDSSignatures", + "CDS write (first call) failed"); /* Test CDS initialization where second write call to the CDS fails */ - /* Note - the PSP is zeroed by writing 4x uint32 values. The 2nd - * call in the source code will be the 5th call to the PSP function. */ - ES_ResetUnitTest(); - UT_SetCDSSize(16); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 5, OS_ERROR); + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_InitializeCDS(16) == OS_ERROR, - "CFE_ES_InitializeCDS", + CFE_ES_InitCDSSignatures() == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_InitCDSSignatures", "CDS write (second call) failed"); - /* Test CDS initialization where third write call to the CDS fails */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 6, OS_ERROR); + /* Test CDS clear where write call to the CDS fails */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_InitializeCDS(16) == OS_ERROR, - "CFE_ES_InitializeCDS", - "CDS write (third call) failed"); + CFE_ES_ClearCDS() == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_ClearCDS", + "CDS write failed"); - /* Test rebuilding the CDS where the registry is too large */ + /* Test rebuilding the CDS where the registry is not the same size */ ES_ResetUnitTest(); - UT_SetCDSSize(0); - CFE_ES_Global.CDSVars.MaxNumRegEntries = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES + 1; + UT_GetDataBuffer(UT_KEY(CFE_PSP_ReadFromCDS), (void**)&CdsPtr, &CdsSize, NULL); + TempSize = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES + 1; + memcpy(CdsPtr + CDS_REG_SIZE_OFFSET, &TempSize, sizeof(TempSize)); UT_Report(__FILE__, __LINE__, CFE_ES_RebuildCDS() == CFE_ES_CDS_INVALID, "CFE_ES_RebuildCDS", "Registry too large to recover"); + /* Test clearing CDS where size is an odd number (requires partial write) */ + ES_ResetUnitTest(); + CFE_ES_Global.CDSVars.TotalSize = 53; + UT_Report(__FILE__, __LINE__, + CFE_ES_ClearCDS() == CFE_SUCCESS, + "CFE_ES_ClearCDS", + "CDS write failed"); + + /* + * To prepare for the rebuild tests, set up a clean area in PSP mem, + * and make a registry entry. + */ + ES_UT_SetupCDSGlobal(50000); + ES_UT_SetupSingleCDSRegistry("UT", 8, false, &UtCDSRegRecPtr); + UtAssert_NONZERO(UtCDSRegRecPtr->BlockOffset); + UtAssert_NONZERO(UtCDSRegRecPtr->BlockSize); + UtAssert_INT32_EQ(CFE_ES_UpdateCDSRegistry(), CFE_SUCCESS); + /* Test successfully rebuilding the CDS */ ES_ResetUnitTest(); - CFE_ES_Global.CDSVars.MaxNumRegEntries = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES - 4; + + /* The reset would have cleared the registry data */ + UtAssert_ZERO(UtCDSRegRecPtr->BlockOffset); + UtAssert_ZERO(UtCDSRegRecPtr->BlockSize); + UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDS() == CFE_SUCCESS, + CFE_ES_CDS_EarlyInit() == CFE_SUCCESS, "CFE_ES_RebuildCDS", "CDS rebuild successful"); + /* Check that the registry entry exists again (was recovered) */ + UtAssert_NONZERO(UtCDSRegRecPtr->BlockOffset); + UtAssert_NONZERO(UtCDSRegRecPtr->BlockSize); + /* Test rebuilding the CDS with the registry unreadable */ ES_ResetUnitTest(); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 2, OS_ERROR); @@ -5418,21 +5572,23 @@ void TestCDS() /* Test deleting the CDS from the registry with a registry write failure */ ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; - CFE_ES_CDSBlockDesc.ActualSize = 512; - ES_UT_SetupSingleCDSRegistry("NO_APP.CDS_NAME", true, NULL); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); + ES_UT_SetupSingleCDSRegistry("NO_APP.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, true, NULL); + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, CFE_ES_DeleteCDS("NO_APP.CDS_NAME", true) == -1, "CFE_ES_DeleteCDS", + "CDS block descriptor write failed"); + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); + UT_Report(__FILE__, __LINE__, + CFE_ES_DeleteCDS("NO_APP.CDS_NAME", true) == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_DeleteCDS", "CDS registry write failed"); /* Test deleting the CDS from the registry with the owner application * still active */ ES_ResetUnitTest(); - ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", true, NULL); + ES_UT_SetupSingleCDSRegistry("CFE_ES.CDS_NAME", ES_UT_CDS_BLOCK_SIZE, true, NULL); ES_UT_SetupSingleAppId(CFE_ES_AppType_CORE, CFE_ES_AppState_RUNNING, "CFE_ES", NULL, NULL); UT_Report(__FILE__, __LINE__, CFE_ES_DeleteCDS("CFE_ES.CDS_NAME", true) == @@ -5440,13 +5596,13 @@ void TestCDS() "CFE_ES_DeleteCDS", "Owner application still active"); + /* + * To prepare for the rebuild tests, set up a clean area in PSP mem + */ + ES_UT_SetupCDSGlobal(128 * 1024); + /* Test CDS initialization where rebuilding the CDS is successful */ ES_ResetUnitTest(); - CdsSize = 128 * 1024; - CdsPtr = UT_SetCDSSize(128 * 1024); - memcpy(CdsPtr, "_CDSBeg_", 8); - memcpy(CdsPtr + CdsSize - 8, "_CDSEnd_", 8); - CFE_ES_Global.CDSVars.MaxNumRegEntries = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES - 4; UT_Report(__FILE__, __LINE__, CFE_ES_CDS_EarlyInit() == CFE_SUCCESS, "CFE_ES_CDS_EarlyInit", @@ -5455,457 +5611,206 @@ void TestCDS() /* Test CDS initialization where rebuilding the CDS is unsuccessful */ ES_ResetUnitTest(); UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 3, OS_ERROR); - CFE_ES_Global.CDSVars.MaxNumRegEntries = CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES - 4; UT_Report(__FILE__, __LINE__, CFE_ES_CDS_EarlyInit() == CFE_SUCCESS, "CFE_ES_CDS_EarlyInit", "Initialization with unsuccessful rebuild"); - /* Test CDS initialization where write call to the CDS fails while filling - * in extra uint32 space - */ + /* Test CDS initialization where initializing the CDS registry fails */ ES_ResetUnitTest(); - UT_SetCDSSize(0); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 5, OS_ERROR); + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_InitializeCDS(32 * 4 - 4) == OS_ERROR, - "CFE_ES_InitializeCDS", - "CDS write failed while filling extra space"); + CFE_ES_InitCDSRegistry() == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_InitCDSRegistry", + "CDS registry write size failed"); - /* Test CDS initialization where creating the CDS pool fails */ - ES_ResetUnitTest(); + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_InitializeCDS(sizeof(CFE_ES_Global.CDSVars.ValidityField)) == - CFE_ES_BAD_ARGUMENT, - "CFE_ES_InitializeCDS", - "CDS pool create failed"); + CFE_ES_InitCDSRegistry() == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_InitCDSRegistry", + "CDS registry write content failed"); /* Test deleting the CDS from the registry with a CDS name longer than the * maximum allowed */ ES_ResetUnitTest(); - memset(CDSName, 'a', CFE_ES_CDS_MAX_FULL_NAME_LEN - 1); - CDSName[CFE_ES_CDS_MAX_FULL_NAME_LEN - 1] = '\0'; - ES_UT_SetupSingleCDSRegistry(CDSName, true, NULL); + memset(CDSName, 'a', sizeof(CDSName) - 1); + CDSName[sizeof(CDSName) - 1] = '\0'; + ES_UT_SetupSingleCDSRegistry(CDSName, ES_UT_CDS_BLOCK_SIZE, true, NULL); UT_Report(__FILE__, __LINE__, CFE_ES_DeleteCDS(CDSName, - true) == CFE_ES_ERR_MEM_HANDLE, + true) == CFE_ES_CDS_NOT_FOUND_ERR, "CFE_ES_DeleteCDS", "CDS name too long"); } /* End TestCDS */ void TestCDSMempool(void) { - uint32 MinCDSSize = CFE_ES_CDS_MIN_BLOCK_SIZE + - sizeof(CFE_ES_CDSBlockDesc_t); - CFE_ES_CDSBlockHandle_t BlockHandle; - int Data; - uint32 i; - - extern uint32 CFE_ES_CDSMemPoolDefSize[]; + CFE_ES_CDS_RegRec_t *UtCdsRegRecPtr; + int Data; + CFE_ES_ResourceID_t BlockHandle; + CFE_ES_CDS_Offset_t SavedSize; + CFE_ES_CDS_Offset_t SavedOffset; + uint8 *CdsPtr; UtPrintf("Begin Test CDS memory pool"); - UT_SetCDSSize(0); - - /* Set up the CDS block to read in the following tests */ - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; - CFE_ES_CDSBlockDesc.ActualSize = 512; - CFE_ES_CDSBlockDesc.SizeUsed = 512; + ES_UT_SetupCDSGlobal(0); /* Test creating the CDS pool with the pool size too small */ ES_ResetUnitTest(); UT_Report(__FILE__, __LINE__, - CFE_ES_CreateCDSPool(0, 0) == CFE_ES_BAD_ARGUMENT, + CFE_ES_CreateCDSPool(2, 1) == CFE_ES_CDS_INVALID_SIZE, "CFE_ES_CreateCDSPool", "CDS pool size too small"); /* Test rebuilding the CDS pool with the pool size too small */ - ES_ResetUnitTest(); UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(0, 0) == CFE_ES_BAD_ARGUMENT, + CFE_ES_RebuildCDSPool(2, 1) == CFE_ES_CDS_INVALID_SIZE, "CFE_ES_RebuildCDSPool", "CDS pool size too small"); - /* Test rebuilding the CDS pool with the CDS block unused */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 2, OS_ERROR); - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_UNUSED; - UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(MinCDSSize, 0) == CFE_SUCCESS, - "CFE_ES_RebuildCDSPool", - "CDS block unused"); - - /* Test rebuilding the CDS pool with a CDS read failure */ - ES_ResetUnitTest(); - UT_SetForceFail(UT_KEY(CFE_PSP_ReadFromCDS), -1); - UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(MinCDSSize, 0) == CFE_ES_CDS_ACCESS_ERROR, - "CFE_ES_RebuildCDSPool", - "Error reading CDS"); - - /* Test rebuilding the CDS pool with a CDS write failure */ + /* Test rebuilding CDS pool with CDS access errors */ + /* + * To setup - Create a CDS registry and delete it, which creates + * a freed block in the pool. Then attempt to rebuild. + */ ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 2, OS_ERROR); - UT_SetForceFail(UT_KEY(CFE_PSP_WriteToCDS), OS_ERROR); - UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(MinCDSSize, 0) == CFE_ES_CDS_ACCESS_ERROR, - "CFE_ES_RebuildCDSPool", - "Error writing CDS"); + ES_UT_SetupCDSGlobal(50000); + SavedSize = CFE_ES_Global.CDSVars.TotalSize; + SavedOffset = CFE_ES_Global.CDSVars.Pool.TailPosition; + ES_UT_SetupSingleCDSRegistry("UT", sizeof(Data) + sizeof(CFE_ES_CDS_BlockHeader_t), + false, &UtCdsRegRecPtr); + UtAssert_NONZERO(UtCdsRegRecPtr->BlockOffset); + UtAssert_NONZERO(UtCdsRegRecPtr->BlockSize); + CFE_ES_DeleteCDS("UT",false); + UtAssert_INT32_EQ(CFE_ES_UpdateCDSRegistry(), CFE_SUCCESS); - /* Test rebuilding the CDS pool with a block not previously used */ + /* Clear/reset the global state */ ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.CheckBits = 1; - /* Set flags so as to fail on second CDS read */ - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_SUCCESS); - UT_SetForceFail(UT_KEY(CFE_PSP_ReadFromCDS), -1); + /* Test rebuilding the CDS pool with a descriptor retrieve error */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(MinCDSSize, 1) == OS_SUCCESS, + CFE_ES_RebuildCDSPool(SavedSize, SavedOffset) == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_RebuildCDSPool", - "CDS block not used before"); - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; + "CDS descriptor retrieve error"); - /* Test rebuilding the CDS pool with an invalid block descriptor */ - ES_ResetUnitTest(); - CFE_ES_CDSMemPoolDefSize[0] = 0; + /* Test rebuilding the CDS pool with a descriptor commit error */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(MinCDSSize, 0) == CFE_ES_CDS_ACCESS_ERROR, + CFE_ES_RebuildCDSPool(SavedSize, SavedOffset) == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_RebuildCDSPool", - "Invalid block descriptor"); - CFE_ES_CDSMemPoolDefSize[0] = CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE; - - /* Test successfully creating a pool where the offset = 0 */ - ES_ResetUnitTest(); - UT_Report(__FILE__, __LINE__, - CFE_ES_CreateCDSPool(1000000, 0) == CFE_SUCCESS, - "CFE_ES_CreateCDSPool", - "Create with zero offset; successful"); - - /* Test allocating a CDS block with a block size error */ - ES_ResetUnitTest(); - UT_Report(__FILE__, __LINE__, - CFE_ES_GetCDSBlock(&BlockHandle, - 800) == CFE_ES_ERR_MEM_BLOCK_SIZE, - "CFE_ES_GetCDSBlock", - "Block size error"); - - /* Test returning a CDS block to the memory pool using an invalid - block descriptor */ - ES_ResetUnitTest(); - BlockHandle = 0; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_PutCDSBlock", - "Invalid block descriptor"); - - /* Test creating a new pool and set up for getting a pre-made block */ - ES_ResetUnitTest(); - BlockHandle = 0; - UT_Report(__FILE__, __LINE__, - CFE_ES_CreateCDSPool(1000000, 8) == CFE_SUCCESS, - "CFE_ES_CreateCDSPool", - "Create with non-zero offset; successful"); - - /* Test successfully allocating a pre-made CDS block */ - ES_ResetUnitTest(); - UT_Report(__FILE__, __LINE__, - CFE_ES_GetCDSBlock(&BlockHandle, 800) == OS_SUCCESS, - "CFE_ES_GetCDSBlock", - "Get a CDS block; successful"); - - /* Test successfully returning a CDS block back to the memory pool */ - ES_ResetUnitTest(); - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == OS_SUCCESS, - "CFE_ES_PutCDSBlock", - "Return a CDS block; successful"); - - /* Test allocating a CDS block with a CDS read failure */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, -1); - UT_Report(__FILE__, __LINE__, - CFE_ES_GetCDSBlock(&BlockHandle, 800) == CFE_ES_CDS_ACCESS_ERROR, - "CFE_ES_GetCDSBlock", - "Error reading CDS"); - - /* Test allocating a CDS block with a CDS write failure */ - ES_ResetUnitTest(); - UT_SetForceFail(UT_KEY(CFE_PSP_WriteToCDS), OS_ERROR); - UT_Report(__FILE__, __LINE__, - CFE_ES_GetCDSBlock(&BlockHandle, 800) == CFE_ES_CDS_ACCESS_ERROR, - "CFE_ES_GetCDSBlock", - "Error writing CDS"); - - /* Test allocating a CDS block using a block size that's too large */ - ES_ResetUnitTest(); - UT_Report(__FILE__, __LINE__, - CFE_ES_GetCDSBlock(&BlockHandle, - CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE + 1) == - CFE_ES_ERR_MEM_BLOCK_SIZE, - "CFE_ES_GetCDSBlock", - "Block size too large"); - - /* Test returning a CDS block to the memory pool with an - * invalid CDS handle - */ - ES_ResetUnitTest(); - BlockHandle = sizeof(CFE_ES_Global.CDSVars.ValidityField) - 1; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_PutCDSBlock", - "Invalid CDS handle"); - - /* Test returning a CDS block to the memory pool with a CDS read error */ - ES_ResetUnitTest(); - UT_SetForceFail(UT_KEY(CFE_PSP_ReadFromCDS), -1); - BlockHandle = 10; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_CDS_ACCESS_ERROR, - "CFE_ES_PutCDSBlock", - "Error reading CDS"); - - /* Test returning a CDS block to the memory pool with an invalid - * block descriptor - */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_UNUSED; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_PutCDSBlock", - "Invalid block descriptor"); - - /* Test returning a CDS block to the memory pool with the block size - * too large - */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.ActualSize = CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE + 1; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_PutCDSBlock", - "Invalid memory handle"); - - /* Test returning a CDS block to the memory pool with a CDS write error */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.ActualSize = 452; - UT_SetForceFail(UT_KEY(CFE_PSP_WriteToCDS), OS_ERROR); - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_CDS_ACCESS_ERROR, - "CFE_ES_PutCDSBlock", - "Error writing CDS"); + "CDS descriptor commit error"); /* Test CDS block write using an invalid memory handle */ ES_ResetUnitTest(); - BlockHandle = 7; + BlockHandle = CFE_ES_ResourceID_FromInteger(7); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, - &Data) == CFE_ES_ERR_MEM_HANDLE, + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == CFE_ES_RESOURCE_ID_INVALID, "CFE_ES_CDSBlockWrite", "Invalid memory handle"); - BlockHandle = 10; - - /* Test CDS block write with the block size too large */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.ActualSize = CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE + 1; - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, - &Data) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_CDSBlockWrite", - "Actual size too large"); - CFE_ES_CDSBlockDesc.ActualSize = 452; + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_RESOURCE_ID_INVALID, + "CFE_ES_CDSBlockRead", + "Invalid memory handle"); - /* Test CDS block write using an invalid (unused) block */ + /* Test CDS block access */ ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_UNUSED; - UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, - &Data) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_CDSBlockWrite", - "Invalid CDS block"); - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; + ES_UT_SetupCDSGlobal(50000); + ES_UT_SetupSingleCDSRegistry("UT", sizeof(Data) + sizeof(CFE_ES_CDS_BlockHeader_t), + false, &UtCdsRegRecPtr); + BlockHandle = CFE_ES_CDSBlockRecordGetID(UtCdsRegRecPtr); + Data = 42; - /* Test CDS block write with a CDS write error (block descriptor) */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); + /* Basic success path */ UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, &Data) == OS_ERROR, + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == CFE_SUCCESS, "CFE_ES_CDSBlockWrite", - "Error writing block descriptor to CDS"); - - /* Test CDS block write with a CDS write error (new data) */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); + "Nominal"); + Data = 0; UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, &Data) == OS_ERROR, - "CFE_ES_CDSBlockWrite", - "Error writing new data to CDS"); + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_SUCCESS, + "CFE_ES_CDSBlockRead", + "Nominal"); - /* Test CDS block write with a CDS read error */ - ES_ResetUnitTest(); - UT_SetForceFail(UT_KEY(CFE_PSP_ReadFromCDS), -1); - UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, &Data) == OS_ERROR, - "CFE_ES_CDSBlockWrite", - "Error reading CDS"); + UtAssert_INT32_EQ(Data, 42); - /* Test CDS block read with an invalid memory handle */ - ES_ResetUnitTest(); - BlockHandle = 7; - UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_CDSBlockRead", - "Invalid memory handle"); - BlockHandle = 10; - /* Test CDS block read with the block size too large */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.ActualSize = CFE_PLATFORM_ES_CDS_MAX_BLOCK_SIZE + 1; - CFE_ES_CDSBlockDesc.CheckBits = CFE_ES_CDS_CHECK_PATTERN; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; + /* Corrupt/change the block offset, should fail validation */ + --UtCdsRegRecPtr->BlockOffset; UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_CDSBlockRead", - "Actual size too large"); - CFE_ES_CDSBlockDesc.ActualSize = 452; - - /* Test CDS block read using an invalid (unused) block */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_UNUSED; + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == CFE_ES_POOL_BLOCK_INVALID, + "CFE_ES_CDSBlockWrite", + "Block offset error"); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_ERR_MEM_HANDLE, + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_POOL_BLOCK_INVALID, "CFE_ES_CDSBlockRead", - "Invalid CDS block"); - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; + "Block offset error"); - /* Test CDS block read with a CRC mismatch */ - ES_ResetUnitTest(); - Data = CFE_ES_CDSBlockDesc.CRC; - CFE_ES_CDSBlockDesc.CRC = 56456464; - UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, - BlockHandle) == CFE_ES_CDS_BLOCK_CRC_ERR, - "CFE_ES_CDSBlockRead", - "CRC doesn't match"); - CFE_ES_CDSBlockDesc.CRC = Data; + ++UtCdsRegRecPtr->BlockOffset; - /* Test CDS block read with a CDS read error (block descriptor) */ - ES_ResetUnitTest(); - UT_SetForceFail(UT_KEY(CFE_PSP_ReadFromCDS), -1); + /* Corrupt/change the block size, should trigger invalid size error */ + --UtCdsRegRecPtr->BlockSize; UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == OS_ERROR, - "CFE_ES_CDSBlockRead", - "Error reading block descriptor from CDS"); - - /* Test CDS block read with a CDS read error (block data) */ - ES_ResetUnitTest(); - UT_SetForceFail(UT_KEY(CFE_PSP_ReadFromCDS), -1); - UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_SUCCESS); + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == CFE_ES_CDS_INVALID_SIZE, + "CFE_ES_CDSBlockWrite", + "Block size error"); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == OS_ERROR, + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_CDS_INVALID_SIZE, "CFE_ES_CDSBlockRead", - "Error reading block data from CDS"); + "Block size error"); + ++UtCdsRegRecPtr->BlockSize; - /* Test allocating a CDS block with a block size error (path 2)*/ - ES_ResetUnitTest(); - CFE_ES_CDSMemPool.Current = CFE_ES_CDSMemPool.End; + /* Test CDS block read/write with a CDS read error (block descriptor) */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_GetCDSBlock(&BlockHandle, - 800) == CFE_ES_ERR_MEM_BLOCK_SIZE, - "CFE_ES_GetCDSBlock", - "Block size error (second path)"); - - /* Test rebuilding the CDS pool with an invalid block descriptor */ - ES_ResetUnitTest(); - CFE_ES_CDSMemPoolDefSize[0] = 0; - CFE_ES_CDSBlockDesc.AllocatedFlag = CFE_ES_CDS_BLOCK_USED; + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_CDSBlockWrite", + "Read error on descriptor"); + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_RebuildCDSPool(MinCDSSize, 0) == OS_SUCCESS, - "CFE_ES_RebuildCDSPool", - "Invalid block descriptor"); + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_CDS_ACCESS_ERROR, + "CFE_ES_CDSBlockRead", + "Read error on descriptor"); - /* Test returning a CDS block to the memory pool with an - * invalid check bit pattern - */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.CheckBits = 0x1111; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_PutCDSBlock", - "Invalid check bit pattern"); - /* Test returning a CDS block to the memory pool with an - * invalid check bit pattern - */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.CheckBits = 0x1111; + /* Test CDS block write with a CDS write error (block header) */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 1, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, &Data) == - CFE_ES_ERR_MEM_HANDLE, + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_CDSBlockWrite", - "Invalid check bit pattern"); + "Write error on header"); - /* Test returning a CDS block to the memory pool with an - * invalid check bit pattern - */ - ES_ResetUnitTest(); - CFE_ES_CDSBlockDesc.CheckBits = 0x1111; + /* Test CDS block read with a CDS read error (block header) */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == - CFE_ES_ERR_MEM_HANDLE, + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_CDS_ACCESS_ERROR, "CFE_ES_CDSBlockRead", - "Invalid check bit pattern"); - - /* Test returning a CDS block to the memory pool with an - * invalid CDS handle (path 2) - */ - ES_ResetUnitTest(); - BlockHandle = CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t) - - CFE_ES_CDSMemPool.MinBlockSize - - sizeof(CFE_ES_Global.CDSVars.ValidityField) + 1; - UT_Report(__FILE__, __LINE__, - CFE_ES_PutCDSBlock(BlockHandle) == CFE_ES_ERR_MEM_HANDLE, - "CFE_ES_PutCDSBlock", - "Invalid CDS handle (second path)"); + "Read error on header"); - /* Test CDS block write with a CDS read error (path 2) */ - ES_ResetUnitTest(); - BlockHandle = CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t) - - CFE_ES_CDSMemPool.MinBlockSize - - sizeof(CFE_ES_Global.CDSVars.ValidityField) + 1; + /* Test CDS block write with a CDS write error (data content) */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_WriteToCDS), 2, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockWrite(BlockHandle, &Data) == - CFE_ES_ERR_MEM_HANDLE, + CFE_ES_CDSBlockWrite(BlockHandle, &Data) == OS_ERROR, "CFE_ES_CDSBlockWrite", - "Error writing CDS (second path)"); + "Write error on content"); - /* Test CDS block read with a CDS read error (path 2) */ - ES_ResetUnitTest(); - BlockHandle = CFE_ES_CDSMemPool.End - sizeof(CFE_ES_CDSBlockDesc_t) - - CFE_ES_CDSMemPool.MinBlockSize - - sizeof(CFE_ES_Global.CDSVars.ValidityField) + 1; + /* Test CDS block read with a CDS read error (data content) */ + UT_SetDeferredRetcode(UT_KEY(CFE_PSP_ReadFromCDS), 3, OS_ERROR); UT_Report(__FILE__, __LINE__, - CFE_ES_CDSBlockRead(&Data, BlockHandle) == - CFE_ES_ERR_MEM_HANDLE, + CFE_ES_CDSBlockRead(&Data, BlockHandle) == OS_ERROR, "CFE_ES_CDSBlockRead", - "Error reading CDS (second path)"); - - /* Test CDS minimum memory pool size with no non-zero blocks defined */ - ES_ResetUnitTest(); + "Read error on content"); - for (i = 0; i < CFE_ES_CDS_NUM_BLOCK_SIZES; i++) - { - CFE_ES_CDSMemPoolDefSize[i] = 0; - } - - CFE_ES_CDSMemPool.MinBlockSize = 0; + /* Corrupt the data as to cause a CRC mismatch */ + UT_GetDataBuffer(UT_KEY(CFE_PSP_ReadFromCDS), (void**)&CdsPtr, NULL, NULL); + CdsPtr[UtCdsRegRecPtr->BlockOffset] ^= 0x02; /* Bit flip */ UT_Report(__FILE__, __LINE__, - CFE_ES_CDSReqdMinSize(1) == sizeof(CFE_ES_CDSBlockDesc_t), - "CFE_ES_CDSReqdMinSize", - "No non-zero blocks"); + CFE_ES_CDSBlockRead(&Data, BlockHandle) == CFE_ES_CDS_BLOCK_CRC_ERR, + "CFE_ES_CDSBlockRead", + "CRC error on content"); + CdsPtr[UtCdsRegRecPtr->BlockOffset] ^= 0x02; /* Fix Bit */ } void TestESMempool(void) diff --git a/fsw/cfe-core/unit-test/es_UT.h b/fsw/cfe-core/unit-test/es_UT.h index 0d4a9c6e0..6d9ebe4ed 100644 --- a/fsw/cfe-core/unit-test/es_UT.h +++ b/fsw/cfe-core/unit-test/es_UT.h @@ -280,7 +280,7 @@ void TestAPI(void); ** \sa #UT_SetBSPFail, #CFE_ES_RebuildCDS, #UT_SetRtnCode ** \sa #CFE_ES_InitCDSRegistry, #UT_SetCDSSize, #CFE_ES_CDS_EarlyInit ** \sa #UT_SetCDSBSPCheckValidity, #CFE_ES_ValidateCDS, #UT_SetCDSReadGoodEnd -** \sa #CFE_ES_InitializeCDS, #CFE_ES_RebuildCDS, #CFE_ES_DeleteCDS +** \sa #CFE_ES_InitCDSSignatures, #CFE_ES_RebuildCDS, #CFE_ES_DeleteCDS ** ******************************************************************************/ void TestCDS(void); diff --git a/fsw/cfe-core/unit-test/tbl_UT.c b/fsw/cfe-core/unit-test/tbl_UT.c index ba9b2089e..0ab972b68 100644 --- a/fsw/cfe-core/unit-test/tbl_UT.c +++ b/fsw/cfe-core/unit-test/tbl_UT.c @@ -2257,7 +2257,7 @@ void Test_CFE_TBL_Register(void) /* a. Perform test */ for (i = 0; i < CFE_PLATFORM_TBL_MAX_CRITICAL_TABLES; i++) { - CFE_TBL_TaskData.CritReg[i].CDSHandle = 1; + CFE_TBL_TaskData.CritReg[i].CDSHandle = CFE_ES_RESOURCEID_UNDEFINED; } RtnCode = CFE_TBL_Register(&TblHandle1, "UT_Table1", @@ -4771,9 +4771,9 @@ void Test_CFE_TBL_Internal(void) for (i = 0; i < CFE_PLATFORM_TBL_MAX_CRITICAL_TABLES; i++) { - if (CFE_TBL_TaskData.CritReg[i].CDSHandle == RegRecPtr->CDSHandle) + if ( CFE_ES_ResourceID_Equal(CFE_TBL_TaskData.CritReg[i].CDSHandle, RegRecPtr->CDSHandle) ) { - CFE_TBL_TaskData.CritReg[i].CDSHandle = CFE_ES_CDS_BAD_HANDLE - 1; + CFE_TBL_TaskData.CritReg[i].CDSHandle = CFE_ES_RESOURCEID_RESERVED; } } diff --git a/fsw/cfe-core/ut-stubs/ut_es_stubs.c b/fsw/cfe-core/ut-stubs/ut_es_stubs.c index c63e70485..528cab1ca 100644 --- a/fsw/cfe-core/ut-stubs/ut_es_stubs.c +++ b/fsw/cfe-core/ut-stubs/ut_es_stubs.c @@ -71,6 +71,12 @@ */ #define CFE_UT_ES_DEFAULT_TASKID ((CFE_ES_ResourceID_t){0x02020001}) +/* + * Default value to return from calls that output a CDS ID, if the + * test case does not provide a value + */ +#define CFE_UT_ES_DEFAULT_CDSID ((CFE_ES_ResourceID_t){0x02050001}) + /* * Invalid value to output from calls as resource ID for the * calls that return failure. If subsequently used by application code, @@ -884,7 +890,7 @@ int32 CFE_ES_CopyToCDS(CFE_ES_CDSHandle_t Handle, void *DataToCopy) int32 status; uint32 CdsBufferSize; - UT_Stub_RegisterContext(UT_KEY(CFE_ES_CopyToCDS), (void*)Handle); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_CopyToCDS), Handle); UT_Stub_RegisterContext(UT_KEY(CFE_ES_CopyToCDS), DataToCopy); status = UT_DEFAULT_IMPL(CFE_ES_CopyToCDS); @@ -927,7 +933,7 @@ int32 CFE_ES_RestoreFromCDS(void *RestoreToMemory, CFE_ES_CDSHandle_t Handle) uint32 CdsBufferSize; UT_Stub_RegisterContext(UT_KEY(CFE_ES_RestoreFromCDS), RestoreToMemory); - UT_Stub_RegisterContext(UT_KEY(CFE_ES_RestoreFromCDS), (void*)Handle); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_RestoreFromCDS), Handle); status = UT_DEFAULT_IMPL(CFE_ES_RestoreFromCDS); if (status >= 0) @@ -976,7 +982,7 @@ int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, { if (UT_Stub_CopyToLocal(UT_KEY(CFE_ES_RegisterCDSEx), (uint8*)HandlePtr, sizeof(*HandlePtr)) < sizeof(*HandlePtr)) { - *HandlePtr = 1; + *HandlePtr = CFE_UT_ES_DEFAULT_CDSID; } } @@ -1105,7 +1111,7 @@ bool CFE_ES_RunLoop(uint32 *ExitStatus) return UT_DEFAULT_IMPL(CFE_ES_RunLoop) != 0; } -int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *HandlePtr, int32 BlockSize, const char *Name) +int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *HandlePtr, CFE_ES_CDS_Offset_t BlockSize, const char *Name) { UT_Stub_RegisterContext(UT_KEY(CFE_ES_RegisterCDS), HandlePtr); UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_RegisterCDS), BlockSize);