From daf6c04b597705fce36f06e116de3b5464ab9417 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 6 Oct 2020 19:29:47 -0400 Subject: [PATCH 1/4] 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); From 043b6081ccd69bbd8cafa0115488158ff157b18c Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 7 Oct 2020 17:40:10 -0400 Subject: [PATCH 2/4] Fix #940, Add module suffix and core name to configdata Add the system-specific module suffix (.o, .so, .obj, etc) and the default CFE core executable name to the configdata structure. This information has several useful purposes. --- cmake/target/CMakeLists.txt | 2 ++ cmake/target/inc/target_config.h | 3 +++ cmake/target/src/target_config.c | 2 ++ 3 files changed, 7 insertions(+) diff --git a/cmake/target/CMakeLists.txt b/cmake/target/CMakeLists.txt index 46a27a253..6ef722b6a 100644 --- a/cmake/target/CMakeLists.txt +++ b/cmake/target/CMakeLists.txt @@ -47,6 +47,8 @@ file (REMOVE "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp") add_executable(core-${TGTNAME} src/target_config.c) target_compile_definitions(core-${TGTNAME} PRIVATE + CFE_DEFAULT_MODULE_EXTENSION="${CMAKE_SHARED_MODULE_SUFFIX}" + CFE_DEFAULT_CORE_FILENAME="$" CFE_CPU_NAME_VALUE="${TGTNAME}" CFE_SPACECRAFT_ID_VALUE=${SPACECRAFT_ID} CFE_CPU_ID_VALUE=${${TGTNAME}_PROCESSORID} diff --git a/cmake/target/inc/target_config.h b/cmake/target/inc/target_config.h index 71c6082cc..c4af5307f 100644 --- a/cmake/target/inc/target_config.h +++ b/cmake/target/inc/target_config.h @@ -143,6 +143,9 @@ typedef const struct uint16 Default_CpuId; /**< Compile-time value for CPU number */ uint16 Default_SpacecraftId; /**< Compile-time value for Spacecraft ID (mission-wide) */ + const char *Default_ModuleExtension; /**< Default system extension for dynamic modules */ + const char *Default_CoreFilename; /**< Default file name for CFE core executable/library */ + Target_CfeConfigData *CfeConfig; /**< CFE configuration sub-structure */ Target_PspConfigData *PspConfig; /**< PSP configuration sub-structure */ CFE_StaticModuleLoadEntry_t *PspModuleList; /**< List of PSP modules (API structures) statically linked into the core EXE */ diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index f15233450..9ba74d59f 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -139,6 +139,8 @@ Target_ConfigData GLOBAL_CONFIGDATA = .Default_CpuName = CFE_CPU_NAME_VALUE, .Default_CpuId = CFE_CPU_ID_VALUE, .Default_SpacecraftId = CFE_SPACECRAFT_ID_VALUE, + .Default_ModuleExtension = CFE_DEFAULT_MODULE_EXTENSION, + .Default_CoreFilename = CFE_DEFAULT_CORE_FILENAME, .CfeConfig = &GLOBAL_CFE_CONFIGDATA, .PspConfig = &GLOBAL_PSP_CONFIGDATA, .PspModuleList = GLOBAL_PSP_MODULELIST, From 655a66c05f250c97db5c1ca022dd4a14e967f40a Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Thu, 8 Oct 2020 09:05:59 -0400 Subject: [PATCH 3/4] Update #940, add ifndef values for new fields Adds an #ifndef empty string for the two new fields, which at the very least prevents IDEs (e.g. Eclipse) from redlining the value as an undefined symbol. (It is always passed in on command line when building via CMake) --- cmake/target/src/target_config.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index 9ba74d59f..bbf33104b 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -54,6 +54,13 @@ #define CFE_SPACECRAFT_ID_VALUE 0x42 #endif +#ifndef CFE_DEFAULT_MODULE_EXTENSION +#define CFE_DEFAULT_MODULE_EXTENSION "" +#endif + +#ifndef CFE_DEFAULT_CORE_FILENAME +#define CFE_DEFAULT_CORE_FILENAME "" +#endif Target_CfeConfigData GLOBAL_CFE_CONFIGDATA = { From 2686e50e3f966a1d6f7785402c372f060a4eda18 Mon Sep 17 00:00:00 2001 From: astrogeco <59618057+astrogeco@users.noreply.github.com> Date: Tue, 13 Oct 2020 11:10:15 -0400 Subject: [PATCH 4/4] Bump to v6.8.0-rc1+dev129 and update Readme --- README.md | 6 ++++++ fsw/cfe-core/src/inc/cfe_version.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a439f2c48..3d95fd2e8 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ The detailed cFE user's guide can be viewed at + ### Development Build: 6.8.0-rc1+dev122 - Adds the field `UnregAppID` to track whether an "unregistered" event was generated, un-overloading the EventCount field to serve its primary purpose of counting actual events generated from a valid/registered AppID. diff --git a/fsw/cfe-core/src/inc/cfe_version.h b/fsw/cfe-core/src/inc/cfe_version.h index 7ffe6c465..ca00f673a 100644 --- a/fsw/cfe-core/src/inc/cfe_version.h +++ b/fsw/cfe-core/src/inc/cfe_version.h @@ -35,7 +35,7 @@ /* Development Build Macro Definitions */ -#define CFE_BUILD_NUMBER 122 /*!< Development Build: Number of commits since baseline */ +#define CFE_BUILD_NUMBER 129 /*!< Development Build: Number of commits since baseline */ #define CFE_BUILD_BASELINE "v6.8.0-rc1" /*!< Development Build: git tag that is the base for the current development */ /* Version Macro Definitions */