diff --git a/README.md b/README.md index 0b985bd14..146d312b6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,17 @@ The detailed cFE user's guide can be viewed at + +### Development Build: v6.8.0-rc1+dev365 - Implements a generic FS facility to perform file writes as a background job. Applications wanting to use this need to instantiate a state object (metadata) in global memory and two callback APIs, one to get a data record, another to send events. The following file requests are changed to use this facility: - ES ER Log dump @@ -29,7 +39,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev348 +### Development Build: v6.8.0-rc1+dev348 - Corrects reference to PSP header file location. Build now succesfully completes the build succeeds again when using `add_psp_module()` in custom CMakeLists file. - Replace "send" with "write" in names for commands that write files. For example, `CFE_SB_**SEND**_ROUTING_INFO_CC` is now `CFE_SB_**WRITE**_ROUTING_INFO_CC`. Updates function names, command code names and comments. @@ -57,7 +67,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev290 +### Development Build: v6.8.0-rc1+dev290 - Documentation: Add Security.md with instructions to report vulnerability - Documentation: Update cpuname/MISSION_CPUNAMES documentation @@ -91,7 +101,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev248 +### Development Build: v6.8.0-rc1+dev248 - Replace `OS_FileSysStatVolume()` with`OS_fsBlocksFree()` which will be deprecated. This call reports the number of total blocks, not just the free blocks, making the check more accurate and removing the need for a workaround for desktop machines. - Instead of accessing `OS_time_t` values directly, use the OSAL-provided conversion and access methods. This provides independence and abstraction from the specific `OS_time_t` definition and allows OSAL to transition to a 64 bit value. @@ -100,14 +110,14 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev236 +### Development Build: v6.8.0-rc1+dev236 - Resolved doxygen warnings for osalguide and updated header file references - Corrects the documentation for the CFE_SB_GetPipeName() unit test stub function. - Adds a new github actions workflow file to run cppcheck - See -### Development Build: 6.8.0-rc1+dev228 +### Development Build: v6.8.0-rc1+dev228 - Remove use of `osapi-os-loader.h` from ES UT. - Use volatile `sig_atomic_t` for system state to avoid race issue if uint32 isn't atomic on a system @@ -115,7 +125,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev218 +### Development Build: v6.8.0-rc1+dev218 - Adds `CFE_SB_TransmitMsg`, `CFE_SB_TransmitBuffer`, `CFE_SB_ReceiveBuffer` - Main change is to utilize `CFE_SB_Buffer_t` and `CFE_MSG_Message_t` in a consistent manner to facilitate alignment @@ -126,7 +136,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev204 +### Development Build: v6.8.0-rc1+dev204 - Backward compatible API change. Replace many uses of generic uint16 and uint32 with a more purpose-specific type. Replace all sizes with size_t across the API. - Rename `UT_SetForceFail` to `UT_SetDefaultReturnValue` since some functions that retain more than 1 value are not necessarily failing @@ -137,7 +147,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev179 +### Development Build: v6.8.0-rc1+dev179 - Adds macros for more compact calls to `CFE_EVS_SendEvent`, making the type be part of the function name. - The sample configs leap seconds default value is now up to date. (As of Oct 2020) @@ -147,7 +157,7 @@ The detailed cFE user's guide can be viewed at -### Development Build: 6.8.0-rc1+dev164 +### Development Build: v6.8.0-rc1+dev164 - Keeps task names under 16 chars to make more debugger friendly, regardless of the OSAL limit. Task name shows up as `ES_BG_TASK` @@ -158,7 +168,7 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - Cast fixed width types to the type used in the `printf` call. Removes `printf` type warnings on the 32-bit RTEMS build. - See -### Development Build: 6.8.0-rc1+dev150 +### Development Build: v6.8.0-rc1+dev150 - Provide new Library API similar to App API - Allows the existing CFE_ES_AppInfo_t structure to be extended to libraries as well as applications by introducing a new value (3) for the Type field. @@ -177,19 +187,19 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - Individual events for deleting destinations when deleting a pipe removed to avoid a race condition around a 10-20% performance hit to hash via rough comparison on a linux box, no memory impact - See -### Development Build: 6.8.0-rc1+dev139 +### Development Build: v6.8.0-rc1+dev139 - For all resource types which have names, IDs are not re-issued after deletion, helping ensure safety as previously deleted IDs will not validate. Provides a consistent Name-ID translation API for all resource types. Enforces consistent argument/name validation on all resource types, and also enforces name uniqueness where relevant. - Enhancement to use the full 16 bits of resource ID space, which avoids repeating ID values that have already been used. This significantly decreases the likelihood that a previously deleted ID will alias a newly allocated/valid ID. - See -### Development Build: 6.8.0-rc1+dev129 +### Development Build: v6.8.0-rc1+dev129 - 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. - Add the system-specific module suffix (.o, .so, .obj, etc) and the default CFE core executable name to the configdata structure. - See -### Development Build: 6.8.0-rc1+dev122 +### Development Build: v6.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. - Move the AppID lookup execution to be early in the `CFE_SB_SendMsgFull` implementation. This avoids double locking between SB+ES and avoids a block-scope local variable. @@ -200,12 +210,12 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - This creates the new `CFE_Status_t` typedef for function's return status codes. Also adds a note to `CFE_TBL_GetStatus` since its behavior will likely change in the future in the hopes of not having a non-zero "info" status. - See -### Development Build: 6.8.0-rc1+dev109 +### Development Build: v6.8.0-rc1+dev109 - Add a new typedef `CFE_ES_ResourceID_t` that can replace `uint32` for all ID storage and manipulation. Initially this is just an alias to `uint32` for backward compatibility. - See -### Development Build: 6.8.0-rc1+dev105 +### Development Build: v6.8.0-rc1+dev105 - Removes dependency on CCSDS version define. - Removes old name and id defines. @@ -216,7 +226,7 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - See -### Development Build: 6.8.0-rc1+dev91 +### Development Build: v6.8.0-rc1+dev91 - Sets Revision to 99 for development build. - Installs unit test to target directory. @@ -224,7 +234,7 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - Applies the appid/taskid/counterid pattern to Library resources. - See -### Development Build: 6.8.0-rc1+dev81 +### Development Build: v6.8.0-rc1+dev81 - Deconflict CFE_ES_LIB_ALREADY_LOADED and CFE_ES_ERR_SYS_LOG_TRUNCATED EIDs - Scrub all CFE references/uses of OSAL IDs to use the proper osal_id_t type. Any place that an OSAL ID is stored in memory or passed in an API call are changed to the osal_id_t type, rather than uint32. Conversions between this and other types (e.g. bare integer) is done using the OSAL-supplied conversion helpers. @@ -235,7 +245,7 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - See -### Development Build: 6.8.0-rc1+dev65 +### Development Build: v6.8.0-rc1+dev65 - In the next major CFE release, this code will be no longer supported at all. It should be removed early in the cycle to avoid needing to maintain this compatibility code. - The CFE_ES_FindCDSInRegistry function had an unusual loop control structure with mixed types of signed and unsigned. This has the possibility of being infinite if the MaxNumRegEntries is zero due to the way the end condition is structured. Simplify to be like other loops and use unsigned int control variable. @@ -245,7 +255,7 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - HOTFIX 20200902 - Fix SB Test_CleanupApp_API AppID. - See -### Development Build: 6.8.0-rc1+dev42 +### Development Build: v6.8.0-rc1+dev42 - Removes reference from documentation. - CFE_SB_SendMsg stub now behaves the same as CFE_SB_TimeStampMsg (copies message pointer from local). No longer need to emulate CFE_SB_InitMsg from test code, set the API/stub data buffers directly. @@ -254,7 +264,7 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - Replaced CFE_MISSION_SPACECRAFT_ID use with CFE_PSP_GetSpacecraftId() and updated unit test - See -### Development Build: 6.8.0-rc1+dev28 +### Development Build: v6.8.0-rc1+dev28 - Add msg stubs, update SB_UT to use them, and remove msg module include from unit tests - Collapses time options down to just 32 bit second, 16 bit subsecond, always big endian. Removes old defines, and triggers an error if the configuration is set to a format that was removed. @@ -262,14 +272,14 @@ of the OSAL limit. Task name shows up as `ES_BG_TASK` - Unit tests added from within unit tests will not execute, replaced this pattern with direct calls to the main subtest setup routine. - See -### Development Build: 6.8.0-rc1+dev13 +### Development Build: v6.8.0-rc1+dev13 - Deprecates `CFE_SB_GetLastSenderId()` API by introducing new `CFE_OMIT_DEPRECATED_6_8` tag - Documentation update remove deleted requiremements - Add a new *cfe_assert* module for functional testing by making it possible to load the UT assert object code as a CFE library. These are compiled as separate, independent modules and only loaded on demand. Also includes a draft example for cFE testing, which calls some basic ES AppId functions. - See -### Development Build: 6.7.0+dev292 +### Development Build: v6.7.0+dev292 - Add missing include path to the target/h and wrn/coreip directory. Set and clarify difference between WIND_HOME and WIND_BASE variables. @@ -277,7 +287,7 @@ Remove unrelated comment about CEXP (remnant from RTEMS). No more errors about m - Version reporting is does not span multiple lines. - See -### Development Build: 6.7.0+dev289 +### Development Build: v6.7.0+dev289 - Update `CFE_SB_TimeStampMsg` to save the message pointer argument `UT_Stub_CopyFromLocal` so that unit tests can check it - Only affects build system. Fully backward compatible. The defaults are applied if a user has nothing specifically configured in their `targets.cmake`. The defaults will select osal, cfe-core, and psp as before. The user now has the option to explicitly configure and control the inclusion of these modules and also provide mission-specific search paths to override them as desired. @@ -434,13 +444,13 @@ Behavior Change: App unit tests requiring this will not fail to build due to und - Fix strlen in CFE_ES_TaskInit - Minor bug fixes (see ) -### **_OFFICIAL RELEASE: 6.7.0 - Aquila_** +### **_OFFICIAL RELEASE: v6.7.0 - Aquila_** - This is a point release from an internal repository - Changes are detailed in [cFS repo](https://github.com/nasa/cFS) release documentation - Apache 2.0 -### **_OFFICIAL RELEASE: 6.6.0a_** +### **_OFFICIAL RELEASE: v6.6.0a_** - This is a point release from an internal repository - Apache 2.0 diff --git a/cmake/sample_defs/cpu1_cfe_es_startup.scr b/cmake/sample_defs/cpu1_cfe_es_startup.scr index d03c0e77a..d0510376a 100644 --- a/cmake/sample_defs/cpu1_cfe_es_startup.scr +++ b/cmake/sample_defs/cpu1_cfe_es_startup.scr @@ -1,8 +1,8 @@ -CFE_LIB, /cf/sample_lib.so, SAMPLE_LIB_Init, SAMPLE_LIB, 0, 0, 0x0, 0; -CFE_APP, /cf/sample_app.so, SAMPLE_APP_Main, SAMPLE_APP, 50, 16384, 0x0, 0; -CFE_APP, /cf/ci_lab.so, CI_Lab_AppMain, CI_LAB_APP, 60, 16384, 0x0, 0; -CFE_APP, /cf/to_lab.so, TO_Lab_AppMain, TO_LAB_APP, 70, 16384, 0x0, 0; -CFE_APP, /cf/sch_lab.so, SCH_Lab_AppMain, SCH_LAB_APP, 80, 16384, 0x0, 0; +CFE_LIB, sample_lib, SAMPLE_LIB_Init, SAMPLE_LIB, 0, 0, 0x0, 0; +CFE_APP, sample_app, SAMPLE_APP_Main, SAMPLE_APP, 50, 16384, 0x0, 0; +CFE_APP, ci_lab, CI_Lab_AppMain, CI_LAB_APP, 60, 16384, 0x0, 0; +CFE_APP, to_lab, TO_Lab_AppMain, TO_LAB_APP, 70, 16384, 0x0, 0; +CFE_APP, sch_lab, SCH_Lab_AppMain, SCH_LAB_APP, 80, 16384, 0x0, 0; ! ! Startup script fields: ! 1. Object Type -- CFE_APP for an Application, or CFE_LIB for a library. @@ -27,4 +27,7 @@ CFE_APP, /cf/sch_lab.so, SCH_Lab_AppMain, SCH_LAB_APP, 80, 16384, 0x0, 0; ! vxWorks = .o ( ci.o ) ! RTEMS with S-record Loader = .s3r ( ci.s3r ) ! RTEMS with CEXP Loader = .o ( ci.o ) +! 3. The filename field (2) no longer requires a fully-qualified filename; the path and extension +! may be omitted. If omitted, the standard virtual path (/cf) and a platform-specific default +! extension will be used, which is derived from the build system. diff --git a/cmake/sample_defs/cpu1_platform_cfg.h b/cmake/sample_defs/cpu1_platform_cfg.h index 431c9960f..8ab9735b8 100644 --- a/cmake/sample_defs/cpu1_platform_cfg.h +++ b/cmake/sample_defs/cpu1_platform_cfg.h @@ -36,6 +36,35 @@ #ifndef _cfe_platform_cfg_ #define _cfe_platform_cfg_ + +/** +** \cfeescfg Default virtual path for persistent storage +** +** \par Description: +** This configures the default location in the virtual file system +** for persistent/non-volatile storage. Files such as the startup +** script, app/library dynamic modules, and configuration tables are +** expected to be stored in this directory. +** +*/ +#define CFE_PLATFORM_ES_NONVOL_DISK_MOUNT_STRING "/cf" + +/** +** \cfeescfg Default virtual path for volatile storage +** +** \par Description: +** The #CFE_PLATFORM_ES_RAM_DISK_MOUNT_STRING parameter is used to set the cFE mount path +** for the CFE RAM disk. This is a parameter for missions that do not want to +** use the default value of "/ram", or for missions that need to have a different +** value for different CPUs or Spacecraft. +** Note that the vxWorks OSAL cannot currently handle names that have more than one +** path separator in it. The names "/ram", "/ramdisk", "/disk123" will all work, but +** "/disks/ram" will not. +** Multiple separators can be used with the posix or RTEMS ports. +** +*/ +#define CFE_PLATFORM_ES_RAM_DISK_MOUNT_STRING "/ram" + /** ** \cfesbcfg Maximum Number of Unique Message IDs SB Routing Table can hold ** @@ -682,23 +711,6 @@ #define CFE_PLATFORM_ES_RAM_DISK_PERCENT_RESERVED 30 -/** -** \cfeescfg RAM Disk Mount string -** -** \par Description: -** The #CFE_PLATFORM_ES_RAM_DISK_MOUNT_STRING parameter is used to set the cFE mount path -** for the CFE RAM disk. This is a parameter for missions that do not want to -** use the default value of "/ram", or for missions that need to have a different -** value for different CPUs or Spacecraft. -** Note that the vxWorks OSAL cannot currently handle names that have more than one -** path separator in it. The names "/ram", "/ramdisk", "/disk123" will all work, but -** "/disks/ram" will not. -** Multiple separators can be used with the posix or RTEMS ports. -** -*/ -#define CFE_PLATFORM_ES_RAM_DISK_MOUNT_STRING "/ram" - - /** ** \cfeescfg Define Critical Data Store Size ** diff --git a/cmake/target/inc/target_config.h b/cmake/target/inc/target_config.h index c4af5307f..4c19bb6e1 100644 --- a/cmake/target/inc/target_config.h +++ b/cmake/target/inc/target_config.h @@ -106,7 +106,17 @@ typedef const struct uint32 RamDiskTotalSectors; /***< RAM disk number of sectors */ /** - * Default value for start up file + * Default value for nonvolatile file system mount point + */ + const char *NonvolMountPoint; + + /** + * Default value for volatile file system mount point + */ + const char *RamdiskMountPoint; + + /** + * File name of startup script */ const char *NonvolStartupFile; diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index bbf33104b..33c6d49aa 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -72,9 +72,10 @@ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA = .SystemNotify = CFE_ES_ProcessAsyncEvent, /* - * Default values for Startup file. - * This is a suggested value, but the PSP may provide a different file + * Default values for various file paths */ + .NonvolMountPoint = CFE_PLATFORM_ES_NONVOL_DISK_MOUNT_STRING, + .RamdiskMountPoint = CFE_PLATFORM_ES_RAM_DISK_MOUNT_STRING, .NonvolStartupFile = CFE_PLATFORM_ES_NONVOL_STARTUP_FILE, /* diff --git a/docs/src/cfe_es.dox b/docs/src/cfe_es.dox index c059db76a..fdb3cdcf4 100644 --- a/docs/src/cfe_es.dox +++ b/docs/src/cfe_es.dox @@ -41,7 +41,6 @@
  • \subpage cfeesugcdssrv
  • \subpage cfeesugmempoolsrv
  • \subpage cfeesugsyslogsrv
    -
  • \subpage cfeesugshellsrv
  • \subpage cfeesugversion
  • \subpage cfeesugfaq
    @@ -799,19 +798,8 @@ A count of the number of entries in the log is present in the ES housekeeping telemetry. - Next: \ref cfeesugshellsrv
    - Prev: \ref cfeesugmempoolsrv
    - Up To: \ref cfeesovr -**/ - -/** - \page cfeesugshellsrv OS Shell - - NOTE: This cfe functionality is targeted for deprecation in favor of - optionally including this capability via an application. - Next: \ref cfeesugversion
    - Prev: \ref cfeesugsyslogsrv
    + Prev: \ref cfeesugmempoolsrv
    Up To: \ref cfeesovr **/ @@ -821,7 +809,7 @@ Version information is reported at startup, and upon receipt of a No-op command Next: \ref cfeesugfaq
    - Prev: \ref cfeesugshellsrv
    + Prev: \ref cfeesugsyslogsrv
    Up To: \ref cfeesovr **/ @@ -830,7 +818,7 @@ - Prev: \ref cfeesugshellsrv
    + Prev: \ref cfeesugversion
    Up To: \ref cfeesovr **/ diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index 54304aecb..4974eb62c 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -1590,6 +1590,11 @@ int32 CFE_ES_WriteToSysLog(const char *SpecStringPtr, ...) int32 ReturnCode; va_list ArgPtr; + if (SpecStringPtr == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + va_start(ArgPtr, SpecStringPtr); CFE_ES_SysLog_vsnprintf(TmpString, sizeof(TmpString), SpecStringPtr, ArgPtr); va_end(ArgPtr); @@ -1659,6 +1664,11 @@ uint32 CFE_ES_CalculateCRC(const void *DataPtr, size_t DataLength, uint32 InputC }; + if (DataPtr == NULL || DataLength == 0) + { + return InputCRC; + } + switch(TypeCRC) { case CFE_MISSION_ES_CRC_32: @@ -1709,12 +1719,17 @@ int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, size_t BlockSize, con char AppName[OS_MAX_API_NAME] = {"UNKNOWN"}; char CDSName[CFE_MISSION_ES_CDS_MAX_FULL_NAME_LEN] = {""}; - /* Initialize output to safe value, in case this fails */ - *CDSHandlePtr = CFE_ES_CDS_BAD_HANDLE; - /* Check to make sure calling application is legit */ Status = CFE_ES_GetAppID(&ThisAppId); + if (CDSHandlePtr == NULL || Name == NULL){ + CFE_ES_WriteToSysLog("CFE_ES_RegisterCDS:-Failed invalid arguments\n"); + return CFE_ES_BAD_ARGUMENT; + } + + /* Initialize output to safe value, in case this fails */ + *CDSHandlePtr = CFE_ES_CDS_BAD_HANDLE; + if ( Status != CFE_SUCCESS ) /* Application ID was invalid */ { CFE_ES_WriteToSysLog("CFE_CDS:Register-Bad AppId context\n"); @@ -1726,9 +1741,6 @@ int32 CFE_ES_RegisterCDS(CFE_ES_CDSHandle_t *CDSHandlePtr, size_t BlockSize, con } else { - /* Assume we can't make a CDS and return a bad handle for now */ - *CDSHandlePtr = CFE_ES_CDS_BAD_HANDLE; - /* Make sure specified CDS name is not too long or too short */ NameLen = strlen(Name); if ((NameLen > CFE_MISSION_ES_CDS_MAX_NAME_LENGTH) || (NameLen == 0)) @@ -1863,6 +1875,11 @@ CFE_Status_t CFE_ES_GetCDSBlockName(char *BlockName, CFE_ES_CDSHandle_t BlockId, */ int32 CFE_ES_CopyToCDS(CFE_ES_CDSHandle_t Handle, void *DataToCopy) { + if (DataToCopy == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + return CFE_ES_CDSBlockWrite(Handle, DataToCopy); } /* End of CFE_ES_CopyToCDS() */ @@ -1874,6 +1891,11 @@ int32 CFE_ES_CopyToCDS(CFE_ES_CDSHandle_t Handle, void *DataToCopy) */ int32 CFE_ES_RestoreFromCDS(void *RestoreToMemory, CFE_ES_CDSHandle_t Handle) { + if (RestoreToMemory == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + return CFE_ES_CDSBlockRead(RestoreToMemory, Handle); } /* End of CFE_ES_RestoreFromCDS() */ diff --git a/fsw/cfe-core/src/es/cfe_es_apps.c b/fsw/cfe-core/src/es/cfe_es_apps.c index fddb1203b..4802ba75e 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.c +++ b/fsw/cfe-core/src/es/cfe_es_apps.c @@ -76,7 +76,8 @@ */ void CFE_ES_StartApplications(uint32 ResetType, const char *StartFilePath ) { - char ES_AppLoadBuffer[ES_START_BUFF_SIZE]; /* A buffer of for a line in a file */ + char ES_AppLoadBuffer[ES_START_BUFF_SIZE]; /* A buffer of for a line in a file */ + char ScriptFileName[OS_MAX_PATH_LEN]; const char *TokenList[CFE_ES_STARTSCRIPT_MAX_TOKENS_PER_LINE]; uint32 NumTokens; uint32 BuffLen; /* Length of the current buffer */ @@ -93,14 +94,20 @@ void CFE_ES_StartApplications(uint32 ResetType, const char *StartFilePath ) if ( ResetType == CFE_PSP_RST_TYPE_PROCESSOR ) { /* - ** Open the file in the volatile disk. + ** First Attempt to parse as file in the volatile disk (temp area). */ - Status = OS_OpenCreate(&AppFile, CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE, OS_FILE_FLAG_NONE, OS_READ_ONLY); + Status = CFE_FS_ParseInputFileName(ScriptFileName, CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE, + sizeof(ScriptFileName), CFE_FS_FileCategory_TEMP); + + if (Status == CFE_SUCCESS) + { + Status = OS_OpenCreate(&AppFile, ScriptFileName, OS_FILE_FLAG_NONE, OS_READ_ONLY); + } if ( Status >= 0 ) { CFE_ES_WriteToSysLog ("ES Startup: Opened ES App Startup file: %s\n", - CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE); + ScriptFileName); FileOpened = true; } else @@ -120,11 +127,17 @@ void CFE_ES_StartApplications(uint32 ResetType, const char *StartFilePath ) /* ** Try to Open the file passed in to the cFE start. */ - Status = OS_OpenCreate(&AppFile, StartFilePath, OS_FILE_FLAG_NONE, OS_READ_ONLY); + Status = CFE_FS_ParseInputFileName(ScriptFileName, StartFilePath, + sizeof(ScriptFileName), CFE_FS_FileCategory_SCRIPT); + + if (Status == CFE_SUCCESS) + { + Status = OS_OpenCreate(&AppFile, ScriptFileName, OS_FILE_FLAG_NONE, OS_READ_ONLY); + } if ( Status >= 0 ) { - CFE_ES_WriteToSysLog ("ES Startup: Opened ES App Startup file: %s\n",StartFilePath); + CFE_ES_WriteToSysLog ("ES Startup: Opened ES App Startup file: %s\n",ScriptFileName); FileOpened = true; } else @@ -271,7 +284,7 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) CFE_ES_AppId_t AppId; CFE_ES_LibId_t LibId; } IdBuf; - int32 CreateStatus = CFE_ES_ERR_APP_CREATE; + int32 Status; CFE_ES_AppStartParams_t ParamBuf; /* @@ -280,7 +293,7 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) if (NumTokens < 8) { CFE_ES_WriteToSysLog("ES Startup: Invalid ES Startup file entry: %u\n", (unsigned int)NumTokens); - return (CreateStatus); + return CFE_ES_BAD_ARGUMENT; } /* Get pointers to specific tokens that are simple strings used as-is */ @@ -292,7 +305,14 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) * Both Libraries and Apps use File Name (1) and Symbol Name (2) fields so copy those now */ memset(&ParamBuf, 0, sizeof(ParamBuf)); - strncpy(ParamBuf.BasicInfo.FileName, TokenList[1], sizeof(ParamBuf.BasicInfo.FileName) - 1); + Status = CFE_FS_ParseInputFileName(ParamBuf.BasicInfo.FileName, TokenList[1], + sizeof(ParamBuf.BasicInfo.FileName), CFE_FS_FileCategory_DYNAMIC_MODULE); + if (Status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Invalid ES Startup script file name: %s\n", TokenList[1]); + return Status; + } + strncpy(ParamBuf.BasicInfo.InitSymbolName, TokenList[2], sizeof(ParamBuf.BasicInfo.InitSymbolName) - 1); if (strcmp(EntryType, "CFE_APP") == 0) @@ -338,7 +358,7 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) /* ** Now create the application */ - CreateStatus = CFE_ES_AppCreate(&IdBuf.AppId, ModuleName, &ParamBuf); + Status = CFE_ES_AppCreate(&IdBuf.AppId, ModuleName, &ParamBuf); } else if (strcmp(EntryType, "CFE_LIB") == 0) { @@ -347,14 +367,15 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) /* ** Now load the library */ - CreateStatus = CFE_ES_LoadLibrary(&IdBuf.LibId, ModuleName, &ParamBuf.BasicInfo); + Status = CFE_ES_LoadLibrary(&IdBuf.LibId, ModuleName, &ParamBuf.BasicInfo); } else { CFE_ES_WriteToSysLog("ES Startup: Unexpected EntryType %s in startup file.\n", EntryType); + Status = CFE_ES_ERR_APP_CREATE; } - return (CreateStatus); + return (Status); } /* diff --git a/fsw/cfe-core/src/es/cfe_es_mempool.c b/fsw/cfe-core/src/es/cfe_es_mempool.c index 5832b128d..66a833a42 100644 --- a/fsw/cfe-core/src/es/cfe_es_mempool.c +++ b/fsw/cfe-core/src/es/cfe_es_mempool.c @@ -411,6 +411,11 @@ int32 CFE_ES_GetPoolBuf(CFE_ES_MemPoolBuf_t *BufPtr, CFE_ES_MemPoolRecord_t *PoolRecPtr; size_t DataOffset; + if (BufPtr == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + PoolRecPtr = CFE_ES_LocateMemPoolRecordByID(Handle); /* basic sanity check */ @@ -473,6 +478,11 @@ int32 CFE_ES_GetPoolBufInfo(CFE_ES_MemHandle_t Handle, size_t DataOffset; size_t DataSize; + if (BufPtr == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + PoolRecPtr = CFE_ES_LocateMemPoolRecordByID(Handle); /* basic sanity check */ @@ -527,6 +537,11 @@ int32 CFE_ES_PutPoolBuf(CFE_ES_MemHandle_t Handle, size_t DataOffset; int32 Status; + if (BufPtr == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + PoolRecPtr = CFE_ES_LocateMemPoolRecordByID(Handle); /* basic sanity check */ @@ -605,6 +620,11 @@ int32 CFE_ES_GetMemPoolStats(CFE_ES_MemPoolStats_t *BufPtr, uint16 NumBuckets; uint16 Idx; + if (BufPtr == NULL) + { + return CFE_ES_BAD_ARGUMENT; + } + PoolRecPtr = CFE_ES_LocateMemPoolRecordByID(Handle); /* basic sanity check */ diff --git a/fsw/cfe-core/src/evs/cfe_evs.c b/fsw/cfe-core/src/evs/cfe_evs.c index f3fb70b34..ac6c32318 100644 --- a/fsw/cfe-core/src/evs/cfe_evs.c +++ b/fsw/cfe-core/src/evs/cfe_evs.c @@ -154,6 +154,10 @@ int32 CFE_EVS_SendEvent (uint16 EventID, uint16 EventType, const char *Spec, ... va_list Ptr; EVS_AppData_t *AppDataPtr; + if(Spec == NULL){ + return CFE_EVS_INVALID_PARAMETER; + } + /* Query and verify the caller's AppID */ Status = EVS_GetCurrentContext(&AppDataPtr, &AppID); if (Status == CFE_SUCCESS) @@ -190,6 +194,10 @@ int32 CFE_EVS_SendEventWithAppID (uint16 EventID, uint16 EventType, CFE_ES_AppId va_list Ptr; EVS_AppData_t *AppDataPtr; + if(Spec == NULL){ + return CFE_EVS_INVALID_PARAMETER; + } + AppDataPtr = EVS_GetAppDataByID (AppID); if (AppDataPtr == NULL) { @@ -225,6 +233,10 @@ int32 CFE_EVS_SendTimedEvent (CFE_TIME_SysTime_t Time, uint16 EventID, uint16 Ev va_list Ptr; EVS_AppData_t *AppDataPtr; + if(Spec == NULL){ + return CFE_EVS_INVALID_PARAMETER; + } + /* Query and verify the caller's AppID */ Status = EVS_GetCurrentContext(&AppDataPtr, &AppID); if (Status == CFE_SUCCESS) diff --git a/fsw/cfe-core/src/evs/cfe_evs_log.c b/fsw/cfe-core/src/evs/cfe_evs_log.c index e5ae293d7..b8d1cc6fe 100644 --- a/fsw/cfe-core/src/evs/cfe_evs_log.c +++ b/fsw/cfe-core/src/evs/cfe_evs_log.c @@ -54,53 +54,50 @@ void EVS_AddLog (CFE_EVS_LongEventTlm_t *EVS_PktPtr) { - if (CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled == true) - { - /* Serialize access to event log control variables */ - OS_MutSemTake(CFE_EVS_Global.EVS_SharedDataMutexID); + /* Serialize access to event log control variables */ + OS_MutSemTake(CFE_EVS_Global.EVS_SharedDataMutexID); - if ((CFE_EVS_Global.EVS_LogPtr->LogFullFlag == true) && - (CFE_EVS_Global.EVS_LogPtr->LogMode == CFE_EVS_LogMode_DISCARD)) + if ((CFE_EVS_Global.EVS_LogPtr->LogFullFlag == true) && + (CFE_EVS_Global.EVS_LogPtr->LogMode == CFE_EVS_LogMode_DISCARD)) + { + /* If log is full and in discard mode, just count the event */ + CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter++; + } + else + { + if (CFE_EVS_Global.EVS_LogPtr->LogFullFlag == true) { - /* If log is full and in discard mode, just count the event */ + /* If log is full and in wrap mode, count it and store it */ CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter++; } - else - { - if (CFE_EVS_Global.EVS_LogPtr->LogFullFlag == true) - { - /* If log is full and in wrap mode, count it and store it */ - CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter++; - } - /* Copy the event data to the next available entry in the log */ - memcpy(&CFE_EVS_Global.EVS_LogPtr->LogEntry[CFE_EVS_Global.EVS_LogPtr->Next], - EVS_PktPtr, sizeof(*EVS_PktPtr)); + /* Copy the event data to the next available entry in the log */ + memcpy(&CFE_EVS_Global.EVS_LogPtr->LogEntry[CFE_EVS_Global.EVS_LogPtr->Next], + EVS_PktPtr, sizeof(*EVS_PktPtr)); - CFE_EVS_Global.EVS_LogPtr->Next++; + CFE_EVS_Global.EVS_LogPtr->Next++; - if (CFE_EVS_Global.EVS_LogPtr->Next >= CFE_PLATFORM_EVS_LOG_MAX) - { - /* This is important, even if we are in discard mode */ - CFE_EVS_Global.EVS_LogPtr->Next = 0; - } + if (CFE_EVS_Global.EVS_LogPtr->Next >= CFE_PLATFORM_EVS_LOG_MAX) + { + /* This is important, even if we are in discard mode */ + CFE_EVS_Global.EVS_LogPtr->Next = 0; + } - /* Log count cannot exceed the number of entries in the log */ - if (CFE_EVS_Global.EVS_LogPtr->LogCount < CFE_PLATFORM_EVS_LOG_MAX) - { - CFE_EVS_Global.EVS_LogPtr->LogCount++; + /* Log count cannot exceed the number of entries in the log */ + if (CFE_EVS_Global.EVS_LogPtr->LogCount < CFE_PLATFORM_EVS_LOG_MAX) + { + CFE_EVS_Global.EVS_LogPtr->LogCount++; - if (CFE_EVS_Global.EVS_LogPtr->LogCount == CFE_PLATFORM_EVS_LOG_MAX) - { - /* The full flag and log count are somewhat redundant */ - CFE_EVS_Global.EVS_LogPtr->LogFullFlag = true; - } + if (CFE_EVS_Global.EVS_LogPtr->LogCount == CFE_PLATFORM_EVS_LOG_MAX) + { + /* The full flag and log count are somewhat redundant */ + CFE_EVS_Global.EVS_LogPtr->LogFullFlag = true; } } - - OS_MutSemGive(CFE_EVS_Global.EVS_SharedDataMutexID); } + OS_MutSemGive(CFE_EVS_Global.EVS_SharedDataMutexID); + return; } /* End EVS_AddLog */ @@ -159,99 +156,88 @@ int32 CFE_EVS_WriteLogDataFileCmd(const CFE_EVS_WriteLogDataFileCmd_t *data) CFE_FS_Header_t LogFileHdr; char LogFilename[OS_MAX_PATH_LEN]; - if (CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled == false) + /* Copy the commanded filename into local buffer to ensure size limitation and to allow for modification */ + CFE_SB_MessageStringGet(LogFilename, (const char *)CmdPtr->LogFilename, CFE_PLATFORM_EVS_DEFAULT_LOG_FILE, + sizeof(LogFilename), sizeof(CmdPtr->LogFilename)); + + /* Create the log file */ + Result = OS_OpenCreate(&LogFileHandle, LogFilename, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); + + if (Result < OS_SUCCESS) { - EVS_SendEvent(CFE_EVS_NO_LOGWR_EID, CFE_EVS_EventType_ERROR, - "Write Log Command: Event Log is Disabled"); - Result = CFE_EVS_FUNCTION_DISABLED; + EVS_SendEvent(CFE_EVS_ERR_CRLOGFILE_EID, CFE_EVS_EventType_ERROR, + "Write Log File Command Error: OS_OpenCreate = 0x%08X, filename = %s", + (unsigned int)Result, LogFilename); } else { - /* Copy the commanded filename into local buffer to ensure size limitation and to allow for modification */ - CFE_SB_MessageStringGet(LogFilename, (const char *)CmdPtr->LogFilename, CFE_PLATFORM_EVS_DEFAULT_LOG_FILE, - sizeof(LogFilename), sizeof(CmdPtr->LogFilename)); + /* Result will be overridden if everything works */ + Result = CFE_EVS_FILE_WRITE_ERROR; - /* Create the log file */ - Result = OS_OpenCreate(&LogFileHandle, LogFilename, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); + /* Initialize cFE file header for an event log file */ + CFE_FS_InitHeader(&LogFileHdr, "cFE EVS Log File", CFE_FS_SubType_EVS_EVENTLOG); - if (Result < OS_SUCCESS) - { - EVS_SendEvent(CFE_EVS_ERR_CRLOGFILE_EID, CFE_EVS_EventType_ERROR, - "Write Log File Command Error: OS_OpenCreate = 0x%08X, filename = %s", - (unsigned int)Result, LogFilename); + /* Write the file header to the log file */ + BytesWritten = CFE_FS_WriteHeader(LogFileHandle, &LogFileHdr); - } - else + if (BytesWritten == sizeof(LogFileHdr)) { - /* Result will be overridden if everything works */ - Result = CFE_EVS_FILE_WRITE_ERROR; - - /* Initialize cFE file header for an event log file */ - CFE_FS_InitHeader(&LogFileHdr, "cFE EVS Log File", CFE_FS_SubType_EVS_EVENTLOG); - - /* Write the file header to the log file */ - BytesWritten = CFE_FS_WriteHeader(LogFileHandle, &LogFileHdr); + /* Serialize access to event log control variables */ + OS_MutSemTake(CFE_EVS_Global.EVS_SharedDataMutexID); - if (BytesWritten == sizeof(LogFileHdr)) + /* Is the log full? -- Doesn't matter if wrap mode is enabled */ + if (CFE_EVS_Global.EVS_LogPtr->LogCount == CFE_PLATFORM_EVS_LOG_MAX) + { + /* Start with log entry that will be overwritten next (oldest) */ + LogIndex = CFE_EVS_Global.EVS_LogPtr->Next; + } + else { - /* Serialize access to event log control variables */ - OS_MutSemTake(CFE_EVS_Global.EVS_SharedDataMutexID); + /* Start with the first entry in the log (oldest) */ + LogIndex = 0; + } - /* Is the log full? -- Doesn't matter if wrap mode is enabled */ - if (CFE_EVS_Global.EVS_LogPtr->LogCount == CFE_PLATFORM_EVS_LOG_MAX) - { - /* Start with log entry that will be overwritten next (oldest) */ - LogIndex = CFE_EVS_Global.EVS_LogPtr->Next; - } - else - { - /* Start with the first entry in the log (oldest) */ - LogIndex = 0; - } + /* Write all the "in-use" event log entries to the file */ + for (i = 0; i < CFE_EVS_Global.EVS_LogPtr->LogCount; i++) + { + BytesWritten = OS_write(LogFileHandle, + &CFE_EVS_Global.EVS_LogPtr->LogEntry[LogIndex], + sizeof(CFE_EVS_Global.EVS_LogPtr->LogEntry[LogIndex])); - /* Write all the "in-use" event log entries to the file */ - for (i = 0; i < CFE_EVS_Global.EVS_LogPtr->LogCount; i++) + if (BytesWritten == sizeof(CFE_EVS_Global.EVS_LogPtr->LogEntry[LogIndex])) { - BytesWritten = OS_write(LogFileHandle, - &CFE_EVS_Global.EVS_LogPtr->LogEntry[LogIndex], - sizeof(CFE_EVS_Global.EVS_LogPtr->LogEntry[LogIndex])); + LogIndex++; - if (BytesWritten == sizeof(CFE_EVS_Global.EVS_LogPtr->LogEntry[LogIndex])) + if (LogIndex >= CFE_PLATFORM_EVS_LOG_MAX) { - LogIndex++; - - if (LogIndex >= CFE_PLATFORM_EVS_LOG_MAX) - { - LogIndex = 0; - } - } - else - { - break; + LogIndex = 0; } } - - OS_MutSemGive(CFE_EVS_Global.EVS_SharedDataMutexID); - - /* Process command handler success result */ - if (i == CFE_EVS_Global.EVS_LogPtr->LogCount) - { - EVS_SendEvent(CFE_EVS_WRLOG_EID, CFE_EVS_EventType_DEBUG, - "Write Log File Command: %d event log entries written to %s", - (int)CFE_EVS_Global.EVS_LogPtr->LogCount, LogFilename); - Result = CFE_SUCCESS; - } else { - EVS_SendEvent(CFE_EVS_ERR_WRLOGFILE_EID, CFE_EVS_EventType_ERROR, - "Write Log File Command Error: OS_write = 0x%08X, filename = %s", - (unsigned int)BytesWritten, LogFilename); + break; } } - OS_close(LogFileHandle); + OS_MutSemGive(CFE_EVS_Global.EVS_SharedDataMutexID); + + /* Process command handler success result */ + if (i == CFE_EVS_Global.EVS_LogPtr->LogCount) + { + EVS_SendEvent(CFE_EVS_WRLOG_EID, CFE_EVS_EventType_DEBUG, + "Write Log File Command: %d event log entries written to %s", + (int)CFE_EVS_Global.EVS_LogPtr->LogCount, LogFilename); + Result = CFE_SUCCESS; + } + else + { + EVS_SendEvent(CFE_EVS_ERR_WRLOGFILE_EID, CFE_EVS_EventType_ERROR, + "Write Log File Command Error: OS_write = 0x%08X, filename = %s", + (unsigned int)BytesWritten, LogFilename); + } } + OS_close(LogFileHandle); } return(Result); @@ -274,35 +260,25 @@ int32 CFE_EVS_SetLogModeCmd(const CFE_EVS_SetLogModeCmd_t *data) const CFE_EVS_SetLogMode_Payload_t *CmdPtr = &data->Payload; int32 Status; - if (CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled == true) + if ((CmdPtr->LogMode == CFE_EVS_LogMode_OVERWRITE) || (CmdPtr->LogMode == CFE_EVS_LogMode_DISCARD)) { - if ((CmdPtr->LogMode == CFE_EVS_LogMode_OVERWRITE) || (CmdPtr->LogMode == CFE_EVS_LogMode_DISCARD)) - { - /* Serialize access to event log control variables */ - OS_MutSemTake(CFE_EVS_Global.EVS_SharedDataMutexID); - CFE_EVS_Global.EVS_LogPtr->LogMode = CmdPtr->LogMode; - OS_MutSemGive(CFE_EVS_Global.EVS_SharedDataMutexID); + /* Serialize access to event log control variables */ + OS_MutSemTake(CFE_EVS_Global.EVS_SharedDataMutexID); + CFE_EVS_Global.EVS_LogPtr->LogMode = CmdPtr->LogMode; + OS_MutSemGive(CFE_EVS_Global.EVS_SharedDataMutexID); - EVS_SendEvent(CFE_EVS_LOGMODE_EID, CFE_EVS_EventType_DEBUG, - "Set Log Mode Command: Log Mode = %d", (int)CmdPtr->LogMode); + EVS_SendEvent(CFE_EVS_LOGMODE_EID, CFE_EVS_EventType_DEBUG, + "Set Log Mode Command: Log Mode = %d", (int)CmdPtr->LogMode); - Status = CFE_SUCCESS; - } - else - { - Status = CFE_EVS_INVALID_PARAMETER; - EVS_SendEvent(CFE_EVS_ERR_LOGMODE_EID, CFE_EVS_EventType_ERROR, - "Set Log Mode Command Error: Log Mode = %d", (int)CmdPtr->LogMode); - } + Status = CFE_SUCCESS; } else { - Status = CFE_EVS_FUNCTION_DISABLED; - EVS_SendEvent(CFE_EVS_NO_LOGSET_EID, CFE_EVS_EventType_ERROR, - "Set Log Mode Command: Event Log is Disabled"); + Status = CFE_EVS_INVALID_PARAMETER; + EVS_SendEvent(CFE_EVS_ERR_LOGMODE_EID, CFE_EVS_EventType_ERROR, + "Set Log Mode Command Error: Log Mode = %d", (int)CmdPtr->LogMode); } - return Status; } /* End CFE_EVS_SetLogModeCmd */ diff --git a/fsw/cfe-core/src/evs/cfe_evs_task.c b/fsw/cfe-core/src/evs/cfe_evs_task.c index 152b8c133..ce6efb091 100644 --- a/fsw/cfe-core/src/evs/cfe_evs_task.c +++ b/fsw/cfe-core/src/evs/cfe_evs_task.c @@ -49,6 +49,8 @@ /* Global Data */ CFE_EVS_Global_t CFE_EVS_Global; +/* Defines */ +#define CFE_EVS_PANIC_DELAY 500 /**< \brief Task delay before PSP panic */ /* ** Local function prototypes. @@ -94,9 +96,16 @@ int32 CFE_EVS_EarlyInit ( void ) /* Get a pointer to the CFE reset area from the BSP */ Status = CFE_PSP_GetResetArea(&resetAreaAddr, &resetAreaSize); + /* Panic on error */ if (Status != CFE_PSP_SUCCESS) { + /* Can't log evs messages without the reset area */ CFE_ES_WriteToSysLog("EVS call to CFE_PSP_GetResetArea failed, RC=0x%08x\n", (unsigned int)Status); + + /* Delay to allow message to be read */ + OS_TaskDelay(CFE_EVS_PANIC_DELAY); + + CFE_PSP_Panic(CFE_PSP_PANIC_MEMORY_ALLOC); } else if (resetAreaSize < sizeof(CFE_ES_ResetData_t)) { @@ -104,8 +113,18 @@ int32 CFE_EVS_EarlyInit ( void ) Status = CFE_EVS_RESET_AREA_POINTER; CFE_ES_WriteToSysLog("Unexpected size from CFE_PSP_GetResetArea: expected = 0x%08lX, actual = 0x%08lX\n", (unsigned long)sizeof(CFE_ES_ResetData_t), (unsigned long)resetAreaSize); + + /* Delay to allow message to be read */ + OS_TaskDelay(CFE_EVS_PANIC_DELAY); + + CFE_PSP_Panic(CFE_PSP_PANIC_MEMORY_ALLOC); } else + { + Status = CFE_SUCCESS; + } + + if (Status == CFE_SUCCESS) { CFE_EVS_ResetDataPtr = (CFE_ES_ResetData_t *)resetAreaAddr; /* Save pointer to the EVS portion of the CFE reset area */ @@ -117,47 +136,58 @@ int32 CFE_EVS_EarlyInit ( void ) if (Status != OS_SUCCESS) { CFE_ES_WriteToSysLog("EVS call to OS_MutSemCreate failed, RC=0x%08x\n", (unsigned int)Status); + + /* Delay to allow message to be read */ + OS_TaskDelay(CFE_EVS_PANIC_DELAY); + + CFE_PSP_Panic(CFE_PSP_PANIC_STARTUP_SEM); } else { - /* Enable access to the EVS event log */ - CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled = true; + Status = CFE_SUCCESS; + } + } - /* Clear event log if power-on reset or bad contents */ - if (CFE_ES_GetResetType(NULL) == CFE_PSP_RST_TYPE_POWERON) - { - CFE_ES_WriteToSysLog("Event Log cleared following power-on reset\n"); - EVS_ClearLog(); - CFE_EVS_Global.EVS_LogPtr->LogMode = CFE_PLATFORM_EVS_DEFAULT_LOG_MODE; - } - else if (((CFE_EVS_Global.EVS_LogPtr->LogMode != CFE_EVS_LogMode_OVERWRITE) && - (CFE_EVS_Global.EVS_LogPtr->LogMode != CFE_EVS_LogMode_DISCARD)) || - ((CFE_EVS_Global.EVS_LogPtr->LogFullFlag != false) && - (CFE_EVS_Global.EVS_LogPtr->LogFullFlag != true)) || - (CFE_EVS_Global.EVS_LogPtr->Next >= CFE_PLATFORM_EVS_LOG_MAX)) - { - CFE_ES_WriteToSysLog("Event Log cleared, n=%d, c=%d, f=%d, m=%d, o=%d\n", - (int)CFE_EVS_Global.EVS_LogPtr->Next, - (int)CFE_EVS_Global.EVS_LogPtr->LogCount, - (int)CFE_EVS_Global.EVS_LogPtr->LogFullFlag, - (int)CFE_EVS_Global.EVS_LogPtr->LogMode, - (int)CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter); - EVS_ClearLog(); - CFE_EVS_Global.EVS_LogPtr->LogMode = CFE_PLATFORM_EVS_DEFAULT_LOG_MODE; - } - else - { - CFE_ES_WriteToSysLog("Event Log restored, n=%d, c=%d, f=%d, m=%d, o=%d\n", - (int)CFE_EVS_Global.EVS_LogPtr->Next, - (int)CFE_EVS_Global.EVS_LogPtr->LogCount, - (int)CFE_EVS_Global.EVS_LogPtr->LogFullFlag, - (int)CFE_EVS_Global.EVS_LogPtr->LogMode, - (int)CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter); - } + if (Status == CFE_SUCCESS) + { + + /* Report log as enabled */ + CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled = true; + + /* Clear event log if power-on reset or bad contents */ + if (CFE_ES_GetResetType(NULL) == CFE_PSP_RST_TYPE_POWERON) + { + CFE_ES_WriteToSysLog("Event Log cleared following power-on reset\n"); + EVS_ClearLog(); + CFE_EVS_Global.EVS_LogPtr->LogMode = CFE_PLATFORM_EVS_DEFAULT_LOG_MODE; + } + else if (((CFE_EVS_Global.EVS_LogPtr->LogMode != CFE_EVS_LogMode_OVERWRITE) && + (CFE_EVS_Global.EVS_LogPtr->LogMode != CFE_EVS_LogMode_DISCARD)) || + ((CFE_EVS_Global.EVS_LogPtr->LogFullFlag != false) && + (CFE_EVS_Global.EVS_LogPtr->LogFullFlag != true)) || + (CFE_EVS_Global.EVS_LogPtr->Next >= CFE_PLATFORM_EVS_LOG_MAX)) + { + CFE_ES_WriteToSysLog("Event Log cleared, n=%d, c=%d, f=%d, m=%d, o=%d\n", + (int)CFE_EVS_Global.EVS_LogPtr->Next, + (int)CFE_EVS_Global.EVS_LogPtr->LogCount, + (int)CFE_EVS_Global.EVS_LogPtr->LogFullFlag, + (int)CFE_EVS_Global.EVS_LogPtr->LogMode, + (int)CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter); + EVS_ClearLog(); + CFE_EVS_Global.EVS_LogPtr->LogMode = CFE_PLATFORM_EVS_DEFAULT_LOG_MODE; + } + else + { + CFE_ES_WriteToSysLog("Event Log restored, n=%d, c=%d, f=%d, m=%d, o=%d\n", + (int)CFE_EVS_Global.EVS_LogPtr->Next, + (int)CFE_EVS_Global.EVS_LogPtr->LogCount, + (int)CFE_EVS_Global.EVS_LogPtr->LogFullFlag, + (int)CFE_EVS_Global.EVS_LogPtr->LogMode, + (int)CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter); } } - return(CFE_SUCCESS); + return(Status); } /* End CFE_EVS_EarlyInit */ @@ -658,20 +688,8 @@ int32 CFE_EVS_NoopCmd(const CFE_EVS_NoopCmd_t *data) */ int32 CFE_EVS_ClearLogCmd(const CFE_EVS_ClearLogCmd_t *data) { - int32 Status; - - if (CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled == true) - { - EVS_ClearLog(); - Status = CFE_SUCCESS; - } - else - { - EVS_SendEvent(CFE_EVS_NO_LOGCLR_EID, CFE_EVS_EventType_ERROR, - "Clear Log Command: Event Log is Disabled"); - Status = CFE_EVS_FUNCTION_DISABLED; - } - return Status; + EVS_ClearLog(); + return CFE_SUCCESS; } /* @@ -690,13 +708,10 @@ int32 CFE_EVS_ReportHousekeepingCmd (const CFE_MSG_CommandHeader_t *data) EVS_AppData_t *AppDataPtr; CFE_EVS_AppTlmData_t *AppTlmDataPtr; - if (CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled == true) - { - /* Copy hk variables that are maintained in the event log */ - CFE_EVS_Global.EVS_TlmPkt.Payload.LogFullFlag = CFE_EVS_Global.EVS_LogPtr->LogFullFlag; - CFE_EVS_Global.EVS_TlmPkt.Payload.LogMode = CFE_EVS_Global.EVS_LogPtr->LogMode; - CFE_EVS_Global.EVS_TlmPkt.Payload.LogOverflowCounter = CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter; - } + /* Copy hk variables that are maintained in the event log */ + CFE_EVS_Global.EVS_TlmPkt.Payload.LogFullFlag = CFE_EVS_Global.EVS_LogPtr->LogFullFlag; + CFE_EVS_Global.EVS_TlmPkt.Payload.LogMode = CFE_EVS_Global.EVS_LogPtr->LogMode; + CFE_EVS_Global.EVS_TlmPkt.Payload.LogOverflowCounter = CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter; /* Write event state data for registered apps to telemetry packet */ AppDataPtr = CFE_EVS_Global.AppData; diff --git a/fsw/cfe-core/src/fs/cfe_fs_api.c b/fsw/cfe-core/src/fs/cfe_fs_api.c index 7638472e9..fd2e9ef5f 100644 --- a/fsw/cfe-core/src/fs/cfe_fs_api.c +++ b/fsw/cfe-core/src/fs/cfe_fs_api.c @@ -42,6 +42,74 @@ #include "cfe_es.h" #include +/* The target config allows refs into global CONFIGDATA object(s) */ +#include "target_config.h" + + +/* + * Fixed default file system extensions (not platform dependent) + */ +const char CFE_FS_DEFAULT_SCRIPT_EXTENSION[] = ".scr"; +const char CFE_FS_DEFAULT_DUMP_FILE_EXTENSION[] = ".dat"; +const char CFE_FS_DEFAULT_TEMP_FILE_EXTENSION[] = ".tmp"; +const char CFE_FS_DEFAULT_LOG_FILE_EXTENSION[] = ".log"; + + +const char *CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_t FileCategory) +{ + const char *Result; + + switch(FileCategory) + { + case CFE_FS_FileCategory_SCRIPT: + case CFE_FS_FileCategory_DYNAMIC_MODULE: + /* scripts and app/lib modules reside in the non-volatile/CF mount by default */ + Result = GLOBAL_CFE_CONFIGDATA.NonvolMountPoint; + break; + case CFE_FS_FileCategory_TEMP: + case CFE_FS_FileCategory_BINARY_DATA_DUMP: + case CFE_FS_FileCategory_TEXT_LOG: + /* temporary and data dump files are put in the RAM DISK mount by default */ + Result = GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint; + break; + default: + Result = NULL; /* Should not be used */ + break; + } + + return Result; +} + +const char *CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_t FileCategory) +{ + const char *Result; + + switch(FileCategory) + { + case CFE_FS_FileCategory_SCRIPT: + Result = CFE_FS_DEFAULT_SCRIPT_EXTENSION; + break; + case CFE_FS_FileCategory_DYNAMIC_MODULE: + /* app/lib modules use a platform-specific extension, and the + * default is derived from the build system */ + Result = GLOBAL_CONFIGDATA.Default_ModuleExtension; + break; + case CFE_FS_FileCategory_TEMP: + Result = CFE_FS_DEFAULT_TEMP_FILE_EXTENSION; + break; + case CFE_FS_FileCategory_BINARY_DATA_DUMP: + Result = CFE_FS_DEFAULT_DUMP_FILE_EXTENSION; + break; + case CFE_FS_FileCategory_TEXT_LOG: + Result = CFE_FS_DEFAULT_LOG_FILE_EXTENSION; + break; + default: + Result = NULL; /* Should not be used */ + break; + } + + return Result; +} /* ** CFE_FS_ReadHeader() - See API and header file for details @@ -50,6 +118,11 @@ int32 CFE_FS_ReadHeader(CFE_FS_Header_t *Hdr, osal_id_t FileDes) { int32 Result; int32 EndianCheck = 0x01020304; + + if (Hdr == NULL) + { + return CFE_FS_BAD_ARGUMENT; + } /* ** Ensure that we are at the start of the file... @@ -81,9 +154,16 @@ int32 CFE_FS_ReadHeader(CFE_FS_Header_t *Hdr, osal_id_t FileDes) */ void CFE_FS_InitHeader(CFE_FS_Header_t *Hdr, const char *Description, uint32 SubType) { - memset(Hdr, 0, sizeof(CFE_FS_Header_t)); - strncpy((char *)Hdr->Description, Description, sizeof(Hdr->Description) - 1); - Hdr->SubType = SubType; + if(Hdr == NULL || Description == NULL) + { + CFE_ES_WriteToSysLog("CFE_FS:InitHeader-Failed invalid arguments\n"); + } + else + { + memset(Hdr, 0, sizeof(CFE_FS_Header_t)); + strncpy((char *)Hdr->Description, Description, sizeof(Hdr->Description) - 1); + Hdr->SubType = SubType; + } } /* @@ -96,6 +176,11 @@ int32 CFE_FS_WriteHeader(osal_id_t FileDes, CFE_FS_Header_t *Hdr) int32 EndianCheck = 0x01020304; CFE_ES_AppId_t AppID; + if (Hdr == NULL) + { + return CFE_FS_BAD_ARGUMENT; + } + /* ** Ensure that we are at the start of the file... */ @@ -252,6 +337,236 @@ void CFE_FS_ByteSwapUint32(uint32 *Uint32ToSwapPtr) OutPtr[3] = InPtr[0]; } /* End of CFE_FS_ByteSwapUint32() */ +/* +**--------------------------------------------------------------------------------------- +** Name: CFE_FS_ParseInputFileNameEx +** +** Purpose: This reads a file name from user input with extra logic to make more user friendly +** - absolute path is optional; assume default dir if missing +** - module extension is optional; append default for OS/platform if missing +**--------------------------------------------------------------------------------------- +*/ +int32 CFE_FS_ParseInputFileNameEx(char *OutputBuffer, const char *InputBuffer, size_t OutputBufSize, size_t InputBufSize, + const char *DefaultInput, const char *DefaultPath, const char *DefaultExtension) +{ + int32 Status; + const char *InputPtr; + const char *ComponentPtr; + size_t ComponentLen; + char ComponentTerm; + size_t OutputLen; + size_t InputLen; + bool LastPathReached; + + /* The filename consists of a pathname, filename, and extension component. */ + enum + { + PROCESS_INIT, + PATHNAME_COMPONENT, + PATHNAME_SEPARATOR, + FILENAME_COMPONENT, + EXTENSION_SEPARATOR, + EXTENSION_COMPONENT, + END_COMPONENT + } Component; + + /* Sanity check buffer input */ + if (OutputBuffer == NULL || OutputBufSize == 0) + { + return CFE_FS_BAD_ARGUMENT; + } + + Status = CFE_FS_INVALID_PATH; + OutputLen = 0; + ComponentTerm = 0; + LastPathReached = false; + + /* If input buffer is not empty, then use it, otherwise use DefaultInput */ + if (InputBuffer != NULL && InputBufSize > 0 && InputBuffer[0] != 0) + { + InputPtr = InputBuffer; + InputLen = InputBufSize; + } + else if (DefaultInput != NULL) + { + /* This must be a normal null terminated string */ + InputPtr = DefaultInput; + InputLen = strlen(DefaultInput); + } + else + { + /* No input */ + InputPtr = NULL; + InputLen = 0; + } + + Component = PROCESS_INIT; + while (InputPtr != NULL && Component < END_COMPONENT) + { + /* Move to next component */ + if (Component == PATHNAME_SEPARATOR && !LastPathReached) + { + /* repeat until LastPathReached */ + Component = PATHNAME_COMPONENT; + } + else + { + ++Component; + } + + switch(Component) + { + case PATHNAME_COMPONENT: + /* path part ends with the last / char, which begins the filename */ + ComponentTerm = '/'; + ComponentPtr = memchr(InputPtr, ComponentTerm, InputLen); + if (ComponentPtr != NULL) + { + /* has path: use pathname from input, advance InputPtr to next part (filename) */ + ComponentLen = ComponentPtr - InputPtr; + ComponentPtr = InputPtr; + InputPtr += ComponentLen; + InputLen -= ComponentLen; + } + else + { + LastPathReached = true; + + /* no path: if no output at all yet, use default pathname, otherwise move on. */ + if (DefaultPath != NULL && OutputLen == 0) + { + ComponentLen = strlen(DefaultPath); + ComponentPtr = DefaultPath; + } + else + { + /* use no pathname at all */ + ComponentLen = 0; + ComponentPtr = NULL; + } + } + break; + + case FILENAME_COMPONENT: + /* filename ends with a . char, which begins the extension */ + ComponentTerm = '.'; + ComponentPtr = memchr(InputPtr, ComponentTerm, InputLen); + if (ComponentPtr != NULL) + { + /* has ext: use pathname from input, advance InputPtr to next part (extension) */ + ComponentLen = ComponentPtr - InputPtr; + ComponentPtr = InputPtr; + InputPtr += ComponentLen; + InputLen -= ComponentLen; + } + else + { + /* no ext: use remainder of input here - then use default extension for next part */ + ComponentLen = InputLen; + ComponentPtr = InputPtr; + if (DefaultExtension != NULL) + { + InputPtr = DefaultExtension; + InputLen = strlen(DefaultExtension); + } + else + { + /* Use no extension */ + InputPtr = NULL; + InputLen = 0; + } + } + + if (ComponentLen > 0 && *ComponentPtr != 0) + { + /* + * If the filename part is non-empty, then consider the conversion successful + * (note that extension is not really needed for an acceptable filename) + */ + Status = CFE_SUCCESS; + } + + break; + + case PATHNAME_SEPARATOR: + case EXTENSION_SEPARATOR: + /* Remove duplicate terminators that may have been in the input */ + while (OutputLen > 0 && OutputBuffer[OutputLen-1] == ComponentTerm) + { + --OutputLen; + } + + ComponentLen = 1; + ComponentPtr = &ComponentTerm; + + /* advance past any separators in input to get to the next content */ + while (*InputPtr == ComponentTerm && InputLen > 0) + { + ++InputPtr; + --InputLen; + } + break; + + + case EXTENSION_COMPONENT: + /* Intentional fall through to default case */ + + default: + /* Just consume the rest of input - + * should already be pointing to correct data */ + ComponentTerm = 0; + ComponentLen = InputLen; + ComponentPtr = InputPtr; + InputPtr = NULL; /* no more input */ + InputLen = 0; + break; + } + + /* Append component */ + while(ComponentLen > 0 && *ComponentPtr != 0) + { + OutputBuffer[OutputLen] = *ComponentPtr; + ++ComponentPtr; + ++OutputLen; + --ComponentLen; + + if (OutputLen >= OutputBufSize) + { + /* name is too long to fit in output buffer */ + Status = CFE_FS_FNAME_TOO_LONG; + InputPtr = NULL; /* no more input */ + InputLen = 0; + --OutputLen; /* back up one char for term */ + break; + } + } + } + + /* + * Always add a final terminating NUL char. + * + * Note that the loop above should never entirely fill + * buffer (length check includes extra char). + */ + OutputBuffer[OutputLen] = 0; + + return Status; +} + +/* +**--------------------------------------------------------------------------------------- +** Name: CFE_FS_ParseInputFileName +** +** Purpose: Simplified API for CFE_FS_ParseInputFileNameEx where input is always known to be +** a non-empty, null terminated string and the fixed-length input buffer not needed. +**--------------------------------------------------------------------------------------- +*/ +int32 CFE_FS_ParseInputFileName(char *OutputBuffer, const char *InputName, size_t OutputBufSize, CFE_FS_FileCategory_t FileCategory) +{ + return CFE_FS_ParseInputFileNameEx(OutputBuffer, NULL, OutputBufSize, 0, InputName, + CFE_FS_GetDefaultMountPoint(FileCategory), CFE_FS_GetDefaultExtension(FileCategory)); +} + /* ** CFE_FS_ExtractFilenameFromPath - See API and header file for details diff --git a/fsw/cfe-core/src/inc/cfe_error.h b/fsw/cfe-core/src/inc/cfe_error.h index 98b82dc26..657bbc98b 100644 --- a/fsw/cfe-core/src/inc/cfe_error.h +++ b/fsw/cfe-core/src/inc/cfe_error.h @@ -87,28 +87,27 @@ typedef int32 CFE_Status_t; ** Code - is the status code */ - /* ** Error Severity */ -#define CFE_SEVERITY_BITMASK ((int32)0xc0000000) /**< @brief Error Severity Bitmask */ +#define CFE_SEVERITY_BITMASK ((CFE_Status_t)0xc0000000) /**< @brief Error Severity Bitmask */ -#define CFE_SEVERITY_SUCCESS ((int32)0x00000000) /**< @brief Severity Success */ -#define CFE_SEVERITY_INFO ((int32)0x40000000) /**< @brief Severity Info */ -#define CFE_SEVERITY_ERROR ((int32)0xc0000000) /**< @brief Severity Error */ +#define CFE_SEVERITY_SUCCESS ((CFE_Status_t)0x00000000) /**< @brief Severity Success */ +#define CFE_SEVERITY_INFO ((CFE_Status_t)0x40000000) /**< @brief Severity Info */ +#define CFE_SEVERITY_ERROR ((CFE_Status_t)0xc0000000) /**< @brief Severity Error */ /* ** cFE Service Identifiers */ -#define CFE_SERVICE_BITMASK ((int32)0x0e000000) /**< @brief Error Service Bitmask */ +#define CFE_SERVICE_BITMASK ((CFE_Status_t)0x0e000000) /**< @brief Error Service Bitmask */ -#define CFE_EVENTS_SERVICE ((int32)0x02000000) /**< @brief Event Service */ -#define CFE_EXECUTIVE_SERVICE ((int32)0x04000000) /**< @brief Executive Service */ -#define CFE_FILE_SERVICE ((int32)0x06000000) /**< @brief File Service */ -#define CFE_GENERIC_SERVICE ((int32)0x08000000) /**< @brief Generic Service */ -#define CFE_SOFTWARE_BUS_SERVICE ((int32)0x0a000000) /**< @brief Software Bus Service */ -#define CFE_TABLE_SERVICE ((int32)0x0c000000) /**< @brief Table Service */ -#define CFE_TIME_SERVICE ((int32)0x0e000000) /**< @brief Time Service */ +#define CFE_EVENTS_SERVICE ((CFE_Status_t)0x02000000) /**< @brief Event Service */ +#define CFE_EXECUTIVE_SERVICE ((CFE_Status_t)0x04000000) /**< @brief Executive Service */ +#define CFE_FILE_SERVICE ((CFE_Status_t)0x06000000) /**< @brief File Service */ +#define CFE_GENERIC_SERVICE ((CFE_Status_t)0x08000000) /**< @brief Generic Service */ +#define CFE_SOFTWARE_BUS_SERVICE ((CFE_Status_t)0x0a000000) /**< @brief Software Bus Service */ +#define CFE_TABLE_SERVICE ((CFE_Status_t)0x0c000000) /**< @brief Table Service */ +#define CFE_TIME_SERVICE ((CFE_Status_t)0x0e000000) /**< @brief Time Service */ /* ************* COMMON STATUS CODES ************* @@ -123,7 +122,7 @@ typedef int32 CFE_Status_t; * * Operation was performed successfully */ -#define CFE_SUCCESS (0) +#define CFE_SUCCESS (0) /** * @brief No Counter Increment @@ -131,7 +130,7 @@ typedef int32 CFE_Status_t; * Informational code indicating that a command was processed * successfully but that the command counter should _not_ be incremented. */ -#define CFE_STATUS_NO_COUNTER_INCREMENT ((int32)0x48000001) +#define CFE_STATUS_NO_COUNTER_INCREMENT ((CFE_Status_t)0x48000001) /** * @brief Wrong Message Length @@ -140,7 +139,7 @@ typedef int32 CFE_Status_t; * determined that the message length is incorrect * */ -#define CFE_STATUS_WRONG_MSG_LENGTH ((int32)0xc8000002) +#define CFE_STATUS_WRONG_MSG_LENGTH ((CFE_Status_t)0xc8000002) /** * @brief Unknown Message ID @@ -149,7 +148,7 @@ typedef int32 CFE_Status_t; * determined that the message ID does not correspond to a known value * */ -#define CFE_STATUS_UNKNOWN_MSG_ID ((int32)0xc8000003) +#define CFE_STATUS_UNKNOWN_MSG_ID ((CFE_Status_t)0xc8000003) /** * @brief Bad Command Code @@ -158,7 +157,7 @@ typedef int32 CFE_Status_t; * determined that the command code is does not correspond to any known value * */ -#define CFE_STATUS_BAD_COMMAND_CODE ((int32)0xc8000004) +#define CFE_STATUS_BAD_COMMAND_CODE ((CFE_Status_t)0xc8000004) /** * @brief External failure @@ -170,7 +169,7 @@ typedef int32 CFE_Status_t; * Details of the original failure should be written to syslog * and/or a system event before returning this error. */ -#define CFE_STATUS_EXTERNAL_RESOURCE_FAIL ((int32)0xc8000005) +#define CFE_STATUS_EXTERNAL_RESOURCE_FAIL ((CFE_Status_t)0xc8000005) /** * @brief Request already pending @@ -190,10 +189,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_STATUS_NOT_IMPLEMENTED ((int32)0xc800ffff) - - - +#define CFE_STATUS_NOT_IMPLEMENTED ((CFE_Status_t)0xc800ffff) /* ************* EVENTS SERVICES STATUS CODES ************* @@ -205,7 +201,7 @@ typedef int32 CFE_Status_t; * #CFE_EVS_Register FilterScheme parameter was illegal * */ -#define CFE_EVS_UNKNOWN_FILTER ((int32)0xc2000001) +#define CFE_EVS_UNKNOWN_FILTER ((CFE_Status_t)0xc2000001) /** * @brief Application Not Registered @@ -213,7 +209,7 @@ typedef int32 CFE_Status_t; * Calling application never previously called #CFE_EVS_Register * */ -#define CFE_EVS_APP_NOT_REGISTERED ((int32)0xc2000002) +#define CFE_EVS_APP_NOT_REGISTERED ((CFE_Status_t)0xc2000002) /** * @brief Illegal Application ID @@ -222,7 +218,7 @@ typedef int32 CFE_Status_t; * than #CFE_PLATFORM_ES_MAX_APPLICATIONS * */ -#define CFE_EVS_APP_ILLEGAL_APP_ID ((int32)0xc2000003) +#define CFE_EVS_APP_ILLEGAL_APP_ID ((CFE_Status_t)0xc2000003) /** * @brief Application Filter Overload @@ -231,7 +227,7 @@ typedef int32 CFE_Status_t; * registration is greater than #CFE_PLATFORM_EVS_MAX_EVENT_FILTERS * */ -#define CFE_EVS_APP_FILTER_OVERLOAD ((int32)0xc2000004) +#define CFE_EVS_APP_FILTER_OVERLOAD ((CFE_Status_t)0xc2000004) /** * @brief Reset Area Pointer Failure @@ -240,8 +236,7 @@ typedef int32 CFE_Status_t; * not get the pointer to the EVS Log. * */ -#define CFE_EVS_RESET_AREA_POINTER ((int32)0xc2000005) - +#define CFE_EVS_RESET_AREA_POINTER ((CFE_Status_t)0xc2000005) /** * @brief Event Not Registered @@ -250,7 +245,7 @@ typedef int32 CFE_Status_t; * any event filter registered by the calling application. * */ -#define CFE_EVS_EVT_NOT_REGISTERED ((int32)0xc2000006) +#define CFE_EVS_EVT_NOT_REGISTERED ((CFE_Status_t)0xc2000006) /** * @brief File Write Error @@ -258,7 +253,7 @@ typedef int32 CFE_Status_t; * A file write error occurred while processing an EVS command * */ -#define CFE_EVS_FILE_WRITE_ERROR ((int32)0xc2000007) +#define CFE_EVS_FILE_WRITE_ERROR ((CFE_Status_t)0xc2000007) /** * @brief Invalid Pointer @@ -266,16 +261,7 @@ typedef int32 CFE_Status_t; * Invalid parameter supplied to EVS command * */ -#define CFE_EVS_INVALID_PARAMETER ((int32)0xc2000008) - -/** - * @brief Function Disabled - * - * EVS command sent that requires a feature currently turned off - * This is to differentiate between "NOT_IMPLEMENTED" where the - * feature IS implemented but it is disabled at runtime. - */ -#define CFE_EVS_FUNCTION_DISABLED ((int32)0xc2000009) +#define CFE_EVS_INVALID_PARAMETER ((CFE_Status_t)0xc2000008) /** * @brief Not Implemented @@ -286,7 +272,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_EVS_NOT_IMPLEMENTED ((int32)0xc200ffff) +#define CFE_EVS_NOT_IMPLEMENTED ((CFE_Status_t)0xc200ffff) /* ************* EXECUTIVE SERVICES STATUS CODES ************* @@ -299,7 +285,7 @@ typedef int32 CFE_Status_t; * (App ID, Lib ID, Counter ID, etc) did not validate. * */ -#define CFE_ES_ERR_RESOURCEID_NOT_VALID ((int32)0xc4000001) +#define CFE_ES_ERR_RESOURCEID_NOT_VALID ((CFE_Status_t)0xc4000001) /** * @brief Resource Name Error @@ -307,7 +293,7 @@ typedef int32 CFE_Status_t; * There is no match in the system for the given name. * */ -#define CFE_ES_ERR_NAME_NOT_FOUND ((int32)0xc4000002) +#define CFE_ES_ERR_NAME_NOT_FOUND ((CFE_Status_t)0xc4000002) /** * @brief Invalid Pointer @@ -315,7 +301,7 @@ typedef int32 CFE_Status_t; * Invalid pointer argument (NULL) * */ -#define CFE_ES_ERR_BUFFER ((int32)0xc4000003) +#define CFE_ES_ERR_BUFFER ((CFE_Status_t)0xc4000003) /** * @brief Application Create Error @@ -323,7 +309,7 @@ typedef int32 CFE_Status_t; * There was an error loading or creating the App. * */ -#define CFE_ES_ERR_APP_CREATE ((int32)0xc4000004) +#define CFE_ES_ERR_APP_CREATE ((CFE_Status_t)0xc4000004) /** * @brief Child Task Create Error @@ -331,7 +317,7 @@ typedef int32 CFE_Status_t; * There was an error creating a child task. * */ -#define CFE_ES_ERR_CHILD_TASK_CREATE ((int32)0xc4000005) +#define CFE_ES_ERR_CHILD_TASK_CREATE ((CFE_Status_t)0xc4000005) /** * @brief System Log Full @@ -340,7 +326,7 @@ typedef int32 CFE_Status_t; * This error means the message was not logged at all * */ -#define CFE_ES_ERR_SYS_LOG_FULL ((int32)0xc4000006) +#define CFE_ES_ERR_SYS_LOG_FULL ((CFE_Status_t)0xc4000006) /** * @brief Memory Block Size Error @@ -348,7 +334,7 @@ typedef int32 CFE_Status_t; * The block size requested is invalid. * */ -#define CFE_ES_ERR_MEM_BLOCK_SIZE ((int32)0xc4000008) +#define CFE_ES_ERR_MEM_BLOCK_SIZE ((CFE_Status_t)0xc4000008) /** * @brief Load Library Error @@ -356,7 +342,7 @@ typedef int32 CFE_Status_t; * Could not load the shared library. * */ -#define CFE_ES_ERR_LOAD_LIB ((int32)0xc4000009) +#define CFE_ES_ERR_LOAD_LIB ((CFE_Status_t)0xc4000009) /** * @brief Bad Argument @@ -364,7 +350,7 @@ typedef int32 CFE_Status_t; * Bad parameter passed into an ES API. * */ -#define CFE_ES_BAD_ARGUMENT ((int32)0xc400000a) +#define CFE_ES_BAD_ARGUMENT ((CFE_Status_t)0xc400000a) /** * @brief Child Task Register Error @@ -372,7 +358,7 @@ typedef int32 CFE_Status_t; * Errors occured when trying to register a child task. * */ -#define CFE_ES_ERR_CHILD_TASK_REGISTER ((int32)0xc400000b) +#define CFE_ES_ERR_CHILD_TASK_REGISTER ((CFE_Status_t)0xc400000b) /** * @brief Shell Command Error @@ -380,7 +366,7 @@ typedef int32 CFE_Status_t; * Error occured ehen trying to pass a system call to the OS shell * */ -#define CFE_ES_ERR_SHELL_CMD ((int32)0xc400000c) +#define CFE_ES_ERR_SHELL_CMD ((CFE_Status_t)0xc400000c) /** * @brief CDS Already Exists @@ -388,8 +374,7 @@ typedef int32 CFE_Status_t; * The Application is receiving the pointer to a CDS that was already present. * */ -#define CFE_ES_CDS_ALREADY_EXISTS ((int32)0x4400000d) - +#define CFE_ES_CDS_ALREADY_EXISTS ((CFE_Status_t)0x4400000d) /** * @brief CDS Insufficient Memory @@ -398,8 +383,7 @@ typedef int32 CFE_Status_t; * CDS memory. * */ -#define CFE_ES_CDS_INSUFFICIENT_MEMORY ((int32)0xc400000e) - +#define CFE_ES_CDS_INSUFFICIENT_MEMORY ((CFE_Status_t)0xc400000e) /** * @brief CDS Invalid Name @@ -408,8 +392,7 @@ typedef int32 CFE_Status_t; * Either the name is too long (> #CFE_MISSION_ES_CDS_MAX_NAME_LENGTH) or was an empty string. * */ -#define CFE_ES_CDS_INVALID_NAME ((int32)0xc400000f) - +#define CFE_ES_CDS_INVALID_NAME ((CFE_Status_t)0xc400000f) /** * @brief CDS Invalid Size @@ -418,8 +401,7 @@ typedef int32 CFE_Status_t; * beyond the applicable limits, either too large or too small/zero. * */ -#define CFE_ES_CDS_INVALID_SIZE ((int32)0xc4000010) - +#define CFE_ES_CDS_INVALID_SIZE ((CFE_Status_t)0xc4000010) /** * @brief CDS Invalid @@ -427,8 +409,7 @@ typedef int32 CFE_Status_t; * The CDS contents are invalid. * */ -#define CFE_ES_CDS_INVALID ((int32)0xc4000012) - +#define CFE_ES_CDS_INVALID ((CFE_Status_t)0xc4000012) /** * @brief CDS Access Error @@ -436,8 +417,7 @@ typedef int32 CFE_Status_t; * The CDS was inaccessible * */ -#define CFE_ES_CDS_ACCESS_ERROR ((int32)0xc4000013) - +#define CFE_ES_CDS_ACCESS_ERROR ((CFE_Status_t)0xc4000013) /** * @brief File IO Error @@ -445,8 +425,7 @@ typedef int32 CFE_Status_t; * Occurs when a file operation fails * */ -#define CFE_ES_FILE_IO_ERR ((int32)0xc4000014) - +#define CFE_ES_FILE_IO_ERR ((CFE_Status_t)0xc4000014) /** * @brief Reset Area Access Error @@ -454,7 +433,7 @@ typedef int32 CFE_Status_t; * Occurs when the BSP is not successful in returning the reset area address. * */ -#define CFE_ES_RST_ACCESS_ERR ((int32)0xc4000015) +#define CFE_ES_RST_ACCESS_ERR ((CFE_Status_t)0xc4000015) /** * @brief Application Register Error @@ -462,7 +441,7 @@ typedef int32 CFE_Status_t; * Occurs when the #CFE_ES_RegisterApp fails. * */ -#define CFE_ES_ERR_APP_REGISTER ((int32)0xc4000017) +#define CFE_ES_ERR_APP_REGISTER ((CFE_Status_t)0xc4000017) /** * @brief Child Task Delete Error @@ -470,7 +449,7 @@ typedef int32 CFE_Status_t; * There was an error deleting a child task. * */ -#define CFE_ES_ERR_CHILD_TASK_DELETE ((int32)0xc4000018) +#define CFE_ES_ERR_CHILD_TASK_DELETE ((CFE_Status_t)0xc4000018) /** * @brief Child Task Delete Passed Main Task @@ -479,7 +458,7 @@ typedef int32 CFE_Status_t; * the #CFE_ES_DeleteChildTask API. * */ -#define CFE_ES_ERR_CHILD_TASK_DELETE_MAIN_TASK ((int32)0xc4000019) +#define CFE_ES_ERR_CHILD_TASK_DELETE_MAIN_TASK ((CFE_Status_t)0xc4000019) /** * @brief CDS Block CRC Error @@ -489,7 +468,7 @@ typedef int32 CFE_Status_t; * the CDS Data Block are corrupted or the CDS Control Block is corrupted. * */ -#define CFE_ES_CDS_BLOCK_CRC_ERR ((int32)0xc400001A) +#define CFE_ES_CDS_BLOCK_CRC_ERR ((CFE_Status_t)0xc400001A) /** * @brief Mutex Semaphore Delete Error @@ -498,8 +477,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_MUT_SEM_DELETE_ERR ((int32)0xc400001B) - +#define CFE_ES_MUT_SEM_DELETE_ERR ((CFE_Status_t)0xc400001B) /** * @brief Binary Semaphore Delete Error @@ -508,7 +486,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_BIN_SEM_DELETE_ERR ((int32)0xc400001C) +#define CFE_ES_BIN_SEM_DELETE_ERR ((CFE_Status_t)0xc400001C) /** * @brief Counte Semaphore Delete Error @@ -517,7 +495,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_COUNT_SEM_DELETE_ERR ((int32)0xc400001D) +#define CFE_ES_COUNT_SEM_DELETE_ERR ((CFE_Status_t)0xc400001D) /** * @brief Queue Delete Error @@ -526,7 +504,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_QUEUE_DELETE_ERR ((int32)0xc400001E) +#define CFE_ES_QUEUE_DELETE_ERR ((CFE_Status_t)0xc400001E) /** * @brief File Close Error @@ -535,7 +513,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_FILE_CLOSE_ERR ((int32)0xc400001F) +#define CFE_ES_FILE_CLOSE_ERR ((CFE_Status_t)0xc400001F) /** * @brief CDS Wrong Type Error @@ -545,7 +523,7 @@ typedef int32 CFE_Status_t; * a Critical Table Image. * */ -#define CFE_ES_CDS_WRONG_TYPE_ERR ((int32)0xc4000020) +#define CFE_ES_CDS_WRONG_TYPE_ERR ((CFE_Status_t)0xc4000020) /** * @brief CDS Owner Active Error @@ -556,8 +534,7 @@ typedef int32 CFE_Status_t; * in the system. * */ -#define CFE_ES_CDS_OWNER_ACTIVE_ERR ((int32)0xc4000022) - +#define CFE_ES_CDS_OWNER_ACTIVE_ERR ((CFE_Status_t)0xc4000022) /** * @brief Application Cleanup Error @@ -570,7 +547,7 @@ typedef int32 CFE_Status_t; * each problem. * */ -#define CFE_ES_APP_CLEANUP_ERR ((int32)0xc4000023) +#define CFE_ES_APP_CLEANUP_ERR ((CFE_Status_t)0xc4000023) /** * @brief Timer Delete Error @@ -579,7 +556,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_TIMER_DELETE_ERR ((int32)0xc4000024) +#define CFE_ES_TIMER_DELETE_ERR ((CFE_Status_t)0xc4000024) /** * @brief Buffer Not In Pool @@ -587,8 +564,7 @@ typedef int32 CFE_Status_t; * The specified address is not in the memory pool. * */ -#define CFE_ES_BUFFER_NOT_IN_POOL ((int32)0xc4000025) - +#define CFE_ES_BUFFER_NOT_IN_POOL ((CFE_Status_t)0xc4000025) /** * @brief Task Delete Error @@ -597,7 +573,7 @@ typedef int32 CFE_Status_t; * is cleaning up. * */ -#define CFE_ES_TASK_DELETE_ERR ((int32)0xc4000026) +#define CFE_ES_TASK_DELETE_ERR ((CFE_Status_t)0xc4000026) /** * @brief Operation Timed Out @@ -605,7 +581,7 @@ typedef int32 CFE_Status_t; * Occurs if the timeout for a given operation was exceeded * */ -#define CFE_ES_OPERATION_TIMED_OUT ((int32)0xc4000027) +#define CFE_ES_OPERATION_TIMED_OUT ((CFE_Status_t)0xc4000027) /** * @brief Library Already Loaded @@ -614,8 +590,7 @@ typedef int32 CFE_Status_t; * library name is already loaded. * */ -#define CFE_ES_LIB_ALREADY_LOADED ((int32)0x44000028) - +#define CFE_ES_LIB_ALREADY_LOADED ((CFE_Status_t)0x44000028) /** * @brief System Log Message Truncated @@ -624,8 +599,7 @@ typedef int32 CFE_Status_t; * due to insufficient space in the log buffer. * */ -#define CFE_ES_ERR_SYS_LOG_TRUNCATED ((int32)0x44000029) - +#define CFE_ES_ERR_SYS_LOG_TRUNCATED ((CFE_Status_t)0x44000029) /** * @brief Resource ID is not available @@ -635,7 +609,7 @@ typedef int32 CFE_Status_t; * and a new ID cannot be allocated. * */ -#define CFE_ES_NO_RESOURCE_IDS_AVAILABLE ((int32)0xc400002B) +#define CFE_ES_NO_RESOURCE_IDS_AVAILABLE ((CFE_Status_t)0xc400002B) /** * @brief Invalid pool block @@ -645,7 +619,7 @@ typedef int32 CFE_Status_t; * pool has become unusable due to memory corruption. * */ -#define CFE_ES_POOL_BLOCK_INVALID ((int32)0xc400002C) +#define CFE_ES_POOL_BLOCK_INVALID ((CFE_Status_t)0xc400002C) /** * @brief Invalid pool size or buffer address @@ -654,8 +628,7 @@ typedef int32 CFE_Status_t; * bounds for that pool configuration. * */ -#define CFE_ES_POOL_BOUNDS_ERROR ((int32)0xc400002D) - +#define CFE_ES_POOL_BOUNDS_ERROR ((CFE_Status_t)0xc400002D) /** * @brief Duplicate Name Error @@ -663,7 +636,7 @@ typedef int32 CFE_Status_t; * Resource creation failed due to the name already existing in the system. * */ -#define CFE_ES_ERR_DUPLICATE_NAME ((int32)0xc400002E) +#define CFE_ES_ERR_DUPLICATE_NAME ((CFE_Status_t)0xc400002E) /** * @brief Not Implemented @@ -674,8 +647,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_ES_NOT_IMPLEMENTED ((int32)0xc400ffff) - +#define CFE_ES_NOT_IMPLEMENTED ((CFE_Status_t)0xc400ffff) /* ************* FILE SERVICES STATUS CODES ************* @@ -688,7 +660,7 @@ typedef int32 CFE_Status_t; * validation checks. * */ -#define CFE_FS_BAD_ARGUMENT ((int32)0xc6000001) +#define CFE_FS_BAD_ARGUMENT ((CFE_Status_t)0xc6000001) /** * @brief Invalid Path @@ -696,7 +668,7 @@ typedef int32 CFE_Status_t; * FS was unable to extract a filename from a path string * */ -#define CFE_FS_INVALID_PATH ((int32)0xc6000002) +#define CFE_FS_INVALID_PATH ((CFE_Status_t)0xc6000002) /** * @brief Filename Too Long @@ -704,8 +676,7 @@ typedef int32 CFE_Status_t; * FS filename string is too long * */ -#define CFE_FS_FNAME_TOO_LONG ((int32)0xc6000003) - +#define CFE_FS_FNAME_TOO_LONG ((CFE_Status_t)0xc6000003) /** * @brief Not Implemented @@ -716,8 +687,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_FS_NOT_IMPLEMENTED ((int32)0xc600ffff) - +#define CFE_FS_NOT_IMPLEMENTED ((CFE_Status_t)0xc600ffff) /* ************* SOFTWARE BUS SERVICES STATUS CODES ************* @@ -730,8 +700,7 @@ typedef int32 CFE_Status_t; * been received in the time given in the "timeout" parameter. * */ -#define CFE_SB_TIME_OUT ((int32)0xca000001) - +#define CFE_SB_TIME_OUT ((CFE_Status_t)0xca000001) /** * @brief No Message @@ -740,8 +709,7 @@ typedef int32 CFE_Status_t; * value indicates that there was not a message on the pipe. * */ -#define CFE_SB_NO_MESSAGE ((int32)0xca000002) - +#define CFE_SB_NO_MESSAGE ((CFE_Status_t)0xca000002) /** * @brief Bad Argument @@ -750,8 +718,7 @@ typedef int32 CFE_Status_t; * validation checks. * */ -#define CFE_SB_BAD_ARGUMENT ((int32)0xca000003) - +#define CFE_SB_BAD_ARGUMENT ((CFE_Status_t)0xca000003) /** * @brief Max Pipes Met @@ -762,8 +729,7 @@ typedef int32 CFE_Status_t; * parameter is defined in the cfe_platform_cfg.h file. * */ -#define CFE_SB_MAX_PIPES_MET ((int32)0xca000004) - +#define CFE_SB_MAX_PIPES_MET ((CFE_Status_t)0xca000004) /** * @brief Pipe Create Error @@ -774,8 +740,7 @@ typedef int32 CFE_Status_t; * code displayed in the event must be tracked. * */ -#define CFE_SB_PIPE_CR_ERR ((int32)0xca000005) - +#define CFE_SB_PIPE_CR_ERR ((CFE_Status_t)0xca000005) /** * @brief Pipe Read Error @@ -788,8 +753,7 @@ typedef int32 CFE_Status_t; * will be caught by higher level code in the Software Bus. * */ -#define CFE_SB_PIPE_RD_ERR ((int32)0xca000006) - +#define CFE_SB_PIPE_RD_ERR ((CFE_Status_t)0xca000006) /** * @brief Message Too Big @@ -799,8 +763,7 @@ typedef int32 CFE_Status_t; * configuration parameter #CFE_MISSION_SB_MAX_SB_MSG_SIZE in cfe_mission_cfg.h * */ -#define CFE_SB_MSG_TOO_BIG ((int32)0xca000007) - +#define CFE_SB_MSG_TOO_BIG ((CFE_Status_t)0xca000007) /** * @brief Buffer Allocation Error @@ -813,8 +776,7 @@ typedef int32 CFE_Status_t; * a Software Bus command to send the SB statistics packet. * */ -#define CFE_SB_BUF_ALOC_ERR ((int32)0xca000008) - +#define CFE_SB_BUF_ALOC_ERR ((CFE_Status_t)0xca000008) /** * @brief Max Messages Met @@ -824,8 +786,7 @@ typedef int32 CFE_Status_t; * the platform configuration parameter #CFE_PLATFORM_SB_MAX_MSG_IDS has been met. * */ -#define CFE_SB_MAX_MSGS_MET ((int32)0xca000009) - +#define CFE_SB_MAX_MSGS_MET ((CFE_Status_t)0xca000009) /** * @brief Max Destinations Met @@ -837,8 +798,7 @@ typedef int32 CFE_Status_t; * #CFE_PLATFORM_SB_MAX_DEST_PER_PKT. * */ -#define CFE_SB_MAX_DESTS_MET ((int32)0xca00000a) - +#define CFE_SB_MAX_DESTS_MET ((CFE_Status_t)0xca00000a) /** * @brief No Subscribers @@ -847,8 +807,7 @@ typedef int32 CFE_Status_t; * not been an entry in the routing tables for the MsgId/PipeId given as * parameters. */ -#define CFE_SB_NO_SUBSCRIBERS ((int32)0xca00000b) - +#define CFE_SB_NO_SUBSCRIBERS ((CFE_Status_t)0xca00000b) /** * @brief Internal Error @@ -858,8 +817,7 @@ typedef int32 CFE_Status_t; * cause would be a Single Event Upset. * */ -#define CFE_SB_INTERNAL_ERR ((int32)0xca00000c) - +#define CFE_SB_INTERNAL_ERR ((CFE_Status_t)0xca00000c) /** * @brief Wrong Message Type @@ -868,8 +826,7 @@ typedef int32 CFE_Status_t; * is made on a packet that does not include a field for msg time. * */ -#define CFE_SB_WRONG_MSG_TYPE ((int32)0xca00000d) - +#define CFE_SB_WRONG_MSG_TYPE ((CFE_Status_t)0xca00000d) /** * @brief Buffer Invalid @@ -879,8 +836,7 @@ typedef int32 CFE_Status_t; * correct or the buffer was previously released. * */ -#define CFE_SB_BUFFER_INVALID ((int32)0xca00000e) - +#define CFE_SB_BUFFER_INVALID ((CFE_Status_t)0xca00000e) /** * @brief No Message Recieved @@ -889,8 +845,7 @@ typedef int32 CFE_Status_t; * value indicates that there was not a message recived on the pipe. * */ -#define CFE_SB_NO_MSG_RECV ((int32)0xca00000f) - +#define CFE_SB_NO_MSG_RECV ((CFE_Status_t)0xca00000f) /** * @brief Not Implemented @@ -901,7 +856,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_SB_NOT_IMPLEMENTED ((int32)0xca00ffff) +#define CFE_SB_NOT_IMPLEMENTED ((CFE_Status_t)0xca00ffff) /* ************* TABLE SERVICES STATUS CODES ************* @@ -915,7 +870,7 @@ typedef int32 CFE_Status_t; * identified a Table Access Descriptor that was not used. * */ -#define CFE_TBL_ERR_INVALID_HANDLE ((int32)0xcc000001) +#define CFE_TBL_ERR_INVALID_HANDLE ((CFE_Status_t)0xcc000001) /** * @brief Invalid Name @@ -925,7 +880,7 @@ typedef int32 CFE_Status_t; * #CFE_MISSION_TBL_MAX_NAME_LENGTH or was zero characters long. * */ -#define CFE_TBL_ERR_INVALID_NAME ((int32)0xcc000002) +#define CFE_TBL_ERR_INVALID_NAME ((CFE_Status_t)0xcc000002) /** * @brief Invalid Size @@ -936,7 +891,7 @@ typedef int32 CFE_Status_t; * c) that had a size of zero * */ -#define CFE_TBL_ERR_INVALID_SIZE ((int32)0xcc000003) +#define CFE_TBL_ERR_INVALID_SIZE ((CFE_Status_t)0xcc000003) /** * @brief Update Pending @@ -944,7 +899,7 @@ typedef int32 CFE_Status_t; * The calling Application has identified a table that has a load pending. * */ -#define CFE_TBL_INFO_UPDATE_PENDING ((int32)0x4c000004) +#define CFE_TBL_INFO_UPDATE_PENDING ((CFE_Status_t)0x4c000004) /** * @brief Never Loaded @@ -952,7 +907,7 @@ typedef int32 CFE_Status_t; * Table has not been loaded with data. * */ -#define CFE_TBL_ERR_NEVER_LOADED ((int32)0xcc000005) +#define CFE_TBL_ERR_NEVER_LOADED ((CFE_Status_t)0xcc000005) /** * @brief Registry Full @@ -961,7 +916,7 @@ typedef int32 CFE_Status_t; * registry already contained #CFE_PLATFORM_TBL_MAX_NUM_TABLES in it. * */ -#define CFE_TBL_ERR_REGISTRY_FULL ((int32)0xcc000006) +#define CFE_TBL_ERR_REGISTRY_FULL ((CFE_Status_t)0xcc000006) /** * @brief Duplicate Warning @@ -971,7 +926,7 @@ typedef int32 CFE_Status_t; * stays in place and the new table is rejected. * */ -#define CFE_TBL_WARN_DUPLICATE ((int32)0x4c000007) +#define CFE_TBL_WARN_DUPLICATE ((CFE_Status_t)0x4c000007) /** * @brief No Access @@ -980,7 +935,7 @@ typedef int32 CFE_Status_t; * failed when calling #CFE_TBL_Share or forgot to call either one. * */ -#define CFE_TBL_ERR_NO_ACCESS ((int32)0xcc000008) +#define CFE_TBL_ERR_NO_ACCESS ((CFE_Status_t)0xcc000008) /** * @brief Unregistered @@ -989,7 +944,7 @@ typedef int32 CFE_Status_t; * been unregistered. * */ -#define CFE_TBL_ERR_UNREGISTERED ((int32)0xcc000009) +#define CFE_TBL_ERR_UNREGISTERED ((CFE_Status_t)0xcc000009) /** * @brief Bad Application ID @@ -999,7 +954,7 @@ typedef int32 CFE_Status_t; * #CFE_ES_RegisterApp function. * */ -#define CFE_TBL_ERR_BAD_APP_ID ((int32)0xcc00000A) +#define CFE_TBL_ERR_BAD_APP_ID ((CFE_Status_t)0xcc00000A) /** * @brief Handles Full @@ -1008,7 +963,7 @@ typedef int32 CFE_Status_t; * Handle Array already used all CFE_PLATFORM_TBL_MAX_NUM_HANDLES in it. * */ -#define CFE_TBL_ERR_HANDLES_FULL ((int32)0xcc00000B) +#define CFE_TBL_ERR_HANDLES_FULL ((CFE_Status_t)0xcc00000B) /** * @brief Duplicate Table With Different Size @@ -1018,7 +973,7 @@ typedef int32 CFE_Status_t; * table is different from the size already in the registry. * */ -#define CFE_TBL_ERR_DUPLICATE_DIFF_SIZE ((int32)0xcc00000C) +#define CFE_TBL_ERR_DUPLICATE_DIFF_SIZE ((CFE_Status_t)0xcc00000C) /** * @brief Dupicate Table And Not Owned @@ -1028,7 +983,7 @@ typedef int32 CFE_Status_t; * table is owned by a different application. * */ -#define CFE_TBL_ERR_DUPLICATE_NOT_OWNED ((int32)0xcc00000D) +#define CFE_TBL_ERR_DUPLICATE_NOT_OWNED ((CFE_Status_t)0xcc00000D) /** * @brief Updated @@ -1039,7 +994,7 @@ typedef int32 CFE_Status_t; * the last time the application obtained its address or status. * */ -#define CFE_TBL_INFO_UPDATED ((int32)0x4c00000E) +#define CFE_TBL_INFO_UPDATED ((CFE_Status_t)0x4c00000E) /** * @brief No Buffer Available @@ -1048,7 +1003,7 @@ typedef int32 CFE_Status_t; * none were available. * */ -#define CFE_TBL_ERR_NO_BUFFER_AVAIL ((int32)0xcc00000F) +#define CFE_TBL_ERR_NO_BUFFER_AVAIL ((CFE_Status_t)0xcc00000F) /** * @brief Dump Only Error @@ -1057,7 +1012,7 @@ typedef int32 CFE_Status_t; * table that was created with "Dump Only" attributes. * */ -#define CFE_TBL_ERR_DUMP_ONLY ((int32)0xcc000010) +#define CFE_TBL_ERR_DUMP_ONLY ((CFE_Status_t)0xcc000010) /** * @brief Illegal Source Type @@ -1066,7 +1021,7 @@ typedef int32 CFE_Status_t; * value for the second parameter. * */ -#define CFE_TBL_ERR_ILLEGAL_SRC_TYPE ((int32)0xcc000011) +#define CFE_TBL_ERR_ILLEGAL_SRC_TYPE ((CFE_Status_t)0xcc000011) /** * @brief Load In Progress @@ -1075,7 +1030,7 @@ typedef int32 CFE_Status_t; * was trying to load the table. * */ -#define CFE_TBL_ERR_LOAD_IN_PROGRESS ((int32)0xcc000012) +#define CFE_TBL_ERR_LOAD_IN_PROGRESS ((CFE_Status_t)0xcc000012) /** * @brief File Not Found @@ -1083,7 +1038,7 @@ typedef int32 CFE_Status_t; * The calling Application called #CFE_TBL_Load with a bad filename. * */ -#define CFE_TBL_ERR_FILE_NOT_FOUND ((int32)0xcc000013) +#define CFE_TBL_ERR_FILE_NOT_FOUND ((CFE_Status_t)0xcc000013) /** * @brief File Too Large @@ -1093,7 +1048,7 @@ typedef int32 CFE_Status_t; * than specified in the table header. * */ -#define CFE_TBL_ERR_FILE_TOO_LARGE ((int32)0xcc000014) +#define CFE_TBL_ERR_FILE_TOO_LARGE ((CFE_Status_t)0xcc000014) /** * @brief Short File Warning @@ -1104,7 +1059,7 @@ typedef int32 CFE_Status_t; * at a non-zero offset). * */ -#define CFE_TBL_WARN_SHORT_FILE ((int32)0x4c000015) +#define CFE_TBL_WARN_SHORT_FILE ((CFE_Status_t)0x4c000015) /** * @brief Bad Content ID @@ -1113,7 +1068,7 @@ typedef int32 CFE_Status_t; * whose content ID was not that of a table image. * */ -#define CFE_TBL_ERR_BAD_CONTENT_ID ((int32)0xcc000016) +#define CFE_TBL_ERR_BAD_CONTENT_ID ((CFE_Status_t)0xcc000016) /** * @brief No Update Pending @@ -1121,7 +1076,7 @@ typedef int32 CFE_Status_t; * The calling Application has attempted to update a table without a pending load. * */ -#define CFE_TBL_INFO_NO_UPDATE_PENDING ((int32)0x4c000017) +#define CFE_TBL_INFO_NO_UPDATE_PENDING ((CFE_Status_t)0x4c000017) /** * @brief Table Locked @@ -1129,7 +1084,7 @@ typedef int32 CFE_Status_t; * The calling Application tried to update a table that is locked by another user. * */ -#define CFE_TBL_INFO_TABLE_LOCKED ((int32)0x4c000018) +#define CFE_TBL_INFO_TABLE_LOCKED ((CFE_Status_t)0x4c000018) /** * Validation Pending @@ -1137,7 +1092,7 @@ typedef int32 CFE_Status_t; * The calling Application should call #CFE_TBL_Validate for the specified table. * */ -#define CFE_TBL_INFO_VALIDATION_PENDING ((int32)0x4c000019) +#define CFE_TBL_INFO_VALIDATION_PENDING ((CFE_Status_t)0x4c000019) /** * No Validation Pending @@ -1145,7 +1100,7 @@ typedef int32 CFE_Status_t; * The calling Application tried to validate a table that did not have a validation request pending. * */ -#define CFE_TBL_INFO_NO_VALIDATION_PENDING ((int32)0x4c00001A) +#define CFE_TBL_INFO_NO_VALIDATION_PENDING ((CFE_Status_t)0x4c00001A) /** * @brief Bad Subtype ID @@ -1154,7 +1109,7 @@ typedef int32 CFE_Status_t; * a table image file. * */ -#define CFE_TBL_ERR_BAD_SUBTYPE_ID ((int32)0xcc00001B) +#define CFE_TBL_ERR_BAD_SUBTYPE_ID ((CFE_Status_t)0xcc00001B) /** * @brief File Size Inconsistent @@ -1163,7 +1118,7 @@ typedef int32 CFE_Status_t; * a table image file. * */ -#define CFE_TBL_ERR_FILE_SIZE_INCONSISTENT ((int32)0xcc00001C) +#define CFE_TBL_ERR_FILE_SIZE_INCONSISTENT ((CFE_Status_t)0xcc00001C) /** * @brief No Standard Header @@ -1171,7 +1126,7 @@ typedef int32 CFE_Status_t; * The calling Application tried to access a table file whose standard cFE File Header was the wrong size, etc. * */ -#define CFE_TBL_ERR_NO_STD_HEADER ((int32)0xcc00001D) +#define CFE_TBL_ERR_NO_STD_HEADER ((CFE_Status_t)0xcc00001D) /** * @brief No Table Header @@ -1180,8 +1135,7 @@ typedef int32 CFE_Status_t; * Table File Header was the wrong size, etc. * */ -#define CFE_TBL_ERR_NO_TBL_HEADER ((int32)0xcc00001E) - +#define CFE_TBL_ERR_NO_TBL_HEADER ((CFE_Status_t)0xcc00001E) /** * @brief Filename Too Long @@ -1190,8 +1144,7 @@ typedef int32 CFE_Status_t; * that was too long. * */ -#define CFE_TBL_ERR_FILENAME_TOO_LONG ((int32)0xcc00001F) - +#define CFE_TBL_ERR_FILENAME_TOO_LONG ((CFE_Status_t)0xcc00001F) /** * @brief File For Wrong Table @@ -1200,8 +1153,7 @@ typedef int32 CFE_Status_t; * header indicated that it was for a different table. * */ -#define CFE_TBL_ERR_FILE_FOR_WRONG_TABLE ((int32)0xcc000020) - +#define CFE_TBL_ERR_FILE_FOR_WRONG_TABLE ((CFE_Status_t)0xcc000020) /** * @brief Load Incomplete @@ -1210,8 +1162,7 @@ typedef int32 CFE_Status_t; * claimed the load was larger than what was actually read from the file. * */ -#define CFE_TBL_ERR_LOAD_INCOMPLETE ((int32)0xcc000021) - +#define CFE_TBL_ERR_LOAD_INCOMPLETE ((CFE_Status_t)0xcc000021) /** * @brief Partial Load Warning @@ -1221,8 +1172,7 @@ typedef int32 CFE_Status_t; * that #CFE_TBL_WARN_SHORT_FILE also indicates a partial load. * */ -#define CFE_TBL_WARN_PARTIAL_LOAD ((int32)0x4c000022) - +#define CFE_TBL_WARN_PARTIAL_LOAD ((CFE_Status_t)0x4c000022) /** * @brief Partial Load Error @@ -1234,8 +1184,7 @@ typedef int32 CFE_Status_t; * #CFE_TBL_WARN_SHORT_FILE also indicates a partial load. * */ -#define CFE_TBL_ERR_PARTIAL_LOAD ((int32)0xcc000023) - +#define CFE_TBL_ERR_PARTIAL_LOAD ((CFE_Status_t)0xcc000023) /** * @brief Dump Pending @@ -1245,8 +1194,7 @@ typedef int32 CFE_Status_t; * with the owning application. * */ -#define CFE_TBL_INFO_DUMP_PENDING ((int32)0x4c000024) - +#define CFE_TBL_INFO_DUMP_PENDING ((CFE_Status_t)0x4c000024) /** * @brief Invalid Options @@ -1262,8 +1210,7 @@ typedef int32 CFE_Status_t; * -# #CFE_TBL_OPT_DUMP_ONLY * */ -#define CFE_TBL_ERR_INVALID_OPTIONS ((int32)0xcc000025) - +#define CFE_TBL_ERR_INVALID_OPTIONS ((CFE_Status_t)0xcc000025) /** * @brief Not Critical Warning @@ -1274,8 +1221,7 @@ typedef int32 CFE_Status_t; * will be treated as a normal table from now on. * */ -#define CFE_TBL_WARN_NOT_CRITICAL ((int32)0x4c000026) - +#define CFE_TBL_WARN_NOT_CRITICAL ((CFE_Status_t)0x4c000026) /** * @brief Recovered Table @@ -1288,8 +1234,7 @@ typedef int32 CFE_Status_t; * validated using the table's validation function. * */ -#define CFE_TBL_INFO_RECOVERED_TBL ((int32)0x4c000027) - +#define CFE_TBL_INFO_RECOVERED_TBL ((CFE_Status_t)0x4c000027) /** * @brief Bad Spacecraft ID @@ -1300,8 +1245,7 @@ typedef int32 CFE_Status_t; * with an invalid Spacecraft ID in the table file header. * */ -#define CFE_TBL_ERR_BAD_SPACECRAFT_ID ((int32)0xcc000028) - +#define CFE_TBL_ERR_BAD_SPACECRAFT_ID ((CFE_Status_t)0xcc000028) /** * @brief Bad Processor ID @@ -1312,7 +1256,7 @@ typedef int32 CFE_Status_t; * with an invalid Processor ID in the table file header. * */ -#define CFE_TBL_ERR_BAD_PROCESSOR_ID ((int32)0xcc000029) +#define CFE_TBL_ERR_BAD_PROCESSOR_ID ((CFE_Status_t)0xcc000029) /** * @brief Message Error @@ -1320,20 +1264,28 @@ typedef int32 CFE_Status_t; * Error code indicating that the TBL command was not processed * successfully and that the error counter should be incremented. */ -#define CFE_TBL_MESSAGE_ERROR ((int32)0xcc00002a) +#define CFE_TBL_MESSAGE_ERROR ((CFE_Status_t)0xcc00002a) /** ** Error code indicating that the TBL file is shorter than ** indicated in the file header. */ -#define CFE_TBL_ERR_SHORT_FILE ((int32)0xcc00002b) +#define CFE_TBL_ERR_SHORT_FILE ((CFE_Status_t)0xcc00002b) /** ** Error code indicating that the TBL file could not be ** opened by the OS. */ -#define CFE_TBL_ERR_ACCESS ((int32)0xcc00002c) +#define CFE_TBL_ERR_ACCESS ((CFE_Status_t)0xcc00002c) +/** + * @brief Bad Argument + * + * A parameter given by a caller to a Table API did not pass + * validation checks. + * + */ +#define CFE_TBL_BAD_ARGUMENT ((CFE_Status_t)0xcc00002d) /** * @brief Not Implemented @@ -1344,8 +1296,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_TBL_NOT_IMPLEMENTED ((int32)0xcc00ffff) - +#define CFE_TBL_NOT_IMPLEMENTED ((CFE_Status_t)0xcc00ffff) /* ************* TIME SERVICES STATUS CODES ************* @@ -1360,7 +1311,7 @@ typedef int32 CFE_Status_t; * the specified feature. * */ -#define CFE_TIME_NOT_IMPLEMENTED ((int32)0xce00ffff) +#define CFE_TIME_NOT_IMPLEMENTED ((CFE_Status_t)0xce00ffff) /** * @brief Internal Only @@ -1372,7 +1323,7 @@ typedef int32 CFE_Status_t; * a "time at the tone" command packet using internal data. * */ -#define CFE_TIME_INTERNAL_ONLY ((int32)0xce000001) +#define CFE_TIME_INTERNAL_ONLY ((CFE_Status_t)0xce000001) /** * @brief Out Of Range @@ -1387,7 +1338,7 @@ typedef int32 CFE_Status_t; * Services has previously been commanded to set the clock state * to "valid". */ -#define CFE_TIME_OUT_OF_RANGE ((int32)0xce000002) +#define CFE_TIME_OUT_OF_RANGE ((CFE_Status_t)0xce000002) /** * @brief Too Many Sync Callbacks @@ -1398,7 +1349,7 @@ typedef int32 CFE_Status_t; * distribute the single callback to child threads as needed. * */ -#define CFE_TIME_TOO_MANY_SYNCH_CALLBACKS ((int32)0xce000003) +#define CFE_TIME_TOO_MANY_SYNCH_CALLBACKS ((CFE_Status_t)0xce000003) /** * @brief Callback Not Registered @@ -1408,19 +1359,26 @@ typedef int32 CFE_Status_t; * located in the Synchronization Callback Registry. * */ -#define CFE_TIME_CALLBACK_NOT_REGISTERED ((int32)0xce000004) -/**@}*/ +#define CFE_TIME_CALLBACK_NOT_REGISTERED ((CFE_Status_t)0xce000004) +/** + * @brief Bad Argument + * + * A parameter given by a caller to a TIME Services API did not pass + * validation checks. + * + */ +#define CFE_TIME_BAD_ARGUMENT ((CFE_Status_t)0xce000005) +/**@}*/ /* Compatibility for error names which have been updated */ #ifndef CFE_OMIT_DEPRECATED_6_8 -#define CFE_ES_ERR_TASKID CFE_ES_ERR_RESOURCEID_NOT_VALID -#define CFE_ES_ERR_APPID CFE_ES_ERR_RESOURCEID_NOT_VALID -#define CFE_ES_ERR_MEM_HANDLE CFE_ES_ERR_RESOURCEID_NOT_VALID -#define CFE_ES_ERR_APPNAME CFE_ES_ERR_NAME_NOT_FOUND -#define CFE_ES_CDS_NOT_FOUND_ERR CFE_ES_ERR_NAME_NOT_FOUND -#define CFE_ES_CDS_REGISTRY_FULL CFE_ES_NO_RESOURCE_IDS_AVAILABLE +#define CFE_ES_ERR_TASKID CFE_ES_ERR_RESOURCEID_NOT_VALID +#define CFE_ES_ERR_APPID CFE_ES_ERR_RESOURCEID_NOT_VALID +#define CFE_ES_ERR_MEM_HANDLE CFE_ES_ERR_RESOURCEID_NOT_VALID +#define CFE_ES_ERR_APPNAME CFE_ES_ERR_NAME_NOT_FOUND +#define CFE_ES_CDS_NOT_FOUND_ERR CFE_ES_ERR_NAME_NOT_FOUND +#define CFE_ES_CDS_REGISTRY_FULL CFE_ES_NO_RESOURCE_IDS_AVAILABLE #endif - -#endif /* _cfe_error_ */ +#endif /* _cfe_error_ */ diff --git a/fsw/cfe-core/src/inc/cfe_evs_events.h b/fsw/cfe-core/src/inc/cfe_evs_events.h index 5c3b0af93..20d6b1fbf 100644 --- a/fsw/cfe-core/src/inc/cfe_evs_events.h +++ b/fsw/cfe-core/src/inc/cfe_evs_events.h @@ -533,51 +533,6 @@ **/ #define CFE_EVS_WRLOG_EID 33 -/** \brief 'Set Log Mode Command: Event Log is Disabled' -** \event 'Set Log Mode Command: Event Log is Disabled' -** -** \par Type: ERROR -** -** \par Cause: -** -** This event message is generated upon receipt of a "Set Log Mode" -** command when the use of the Event Log has been disabled. The EVS task -** must succeed during task initialization in acquiring a pointer to -** the cFE reset area and in the creation of a serializing semaphore to -** control access to the Event Log. -**/ -#define CFE_EVS_NO_LOGSET_EID 34 - -/** \brief 'Clear Log Command: Event Log is Disabled' -** \event 'Clear Log Command: Event Log is Disabled' -** -** \par Type: ERROR -** -** \par Cause: -** -** This event message is generated upon receipt of a "Clear Log" -** command when the use of the Event Log has been disabled. The EVS task -** must succeed during task initialization in acquiring a pointer to -** the cFE reset area and in the creation of a serializing semaphore to -** control access to the Event Log. -**/ -#define CFE_EVS_NO_LOGCLR_EID 35 - -/** \brief 'Write Log Command: Event Log is Disabled' -** \event 'Write Log Command: Event Log is Disabled' -** -** \par Type: ERROR -** -** \par Cause: -** -** This event message is generated upon receipt of a "Write Log" -** command when the use of the Event Log has been disabled. The EVS task -** must succeed during task initialization in acquiring a pointer to -** the cFE reset area and in the creation of a serializing semaphore to -** control access to the Event Log. -**/ -#define CFE_EVS_NO_LOGWR_EID 36 - /** \brief 'Add Filter Command:AppName = \%s, EventID = 0x\%08x is already registered for filtering' ** \event 'Add Filter Command:AppName = \%s, EventID = 0x\%08x is already registered for filtering' ** diff --git a/fsw/cfe-core/src/inc/cfe_fs.h b/fsw/cfe-core/src/inc/cfe_fs.h index 91d4b98af..13be4d0c3 100644 --- a/fsw/cfe-core/src/inc/cfe_fs.h +++ b/fsw/cfe-core/src/inc/cfe_fs.h @@ -42,6 +42,27 @@ #include "common_types.h" #include "cfe_time.h" +/** + * \brief Generalized file types/categories known to FS + * + * This defines different categories of files, where they + * may reside in different default locations of the virtualized file system. + * + * This is different from, and should not be confused with, the "SubType" + * field in the FS header. This value is only used at runtime for FS APIs + * and should not actually appear in any output file or message. + */ +typedef enum +{ + CFE_FS_FileCategory_UNKNOWN, /**< Placeholder, unknown file category */ + CFE_FS_FileCategory_DYNAMIC_MODULE, /**< Dynamically loadable apps/libraries (e.g. .so, .o, .dll, etc) */ + CFE_FS_FileCategory_BINARY_DATA_DUMP, /**< Binary log file generated by various data dump commands */ + CFE_FS_FileCategory_TEXT_LOG, /**< Text-based log file generated by various commands */ + CFE_FS_FileCategory_SCRIPT, /**< Text-based Script files (e.g. ES startup script) */ + CFE_FS_FileCategory_TEMP, /**< Temporary/Ephemeral files */ + CFE_FS_FileCategory_MAX /**< Placeholder, keep last */ +} CFE_FS_FileCategory_t; + /* * Because FS is a library not an app, it does not have its own context or * event IDs. The file writer runs in the context of the ES background task @@ -222,6 +243,107 @@ CFE_Status_t CFE_FS_SetTimestamp(osal_id_t FileDes, CFE_TIME_SysTime_t NewTimest * @{ */ +/*****************************************************************************/ +/** +** \brief Get the default virtual mount point for a file category +** +** Certain classes of files generally reside in a common directory, mainly +** either the persistent storage (/cf typically) or ram disk (/ram typically). +** +** Ephemeral status files are generally in the ram disk while application +** modules and scripts are generally in the persistent storage. +** +** This returns the expected directory for a given class of files in the form +** of a virtual OSAL mount point string. +** +** \returns String containing the mount point, or NULL if unkown/invalid +*/ +const char *CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_t FileCategory); + +/*****************************************************************************/ +/** +** \brief Get the default filename extension for a file category +** +** Certain file types may have an extension that varies from system to system. +** This is primarily an issue for application modules which are ".so" on +** Linux systems, ".dll" on Windows, ".o" on VxWorks, ".obj" on RTEMS, and so on. +** +** This uses a combination of compile-time configuration and hints from the +** build environment to get the default/expected extension for a given file +** category. +** +** \returns String containing the extension, or NULL if unkown/invalid +*/ +const char *CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_t FileCategory); + + +/*****************************************************************************/ +/** +** \brief Parse a filename input from an input buffer into a local buffer +** +** \par Description +** This provides a more user friendly way to specify file names, +** using default values for the path and extension, which can +** vary from system to system. +** +** If InputBuffer is null or its length is zero, then DefaultInput +** is used as if it was the content of the input buffer. +** +** If either the pathname or extension is missing from the input, +** it will be added from defaults, with the complete fully-qualified +** filename stored in the output buffer. +** +** \par Assumptions, External Events, and Notes: +** -# The paths and filenames used here are the standard unix style +** filenames separated by "/" (path) and "." (extension) characters. +** -# Input Buffer has a fixed max length. Parsing will not exceed InputBufSize, +** and does not need to be null terminated. However parsing will stop +** at the first null char, when the input is shorter than the maximum. +** +** \param[out] OutputBuffer Buffer to store result. +** \param[in] InputBuffer A input buffer that may contain a file name (e.g. from command). +** \param[in] OutputBufSize Maximum Size of output buffer. +** \param[in] InputBufSize Maximum Size of input buffer. +** \param[in] DefaultInput Default value to use for input if InputBffer is empty +** \param[in] DefaultPath Default value to use for pathname if omitted from input +** \param[in] DefaultExtension Default value to use for extension if omitted from input +** +** \return Execution status, see \ref CFEReturnCodes +** +******************************************************************************/ +int32 CFE_FS_ParseInputFileNameEx(char *OutputBuffer, const char *InputBuffer, size_t OutputBufSize, size_t InputBufSize, + const char *DefaultInput, const char *DefaultPath, const char *DefaultExtension); + + +/*****************************************************************************/ +/** +** \brief Parse a filename string from the user into a local buffer +** +** \par Description +** Simplified API for CFE_FS_ParseInputFileNameEx() where input is +** always known to be a non-empty, null terminated string and the fixed-length +** input buffer not needed. For instance this may be used where +** the input is a fixed string from cfe_platform_cfg.h or similar. +** +** \par Assumptions, External Events, and Notes: +** The parameters are organized such that this is basically like strncpy() with an +** extra argument, and existing file name accesses which use a direct copy can +** easily change to use this instead. +** +** \sa CFE_FS_ParseInputFileNameEx() +** +** \param[out] OutputBuffer Buffer to store result. +** \param[in] InputName A null terminated input string +** \param[in] OutputBufSize Maximum Size of output buffer. +** \param[in] FileCategory The generalized category of file (implies default path/extension) +** +** \return Execution status, see \ref CFEReturnCodes +** +**--------------------------------------------------------------------------------------- +*/ +int32 CFE_FS_ParseInputFileName(char *OutputBuffer, const char *InputName, size_t OutputBufSize, CFE_FS_FileCategory_t FileCategory); + + /*****************************************************************************/ /** ** \brief Extracts the filename from a unix style path and filename string. diff --git a/fsw/cfe-core/src/inc/cfe_sb.h b/fsw/cfe-core/src/inc/cfe_sb.h index 88749ee8a..aa7862e37 100644 --- a/fsw/cfe-core/src/inc/cfe_sb.h +++ b/fsw/cfe-core/src/inc/cfe_sb.h @@ -177,7 +177,10 @@ typedef uint8 *CFE_SB_MsgPayloadPtr_t; ** ** Software Zero Copy handle used in many SB APIs */ -typedef cpuaddr CFE_SB_ZeroCopyHandle_t; +typedef struct +{ + struct CFE_SB_BufferD* BufDscPtr; /* abstract descriptor reference (internal use) */ +} CFE_SB_ZeroCopyHandle_t; /** \brief Quality Of Service Type Definition ** @@ -739,14 +742,14 @@ CFE_SB_Buffer_t *CFE_SB_ZeroCopyGetPtr(size_t MsgSize, ** pointer returned by a call to #CFE_SB_ZeroCopyGetPtr, ** but never used in a call to #CFE_SB_TransmitBuffer. ** -** \param[in] BufferHandle This must be the handle supplied with the pointer -** when #CFE_SB_ZeroCopyGetPtr was called. +** \param[in] ZeroCopyHandle This must be the handle supplied with the pointer +** when #CFE_SB_ZeroCopyGetPtr was called. ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** \retval #CFE_SB_BUFFER_INVALID \copybrief CFE_SB_BUFFER_INVALID **/ -CFE_Status_t CFE_SB_ZeroCopyReleasePtr(CFE_SB_Buffer_t *Ptr2Release, CFE_SB_ZeroCopyHandle_t BufferHandle); +CFE_Status_t CFE_SB_ZeroCopyReleasePtr(CFE_SB_Buffer_t *Ptr2Release, CFE_SB_ZeroCopyHandle_t ZeroCopyHandle); /*****************************************************************************/ /** @@ -762,14 +765,19 @@ CFE_Status_t CFE_SB_ZeroCopyReleasePtr(CFE_SB_Buffer_t *Ptr2Release, CFE_SB_Zero ** performance in high-rate, high-volume software bus traffic. ** ** \par Assumptions, External Events, and Notes: -** -# The pointer returned by #CFE_SB_ZeroCopyGetPtr is only good for -** one call to #CFE_SB_TransmitBuffer. -** -# Callers must not use the same SB message buffer for multiple sends. +** -# A handle returned by #CFE_SB_ZeroCopyGetPtr is "consumed" by +** a _successful_ call to #CFE_SB_TransmitBuffer. +** -# If this function returns CFE_SUCCESS, this indicates the zero copy handle is +** now owned by software bus, and is no longer owned by the calling application, +** and should not be re-used. +** -# Howver if this function fails (returns any error status) it does not change +** the state of the buffer at all, meaning the calling application still owns it. +** (a failure means the buffer is left in the same state it was before the call). ** -# Applications should be written as if #CFE_SB_ZeroCopyGetPtr is -** equivalent to a \c malloc() and #CFE_SB_TransmitBuffer is equivalent -** to a \c free(). +** equivalent to a \c malloc() and a successful call to #CFE_SB_TransmitBuffer +** is equivalent to a \c free(). ** -# Applications must not de-reference the message pointer (for reading -** or writing) after the call to #CFE_SB_TransmitBuffer. +** or writing) after a successful call to #CFE_SB_TransmitBuffer. ** -# This function will increment and apply the internally tracked ** sequence counter if set to do so. ** diff --git a/fsw/cfe-core/src/inc/cfe_version.h b/fsw/cfe-core/src/inc/cfe_version.h index 94cb45b7c..c30c19c99 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 365 /*!< Development Build: Number of commits since baseline */ +#define CFE_BUILD_NUMBER 382 /*!< 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 */ diff --git a/fsw/cfe-core/src/inc/private/cfe_sbr.h b/fsw/cfe-core/src/inc/private/cfe_sbr.h index de0123bd7..63d00d2ba 100644 --- a/fsw/cfe-core/src/inc/private/cfe_sbr.h +++ b/fsw/cfe-core/src/inc/private/cfe_sbr.h @@ -38,6 +38,13 @@ #include "cfe_msg_typedefs.h" #include "cfe_platform_cfg.h" +/* + * Macro Definitions + */ + +/** \brief Invalid route id */ +#define CFE_SBR_INVALID_ROUTE_ID ((CFE_SBR_RouteId_t) {.RouteId = 0}) + /****************************************************************************** * Type Definitions */ diff --git a/fsw/cfe-core/src/sb/cfe_sb_api.c b/fsw/cfe-core/src/sb/cfe_sb_api.c index 8a1b33a98..ba2eff5af 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_api.c +++ b/fsw/cfe-core/src/sb/cfe_sb_api.c @@ -1393,52 +1393,74 @@ int32 CFE_SB_TransmitMsg(CFE_MSG_Message_t *MsgPtr, bool IncrementSequenceCount char FullName[(OS_MAX_API_NAME * 2)]; CFE_SB_BufferD_t *BufDscPtr; CFE_SBR_RouteId_t RouteId; - CFE_MSG_Type_t MsgType; uint16 PendingEventID; PendingEventID = 0; BufDscPtr = NULL; + RouteId = CFE_SBR_INVALID_ROUTE_ID; Status = CFE_SB_TransmitMsgValidate(MsgPtr, &MsgId, &Size, &RouteId); + CFE_SB_LockSharedData(__func__, __LINE__); + if (Status == CFE_SUCCESS && CFE_SBR_IsValidRouteId(RouteId)) { - CFE_SB_LockSharedData(__func__, __LINE__); - - /* Get buffer */ - BufDscPtr = CFE_SB_GetBufferFromPool(MsgId, Size); + /* Get buffer - note this pre-initializes the returned buffer with + * a use count of 1, which refers to this task as it fills the buffer. */ + BufDscPtr = CFE_SB_GetBufferFromPool(Size); if (BufDscPtr == NULL) { PendingEventID = CFE_SB_GET_BUF_ERR_EID; Status = CFE_SB_BUF_ALOC_ERR; } - else - { - /* For Tlm packets, increment the seq count if requested */ - CFE_MSG_GetType(MsgPtr, &MsgType); - if((MsgType == CFE_MSG_Type_Tlm) && IncrementSequenceCount) - { - CFE_SBR_IncrementSequenceCounter(RouteId); - CFE_MSG_SetSequenceCount(MsgPtr, CFE_SBR_GetSequenceCounter(RouteId)); - } - } - - CFE_SB_UnlockSharedData(__func__, __LINE__); } - if (Status == CFE_SUCCESS && BufDscPtr != NULL) + /* + * Increment the MsgSendErrorCounter only if there was a real error, + * such as a validation issue or failure to allocate a buffer. + * + * (This should NOT be done if simply no route) + */ + if (Status != CFE_SUCCESS) { - /* Copy data into buffer and transmit */ - memcpy(BufDscPtr->Buffer, MsgPtr, Size); - Status = CFE_SB_TransmitBufferFull(BufDscPtr, RouteId, MsgId); + CFE_SB_Global.HKTlmMsg.Payload.MsgSendErrorCounter++; } - if (Status != CFE_SUCCESS) + CFE_SB_UnlockSharedData(__func__, __LINE__); + + /* + * If a buffer was obtained above, then copy the content into it + * and broadcast it to all subscribers in the route. + * + * Note - if there is no route / no subscribers, the "Status" will + * be CFE_SUCCESS because CFE_SB_TransmitMsgValidate() succeeded, + * but there will be no buffer because CFE_SBR_IsValidRouteId() returned + * false. + * + * But if the desciptor is non-null it means the message is valid and + * there is a route to send it to. + */ + if (BufDscPtr != NULL) { - /* Increment error counter (inside lock) if not success */ - CFE_SB_LockSharedData(__func__, __LINE__); - CFE_SB_Global.HKTlmMsg.Payload.MsgSendErrorCounter++; - CFE_SB_UnlockSharedData(__func__, __LINE__); + /* Copy actual message content into buffer and set its metadata */ + memcpy(&BufDscPtr->Content, MsgPtr, Size); + BufDscPtr->MsgId = MsgId; + BufDscPtr->ContentSize = Size; + BufDscPtr->AutoSequence = IncrementSequenceCount; + CFE_MSG_GetType(MsgPtr, &BufDscPtr->ContentType); + + /* + * This routine will use best-effort to send to all subscribers, + * increment the buffer use count for every successful delivery, + * and send an event/increment counter for any unsucessful delivery. + */ + CFE_SB_BroadcastBufferToRoute(BufDscPtr, RouteId); + + /* + * The broadcast function consumes the buffer, so it should not be + * accessed in this function anymore + */ + BufDscPtr = NULL; } if (PendingEventID == CFE_SB_GET_BUF_ERR_EID) @@ -1615,11 +1637,8 @@ int32 CFE_SB_TransmitMsgValidate(CFE_MSG_Message_t *MsgPtr, * \param[in] BufDscPtr Pointer to the buffer description from the memory pool, * released prior to return * \param[in] RouteId Route to send to - * \param[in] MsgId Message Id that is being sent */ -int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, - CFE_SBR_RouteId_t RouteId, - CFE_SB_MsgId_t MsgId) +void CFE_SB_BroadcastBufferToRoute(CFE_SB_BufferD_t *BufDscPtr, CFE_SBR_RouteId_t RouteId) { CFE_ES_AppId_t AppId; CFE_ES_TaskId_t TskId; @@ -1631,7 +1650,6 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, char FullName[(OS_MAX_API_NAME * 2)]; char PipeName[OS_MAX_API_NAME]; - Status = CFE_SUCCESS; SBSndErr.EvtsToSnd = 0; /* get app id for loopback testing */ @@ -1643,66 +1661,75 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, /* take semaphore to prevent a task switch during processing */ CFE_SB_LockSharedData(__func__,__LINE__); - /* Send the packet to all destinations */ - for(DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); DestPtr != NULL; DestPtr = DestPtr->Next) + /* For an invalid route / no subsribers this whole logic can be skipped */ + if (CFE_SBR_IsValidRouteId(RouteId)) { - if (DestPtr->Active == CFE_SB_ACTIVE) /* destination is active */ + /* Set the seq count if requested (while locked) before actually sending */ + /* For some reason this is only done for TLM types (historical, TBD) */ + if (BufDscPtr->AutoSequence && BufDscPtr->ContentType == CFE_MSG_Type_Tlm) { - PipeDscPtr = CFE_SB_LocatePipeDescByID(DestPtr->PipeId); - } - else - { - PipeDscPtr = NULL; - } + CFE_SBR_IncrementSequenceCounter(RouteId); - if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, DestPtr->PipeId)) - { - continue; + /* Write the sequence into the message header itself (overwrites whatever was there) */ + CFE_MSG_SetSequenceCount(&BufDscPtr->Content.Msg, CFE_SBR_GetSequenceCounter(RouteId)); } - if((PipeDscPtr->Opts & CFE_SB_PIPEOPTS_IGNOREMINE) != 0 && - CFE_RESOURCEID_TEST_EQUAL(PipeDscPtr->AppId, AppId)) + /* Send the packet to all destinations */ + for (DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); DestPtr != NULL; DestPtr = DestPtr->Next) { - continue; - }/* end if */ + if (DestPtr->Active == CFE_SB_ACTIVE) /* destination is active */ + { + PipeDscPtr = CFE_SB_LocatePipeDescByID(DestPtr->PipeId); + } + else + { + PipeDscPtr = NULL; + } - /* if Msg limit exceeded, log event, increment counter */ - /* and go to next destination */ - if(DestPtr->BuffCount >= DestPtr->MsgId2PipeLim) - { - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_MSGID_LIM_ERR_EID; - SBSndErr.EvtsToSnd++; - CFE_SB_Global.HKTlmMsg.Payload.MsgLimitErrorCounter++; - PipeDscPtr->SendErrors++; + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, DestPtr->PipeId)) + { + continue; + } - continue; - }/* end if */ + if ((PipeDscPtr->Opts & CFE_SB_PIPEOPTS_IGNOREMINE) != 0 && + CFE_RESOURCEID_TEST_EQUAL(PipeDscPtr->AppId, AppId)) + { + continue; + } /* end if */ - /* - ** Write the buffer descriptor to the queue of the pipe. If the write - ** failed, log info and increment the pipe's error counter. - */ - Status = OS_QueuePut(PipeDscPtr->SysQueueId, (void *)&BufDscPtr, sizeof(CFE_SB_BufferD_t *), 0); + /* if Msg limit exceeded, log event, increment counter */ + /* and go to next destination */ + if (DestPtr->BuffCount >= DestPtr->MsgId2PipeLim) + { + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_MSGID_LIM_ERR_EID; + SBSndErr.EvtsToSnd++; + CFE_SB_Global.HKTlmMsg.Payload.MsgLimitErrorCounter++; + PipeDscPtr->SendErrors++; - if (Status == OS_SUCCESS) - { - /* The queue now holds a ref to the buffer, so increment its ref count. */ - CFE_SB_IncrBufUseCnt(BufDscPtr); + continue; + } /* end if */ - DestPtr->BuffCount++; /* used for checking MsgId2PipeLimit */ - DestPtr->DestCnt++; /* used for statistics */ - ++PipeDscPtr->CurrentQueueDepth; - if (PipeDscPtr->CurrentQueueDepth >= PipeDscPtr->PeakQueueDepth) + /* + ** Write the buffer descriptor to the queue of the pipe. If the write + ** failed, log info and increment the pipe's error counter. + */ + Status = OS_QueuePut(PipeDscPtr->SysQueueId, &BufDscPtr, sizeof(BufDscPtr), 0); + + if (Status == OS_SUCCESS) { - PipeDscPtr->PeakQueueDepth = PipeDscPtr->CurrentQueueDepth; - } + /* The queue now holds a ref to the buffer, so increment its ref count. */ + CFE_SB_IncrBufUseCnt(BufDscPtr); - Status = CFE_SUCCESS; - } - else - { - if (Status == OS_QUEUE_FULL) + DestPtr->BuffCount++; /* used for checking MsgId2PipeLimit */ + DestPtr->DestCnt++; /* used for statistics */ + ++PipeDscPtr->CurrentQueueDepth; + if (PipeDscPtr->CurrentQueueDepth >= PipeDscPtr->PeakQueueDepth) + { + PipeDscPtr->PeakQueueDepth = PipeDscPtr->CurrentQueueDepth; + } + } + else if (Status == OS_QUEUE_FULL) { SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_FULL_ERR_EID; @@ -1719,12 +1746,35 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, SBSndErr.EvtsToSnd++; CFE_SB_Global.HKTlmMsg.Payload.InternalErrorCounter++; PipeDscPtr->SendErrors++; - }/*end if */ + } /*end if */ + + } /* end loop over destinations */ + } + + /* + * If any specific delivery issues occured, also increment the + * general error count before releasing the lock. + */ + if (SBSndErr.EvtsToSnd > 0) + { + CFE_SB_Global.HKTlmMsg.Payload.MsgSendErrorCounter++; + } + + /* + * Remove this from whatever list it was in + * + * If it was a singleton/new buffer this has no effect. + * If it was a zero-copy buffer this removes it from the ZeroCopyList. + */ + CFE_SB_TrackingListRemove(&BufDscPtr->Link); + + /* clear the AppID field in case it was a zero copy buffer, + * as it is no longer owned by that app after broadcasting */ + BufDscPtr->AppId = CFE_ES_APPID_UNDEFINED; + + /* track the buffer as an in-transit message */ + CFE_SB_TrackingListAdd(&CFE_SB_Global.InTransitList, &BufDscPtr->Link); - Status = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; - } - } /* end loop over destinations */ - /* ** Decrement the buffer UseCount and free buffer if cnt=0. This decrement is done ** because the use cnt is initialized to 1 in CFE_SB_GetBufferFromPool. @@ -1753,7 +1803,7 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, CFE_EVS_SendEventWithAppID(CFE_SB_MSGID_LIM_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB_Global.AppId, "Msg Limit Err,MsgId 0x%x,pipe %s,sender %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), + (unsigned int)CFE_SB_MsgIdToValue(BufDscPtr->MsgId), PipeName, CFE_SB_GetAppTskName(TskId,FullName)); /* clear the bit so the task may send this event again */ @@ -1772,7 +1822,7 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, CFE_EVS_SendEventWithAppID(CFE_SB_Q_FULL_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB_Global.AppId, "Pipe Overflow,MsgId 0x%x,pipe %s,sender %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), + (unsigned int)CFE_SB_MsgIdToValue(BufDscPtr->MsgId), PipeName, CFE_SB_GetAppTskName(TskId,FullName)); /* clear the bit so the task may send this event again */ @@ -1788,7 +1838,7 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, CFE_EVS_SendEventWithAppID(CFE_SB_Q_WR_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB_Global.AppId, "Pipe Write Err,MsgId 0x%x,pipe %s,sender %s,stat 0x%x", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), + (unsigned int)CFE_SB_MsgIdToValue(BufDscPtr->MsgId), PipeName, CFE_SB_GetAppTskName(TskId,FullName), (unsigned int)SBSndErr.EvtBuf[i].ErrStat); @@ -1798,9 +1848,6 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, }/* end if */ } - - return CFE_SUCCESS; - } #ifndef CFE_OMIT_DEPRECATED_6_8 @@ -1840,6 +1887,7 @@ int32 CFE_SB_ReceiveBuffer(CFE_SB_Buffer_t **BufPtr, BufDscPtr = NULL; DestPtr = NULL; BufDscSize = 0; + RcvStatus = OS_SUCCESS; /* * Check input args and see if any are bad, which require @@ -1984,7 +2032,7 @@ int32 CFE_SB_ReceiveBuffer(CFE_SB_Buffer_t **BufPtr, * Also set the Receivers pointer to the address of the actual message * (currently this is "borrowing" the ref above, not its own ref) */ - *BufPtr = BufDscPtr->Buffer; + *BufPtr = &BufDscPtr->Content; /* get pointer to destination to be used in decrementing msg limit cnt*/ RouteId = CFE_SBR_GetRouteId(BufDscPtr->MsgId); @@ -2075,113 +2123,113 @@ int32 CFE_SB_ReceiveBuffer(CFE_SB_Buffer_t **BufPtr, CFE_SB_Buffer_t *CFE_SB_ZeroCopyGetPtr(size_t MsgSize, CFE_SB_ZeroCopyHandle_t *BufferHandle) { - int32 stat1; - CFE_ES_AppId_t AppId; - cpuaddr address = 0; - CFE_SB_ZeroCopyD_t *zcd = NULL; - CFE_SB_BufferD_t *bd = NULL; + CFE_ES_AppId_t AppId; + CFE_SB_BufferD_t *BufDscPtr; + CFE_SB_Buffer_t *BufPtr; - CFE_SB_LockSharedData(__func__,__LINE__); - - /* Allocate a new zero copy descriptor from the SB memory pool.*/ - stat1 = CFE_ES_GetPoolBuf((CFE_ES_MemPoolBuf_t*)&zcd, CFE_SB_Global.Mem.PoolHdl, sizeof(CFE_SB_ZeroCopyD_t)); - if(stat1 < 0){ - CFE_SB_UnlockSharedData(__func__,__LINE__); + AppId = CFE_ES_APPID_UNDEFINED; + BufDscPtr = NULL; + BufPtr = NULL; + if(MsgSize > CFE_MISSION_SB_MAX_SB_MSG_SIZE) + { + CFE_ES_WriteToSysLog(" CFE_SB:ZeroCopyGetPtr-Failed, MsgSize is too large\n"); return NULL; } - /* Add the size of a zero copy descriptor to the memory-in-use ctr and */ - /* adjust the high water mark if needed */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse+=stat1; - if(CFE_SB_Global.StatTlmMsg.Payload.MemInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse){ - CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse = CFE_SB_Global.StatTlmMsg.Payload.MemInUse; - }/* end if */ - - /* Allocate a new buffer (from the SB memory pool) to hold the message */ - stat1 = CFE_ES_GetPoolBuf((CFE_ES_MemPoolBuf_t*)&bd, CFE_SB_Global.Mem.PoolHdl, MsgSize + sizeof(CFE_SB_BufferD_t)); - if((stat1 < 0)||(bd==NULL)){ - /*deallocate the first buffer if the second buffer creation fails*/ - stat1 = CFE_ES_PutPoolBuf(CFE_SB_Global.Mem.PoolHdl, zcd); - if(stat1 > 0){ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse-=stat1; - } - CFE_SB_UnlockSharedData(__func__,__LINE__); + if (BufferHandle == NULL) + { + CFE_ES_WriteToSysLog(" CFE_SB:ZeroCopyGetPtr-BufferHandle is NULL\n"); return NULL; } - /* Increment the number of buffers in use by one even though two buffers */ - /* were allocated. SBBuffersInUse increments on a per-message basis */ - CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse++; - if(CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse){ - CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse = CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse; - }/* end if */ - - /* Add the size of the actual buffer to the memory-in-use ctr and */ - /* adjust the high water mark if needed */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse+=stat1; - if(CFE_SB_Global.StatTlmMsg.Payload.MemInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse){ - CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse = CFE_SB_Global.StatTlmMsg.Payload.MemInUse; - }/* end if */ - - /* first set ptr to actual msg buffer the same as ptr to descriptor */ - address = (cpuaddr)bd; + /* get callers AppId */ + if (CFE_ES_GetAppID(&AppId) == CFE_SUCCESS) + { + CFE_SB_LockSharedData(__func__,__LINE__); - /* increment actual msg buffer ptr beyond the descriptor */ - address += sizeof(CFE_SB_BufferD_t); + /* + * All this needs to do is get a descriptor from the pool, + * and associate that descriptor with this app ID, so it + * can be freed if this app is deleted before it uses it. + */ + BufDscPtr = CFE_SB_GetBufferFromPool(MsgSize); - /* Initialize the zero copy descriptor structure. */ - zcd->Size = MsgSize; - zcd->Buffer = (void *)address; - zcd->Next = NULL; + if (BufDscPtr != NULL) + { + /* Track the buffer as a zero-copy assigned to this app ID */ + BufDscPtr->AppId = AppId; + BufPtr = &BufDscPtr->Content; + CFE_SB_TrackingListAdd(&CFE_SB_Global.ZeroCopyList, &BufDscPtr->Link); + } - /* Add this Zero Copy Descriptor to the end of the chain */ - if(CFE_SB_Global.ZeroCopyTail != NULL){ - ((CFE_SB_ZeroCopyD_t *) CFE_SB_Global.ZeroCopyTail)->Next = (void *)zcd; + CFE_SB_UnlockSharedData(__func__,__LINE__); } - zcd->Prev = CFE_SB_Global.ZeroCopyTail; - CFE_SB_Global.ZeroCopyTail = (void *)zcd; - - CFE_SB_UnlockSharedData(__func__,__LINE__); - /* get callers AppId */ - CFE_ES_GetAppID(&AppId); - zcd->AppID = AppId; + if (BufPtr != NULL) + { + /* + * If a buffer was obtained, wipe it now. + * (This ensures the buffer is fully cleared at least once, + * no stale data from a prior use of the same memory) + */ + memset(BufPtr, 0, MsgSize); + } - (*BufferHandle) = (CFE_SB_ZeroCopyHandle_t) zcd; + /* Export both items (descriptor + msg buffer) to caller */ + BufferHandle->BufDscPtr = BufDscPtr; + return BufPtr; - /* Initialize the buffer descriptor structure. */ - bd->UseCount = 1; - bd->Size = MsgSize; - bd->Buffer = (CFE_SB_Buffer_t *)address; +}/* CFE_SB_ZeroCopyGetPtr */ - return (CFE_SB_Buffer_t *)address; +/* + * Helper functions to do sanity checks on the Zero Copy handle + Buffer combo. + * + * Note in a future CFE version the API can be simplified - + * only one of these pointers is strictly needed, since they + * should refer to the same buffer descriptor object. + */ +int32 CFE_SB_ZeroCopyHandleValidate(CFE_SB_Buffer_t *BufPtr, + CFE_SB_ZeroCopyHandle_t ZeroCopyHandle) +{ + /* + * Sanity Check that the pointers are not NULL + */ + if (BufPtr == NULL || ZeroCopyHandle.BufDscPtr == NULL) + { + return CFE_SB_BAD_ARGUMENT; + } -}/* CFE_SB_ZeroCopyGetPtr */ + /* + * Check that the descriptor is actually a "zero copy" type, + * and that it refers to same actual message buffer. + */ + if (!CFE_RESOURCEID_TEST_DEFINED(ZeroCopyHandle.BufDscPtr->AppId) || + (&ZeroCopyHandle.BufDscPtr->Content != BufPtr)) + { + return CFE_SB_BUFFER_INVALID; + } + /* Basic sanity check passed */ + return CFE_SUCCESS; +} /* * Function: CFE_SB_ZeroCopyReleasePtr - See API and header file for details */ int32 CFE_SB_ZeroCopyReleasePtr(CFE_SB_Buffer_t *Ptr2Release, - CFE_SB_ZeroCopyHandle_t BufferHandle) + CFE_SB_ZeroCopyHandle_t ZeroCopyHandle) { - int32 Status; - int32 Stat2; - CFE_ES_MemPoolBuf_t BufAddr; + int32 Status; - Status = CFE_SB_ZeroCopyReleaseDesc(Ptr2Release, BufferHandle); + Status = CFE_SB_ZeroCopyHandleValidate(Ptr2Release, ZeroCopyHandle); CFE_SB_LockSharedData(__func__,__LINE__); - if(Status == CFE_SUCCESS){ - /* give the buffer back to the buffer pool */ - BufAddr = CFE_ES_MEMPOOLBUF_C((cpuaddr)Ptr2Release - sizeof(CFE_SB_BufferD_t)); - Stat2 = CFE_ES_PutPoolBuf(CFE_SB_Global.Mem.PoolHdl, BufAddr); - if(Stat2 > 0){ - /* Substract the size of the actual buffer from the Memory in use ctr */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse-=Stat2; - CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse--; - }/* end if */ + if (Status == CFE_SUCCESS) + { + /* Clear the ownership app ID and decrement use count (may also free) */ + ZeroCopyHandle.BufDscPtr->AppId = CFE_ES_APPID_UNDEFINED; + CFE_SB_DecrBufUseCnt(ZeroCopyHandle.BufDscPtr); } CFE_SB_UnlockSharedData(__func__,__LINE__); @@ -2190,69 +2238,6 @@ int32 CFE_SB_ZeroCopyReleasePtr(CFE_SB_Buffer_t *Ptr2Release, }/* end CFE_SB_ZeroCopyReleasePtr */ - -/****************************************************************************** -** Name: CFE_SB_ZeroCopyReleaseDesc -** -** Purpose: API used for releasing a zero copy descriptor (for zero copy mode -** only). -** -** Assumptions, External Events, and Notes: -** None -** -** Date Written: -** 04/25/2005 -** -** Input Arguments: -** Ptr2Release -** BufferHandle -** -** Output Arguments: -** None -** -** Return Values: -** Status -** -******************************************************************************/ -int32 CFE_SB_ZeroCopyReleaseDesc(CFE_SB_Buffer_t *Ptr2Release, - CFE_SB_ZeroCopyHandle_t BufferHandle) -{ - int32 Stat; - CFE_SB_ZeroCopyD_t *zcd = (CFE_SB_ZeroCopyD_t *) BufferHandle; - - CFE_SB_LockSharedData(__func__,__LINE__); - - Stat = CFE_ES_GetPoolBufInfo(CFE_SB_Global.Mem.PoolHdl, zcd); - - if((Ptr2Release == NULL) || (Stat < 0) || (zcd->Buffer != (void *)Ptr2Release)){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - return CFE_SB_BUFFER_INVALID; - } - - /* delink the descriptor */ - if(zcd->Prev != NULL){ - ((CFE_SB_ZeroCopyD_t *) (zcd->Prev))->Next = zcd->Next; - } - if(zcd->Next != NULL){ - ((CFE_SB_ZeroCopyD_t *) (zcd->Next))->Prev = zcd->Prev; - } - if(CFE_SB_Global.ZeroCopyTail == (void *)zcd){ - CFE_SB_Global.ZeroCopyTail = zcd->Prev; - } - - /* give the descriptor back to the buffer pool */ - Stat = CFE_ES_PutPoolBuf(CFE_SB_Global.Mem.PoolHdl, zcd); - if(Stat > 0){ - /* Substract the size of the actual buffer from the Memory in use ctr */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse-=Stat; - }/* end if */ - - CFE_SB_UnlockSharedData(__func__,__LINE__); - - return CFE_SUCCESS; - -}/* end CFE_SB_ZeroCopyReleaseDesc */ - /* * Function CFE_SB_TransmitBuffer - See API and header file for details */ @@ -2261,54 +2246,53 @@ int32 CFE_SB_TransmitBuffer(CFE_SB_Buffer_t *BufPtr, bool IncrementSequenceCount) { int32 Status; - CFE_MSG_Size_t Size = 0; - CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; CFE_SB_BufferD_t *BufDscPtr; CFE_SBR_RouteId_t RouteId; - CFE_MSG_Type_t MsgType; - /* Release zero copy handle */ - Status = CFE_SB_ZeroCopyReleaseDesc(BufPtr, ZeroCopyHandle); + Status = CFE_SB_ZeroCopyHandleValidate(BufPtr, ZeroCopyHandle); if (Status == CFE_SUCCESS) { - Status = CFE_SB_TransmitMsgValidate(&BufPtr->Msg, &MsgId, &Size, &RouteId); + /* Get actual buffer descriptor pointer from zero copy handle */ + BufDscPtr = ZeroCopyHandle.BufDscPtr; + + /* Validate the content and get the MsgId, store it in the descriptor */ + Status = CFE_SB_TransmitMsgValidate(&BufPtr->Msg, &BufDscPtr->MsgId, &BufDscPtr->ContentSize, &RouteId); - /* Send if route exists */ + /* + * Broadcast the message if validation succeeded. + * + * Note that for the case of no subscribers, the validation returns CFE_SUCCESS + * but the actual route ID may be invalid. This is OK and considered normal- + * the validation will increment the NoSubscribers count, but we should NOT + * increment the MsgSendErrorCounter here - it is not really a sending error to + * have no subscribers. CFE_SB_BroadcastBufferToRoute() will not send to + * anything if the route is not valid (benign). + */ if (Status == CFE_SUCCESS) { - /* Get buffer descriptor pointer */ - BufDscPtr = CFE_SB_GetBufferFromCaller(MsgId, BufPtr); + BufDscPtr->AutoSequence = IncrementSequenceCount; + CFE_MSG_GetType(&BufPtr->Msg, &BufDscPtr->ContentType); - if(CFE_SBR_IsValidRouteId(RouteId)) - { - /* For Tlm packets, increment the seq count if requested */ - CFE_MSG_GetType(&BufPtr->Msg, &MsgType); - if((MsgType == CFE_MSG_Type_Tlm) && IncrementSequenceCount) - { - CFE_SBR_IncrementSequenceCounter(RouteId); - CFE_MSG_SetSequenceCount(&BufPtr->Msg, CFE_SBR_GetSequenceCounter(RouteId)); - } + /* Now broadcast the message, which consumes the buffer */ + CFE_SB_BroadcastBufferToRoute(BufDscPtr, RouteId); - Status = CFE_SB_TransmitBufferFull(BufDscPtr, RouteId, MsgId); - } - else - { - /* Decrement use count if transmit buffer full not called */ - CFE_SB_LockSharedData(__func__, __LINE__); - CFE_SB_DecrBufUseCnt(BufDscPtr); - CFE_SB_UnlockSharedData(__func__, __LINE__); - } - } - else - { - /* Increment send error counter for validation failure */ - CFE_SB_LockSharedData(__func__, __LINE__); - CFE_SB_Global.HKTlmMsg.Payload.MsgSendErrorCounter++; - CFE_SB_UnlockSharedData(__func__, __LINE__); + /* + * IMPORTANT - the descriptor might be freed at any time after this, + * so the descriptor should not be accessed again after this point. + */ + BufDscPtr = NULL; } } + if (Status != CFE_SUCCESS) + { + /* Increment send error counter for validation failure */ + CFE_SB_LockSharedData(__func__, __LINE__); + CFE_SB_Global.HKTlmMsg.Payload.MsgSendErrorCounter++; + CFE_SB_UnlockSharedData(__func__, __LINE__); + } + return Status; } diff --git a/fsw/cfe-core/src/sb/cfe_sb_buf.c b/fsw/cfe-core/src/sb/cfe_sb_buf.c index 03424e1da..ab87523e9 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_buf.c +++ b/fsw/cfe-core/src/sb/cfe_sb_buf.c @@ -39,6 +39,55 @@ #include "cfe_es.h" #include "cfe_error.h" +/* + * The actual message content of a SB Buffer Descriptor is the + * offset of the content member. This will be auto-aligned by + * the compiler according to the requirements of the machine. + */ +#define CFE_SB_BUFFERD_CONTENT_OFFSET (offsetof(CFE_SB_BufferD_t,Content)) + + +/****************************************************************************** + * + * Helper function to reset/clear the links on a list node (make empty) + */ +void CFE_SB_TrackingListReset(CFE_SB_BufferLink_t *Link) +{ + /* A singleton node/empty list points to itself */ + Link->Prev = Link; + Link->Next = Link; +} + +/****************************************************************************** + * + * Helper function to remove a node from a tracking list + */ +void CFE_SB_TrackingListRemove(CFE_SB_BufferLink_t *Node) +{ + /* Remove from list */ + Node->Prev->Next = Node->Next; + Node->Next->Prev = Node->Prev; + + /* The node is now a singleton */ + CFE_SB_TrackingListReset(Node); +} + +/****************************************************************************** + * + * Helper function to add a node to a tracking list + */ +void CFE_SB_TrackingListAdd(CFE_SB_BufferLink_t *List, CFE_SB_BufferLink_t *Node) +{ + /* Connect this node to the list at "prev" position (tail) */ + Node->Prev = List->Prev; + Node->Next = List; + + /* Connect list nodes to this node */ + Node->Prev->Next = Node; + Node->Next->Prev = Node; +} + + /****************************************************************************** ** Function: CFE_SB_GetBufferFromPool() ** @@ -48,82 +97,60 @@ ** by the SB to dynamically allocate memory to hold the message and a buffer ** descriptor associated with the message during the sending of a message. ** +** Note: +** This must only be invoked while holding the SB global lock +** ** Arguments: -** msgId : Message ID -** size : Size of the buffer in bytes. +** MaxMsgSize : Size of the buffer content area in bytes. ** ** Return: ** Pointer to the buffer descriptor for the new buffer, or NULL if the buffer ** could not be allocated. */ -CFE_SB_BufferD_t * CFE_SB_GetBufferFromPool(CFE_SB_MsgId_t MsgId, size_t Size) { - int32 stat1; - uint8 *address = NULL; - CFE_SB_BufferD_t *bd = NULL; +CFE_SB_BufferD_t *CFE_SB_GetBufferFromPool(size_t MaxMsgSize) +{ + int32 stat1; + size_t AllocSize; + CFE_SB_BufferD_t *bd = NULL; + + /* The allocation needs to include enough space for the descriptor object */ + AllocSize = MaxMsgSize + CFE_SB_BUFFERD_CONTENT_OFFSET; /* Allocate a new buffer descriptor from the SB memory pool.*/ - stat1 = CFE_ES_GetPoolBuf((CFE_ES_MemPoolBuf_t*)&bd, CFE_SB_Global.Mem.PoolHdl, Size + sizeof(CFE_SB_BufferD_t)); - if(stat1 < 0){ + stat1 = CFE_ES_GetPoolBuf((CFE_ES_MemPoolBuf_t *)&bd, CFE_SB_Global.Mem.PoolHdl, AllocSize); + if (stat1 < 0) + { return NULL; } /* increment the number of buffers in use and adjust the high water mark if needed */ CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse++; - if(CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse){ + if (CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse) + { CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse = CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse; - }/* end if */ + } /* end if */ /* Add the size of the actual buffer to the memory-in-use ctr and */ /* adjust the high water mark if needed */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse+=stat1; - if(CFE_SB_Global.StatTlmMsg.Payload.MemInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse){ + CFE_SB_Global.StatTlmMsg.Payload.MemInUse += AllocSize; + if (CFE_SB_Global.StatTlmMsg.Payload.MemInUse > CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse) + { CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse = CFE_SB_Global.StatTlmMsg.Payload.MemInUse; - }/* end if */ - - /* first set ptr to actual msg buffer the same as ptr to descriptor */ - address = (uint8 *)bd; - - /* increment actual msg buffer ptr beyond the descriptor */ - address += sizeof(CFE_SB_BufferD_t); + } /* end if */ /* Initialize the buffer descriptor structure. */ - bd->MsgId = MsgId; - bd->UseCount = 1; - bd->Size = Size; - bd->Buffer = (CFE_SB_Buffer_t *)address; + memset(bd, 0, CFE_SB_BUFFERD_CONTENT_OFFSET); - return bd; - -}/* CFE_SB_GetBufferFromPool */ - - -/****************************************************************************** -** Function: CFE_SB_GetBufferFromCaller() -** -** Purpose: -** Request a buffer from the SB buffer pool to use as a buffer descriptor -** for and already created SB buffer. -** -** Arguments: -** msgId : Message ID -** Address : Address of the buffer -** -** Return: -** Pointer to the buffer descriptor for the suplied buffer, or NULL if the -** descriptor could not be allocated. -*/ - -CFE_SB_BufferD_t * CFE_SB_GetBufferFromCaller(CFE_SB_MsgId_t MsgId, - void *Address) { - CFE_SB_BufferD_t *bd = (CFE_SB_BufferD_t *)((cpuaddr)Address - sizeof(CFE_SB_BufferD_t)); + bd->MsgId = CFE_SB_INVALID_MSG_ID; + bd->UseCount = 1; + bd->AllocatedSize = AllocSize; - /* Initialize the MsgId in the buffer descriptor (the rest has already been initialized in this case). */ - bd->MsgId = MsgId; + CFE_SB_TrackingListReset(&bd->Link); return bd; -}/* CFE_SB_GetBufferFromCaller */ +} /* CFE_SB_GetBufferFromPool */ /****************************************************************************** @@ -134,24 +161,25 @@ CFE_SB_BufferD_t * CFE_SB_GetBufferFromCaller(CFE_SB_MsgId_t MsgId, ** One block is the memory used to store the actual message, the other block ** was used to store the buffer descriptor for the message. ** +** Note: +** This must only be invoked while holding the SB global lock +** ** Arguments: ** bd : Pointer to the buffer descriptor. ** ** Return: -** SB status +** None */ -int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd){ - int32 Stat; +void CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd) +{ + /* Remove from any tracking list (no effect if not in a list) */ + CFE_SB_TrackingListRemove(&bd->Link); - /* give the buf descriptor back to the buf descriptor pool */ - Stat = CFE_ES_PutPoolBuf(CFE_SB_Global.Mem.PoolHdl, bd); - if(Stat > 0){ - CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse--; - /* Substract the size of a buffer descriptor from the Memory in use ctr */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse-=Stat; - }/* end if */ + --CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse; + CFE_SB_Global.StatTlmMsg.Payload.MemInUse -= bd->AllocatedSize; - return CFE_SUCCESS; + /* finally give the buf descriptor back to the buf descriptor pool */ + CFE_ES_PutPoolBuf(CFE_SB_Global.Mem.PoolHdl, bd); }/* end CFE_SB_ReturnBufferToPool */ @@ -166,6 +194,8 @@ int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd){ ** UseCount is a variable in the CFE_SB_BufferD_t and is used only to ** determine when a buffer may be returned to the memory pool. ** +** This must only be invoked while holding the SB global lock +** ** Arguments: ** bd : Pointer to the buffer descriptor. ** @@ -195,6 +225,8 @@ void CFE_SB_IncrBufUseCnt(CFE_SB_BufferD_t *bd) ** UseCount is a variable in the CFE_SB_BufferD_t and is used only to ** determine when a buffer may be returned to the memory pool. ** +** This must only be invoked while holding the SB global lock +** ** Arguments: ** bd : Pointer to the buffer descriptor. ** @@ -224,6 +256,9 @@ void CFE_SB_DecrBufUseCnt(CFE_SB_BufferD_t *bd) ** Purpose: ** This function gets a destination descriptor from the SB memory pool. ** +** Note: +** This must only be invoked while holding the SB global lock +** ** Arguments: ** None ** @@ -259,6 +294,9 @@ CFE_SB_DestinationD_t *CFE_SB_GetDestinationBlk(void) ** Purpose: ** This function returns a destination descriptor to the SB memory pool. ** +** Note: +** This must only be invoked while holding the SB global lock +** ** Arguments: ** None ** diff --git a/fsw/cfe-core/src/sb/cfe_sb_init.c b/fsw/cfe-core/src/sb/cfe_sb_init.c index 97a4339d4..561f88b48 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_init.c +++ b/fsw/cfe-core/src/sb/cfe_sb_init.c @@ -118,8 +118,6 @@ int32 CFE_SB_EarlyInit (void) { CFE_SB_ValueToMsgId(CFE_SB_STATS_TLM_MID), sizeof(CFE_SB_Global.StatTlmMsg)); - CFE_SB_Global.ZeroCopyTail = NULL; - return Stat; }/* end CFE_SB_EarlyInit */ @@ -156,6 +154,12 @@ int32 CFE_SB_InitBuffers(void) { (unsigned long)CFE_SB_Global.Mem.Partition.Data,CFE_PLATFORM_SB_BUF_MEMORY_BYTES,(unsigned int)Stat); return Stat; } + + /* + * Initialize the buffer tracking lists to be empty + */ + CFE_SB_TrackingListReset(&CFE_SB_Global.InTransitList); + CFE_SB_TrackingListReset(&CFE_SB_Global.ZeroCopyList); return CFE_SUCCESS; diff --git a/fsw/cfe-core/src/sb/cfe_sb_priv.c b/fsw/cfe-core/src/sb/cfe_sb_priv.c index 2a67924aa..fa478e631 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_priv.c +++ b/fsw/cfe-core/src/sb/cfe_sb_priv.c @@ -535,20 +535,43 @@ void CFE_SB_RemoveDestNode(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *Nod ******************************************************************************/ int32 CFE_SB_ZeroCopyReleaseAppId(CFE_ES_AppId_t AppId) { - CFE_SB_ZeroCopyD_t *prev = NULL; - CFE_SB_ZeroCopyD_t *zcd = (CFE_SB_ZeroCopyD_t *) (CFE_SB_Global.ZeroCopyTail); + CFE_SB_BufferLink_t *NextLink; + CFE_SB_BufferD_t *DscPtr; + + /* + * First go through the "ZeroCopy" tracking list and find all nodes + * with a matching AppID. This needs to be done while locked to + * prevent other tasks from changing the list at the same time. + */ + if (CFE_RESOURCEID_TEST_DEFINED(AppId)) + { + CFE_SB_LockSharedData(__func__, __LINE__); - while(zcd != NULL){ - prev = (CFE_SB_ZeroCopyD_t *) (zcd->Prev); - if( CFE_RESOURCEID_TEST_EQUAL(zcd->AppID, AppId) ) + /* Get start of list */ + NextLink = CFE_SB_TrackingListGetNext(&CFE_SB_Global.ZeroCopyList); + while(!CFE_SB_TrackingListIsEnd(&CFE_SB_Global.ZeroCopyList, NextLink)) { - CFE_SB_ZeroCopyReleasePtr((CFE_SB_Buffer_t *) zcd->Buffer, (CFE_SB_ZeroCopyHandle_t) zcd); + /* Get buffer descriptor pointer */ + /* NOTE: casting via void* here rather than CFE_SB_BufferD_t* avoids a false + * alignment warning on platforms with strict alignment requirements */ + DscPtr = (void *)NextLink; + + /* Read the next link now in case this node gets moved */ + NextLink = CFE_SB_TrackingListGetNext(NextLink); + + /* Check if it is a zero-copy buffer owned by this app */ + if (CFE_RESOURCEID_TEST_EQUAL(DscPtr->AppId, AppId)) + { + /* If so, decrement the use count as the app has now gone away */ + CFE_SB_DecrBufUseCnt(DscPtr); + } } - zcd = prev; + + CFE_SB_UnlockSharedData(__func__, __LINE__); } return CFE_SUCCESS; -}/* end CFE_SB_ZeroCopyReleasePtr */ +}/* end CFE_SB_ZeroCopyReleaseAppId */ /*****************************************************************************/ diff --git a/fsw/cfe-core/src/sb/cfe_sb_priv.h b/fsw/cfe-core/src/sb/cfe_sb_priv.h index d01ab0b5d..de6e5096f 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_priv.h +++ b/fsw/cfe-core/src/sb/cfe_sb_priv.h @@ -98,6 +98,17 @@ ** Type Definitions */ + +/** + * \brief Basic linked list structure allowing all buffer descriptors to be tracked. + */ +typedef struct CFE_SB_BufferLink +{ + struct CFE_SB_BufferLink *Next; + struct CFE_SB_BufferLink *Prev; + +} CFE_SB_BufferLink_t; + /****************************************************************************** ** Typedef: CFE_SB_BufferD_t ** @@ -108,32 +119,45 @@ ** Note: Changing the size of this structure may require the memory pool ** block sizes to change. */ +typedef struct CFE_SB_BufferD +{ + CFE_SB_BufferLink_t Link; /**< Links for inclusion in the tracking lists */ + + /** + * Actual MsgId of the content, cached here to avoid repeat + * calls into CFE_MSG API during traversal/delivery of the message. + * + * MsgId is set for buffers which contain actual data in transit. AppId is unset + * while in transit, as it may be sent to multiple apps. + * + * During zero copy buffer initial allocation, the MsgId is not known at this time + * and should be set to the invalid msg ID. + */ + CFE_SB_MsgId_t MsgId; + + /** + * Current owner of the buffer, if owned by a single app. + * + * This is used to track "zero copy" buffer allocations - this will be set to + * the AppID that initally allocated it, before it is used to transmit a message. + * + * When the message is in transit, it may be queued to multiple applictions, + * so this is unset. + */ + CFE_ES_AppId_t AppId; + + size_t AllocatedSize; /**< Total size of this descriptor (including descriptor itself) */ + size_t ContentSize; /**< Actual size of message content currently stored in the buffer */ + CFE_MSG_Type_t ContentType; /**< Type of message content currently stored in the buffer */ + + bool AutoSequence; /**< If message should get its sequence number assigned from the route */ + + uint16 UseCount; /**< Number of active references to this buffer in the system */ + + CFE_SB_Buffer_t Content; /* Variably sized content field, Keep last */ -typedef struct { - CFE_SB_MsgId_t MsgId; - uint16 UseCount; - size_t Size; - CFE_SB_Buffer_t *Buffer; } CFE_SB_BufferD_t; -/****************************************************************************** -** Typedef: CFE_SB_ZeroCopyD_t -** -** Purpose: -** This structure defines a ZERO COPY BUFFER DESCRIPTOR used to specify -** the buffer provided to a requestor. -** -** Note: Changing the size of this structure may require the memory pool -** block sizes to change. -*/ - -typedef struct { - CFE_ES_AppId_t AppID; - size_t Size; - void *Buffer; - void *Next; - void *Prev; -} CFE_SB_ZeroCopyD_t; /****************************************************************************** ** Typedef: CFE_SB_PipeD_t @@ -219,7 +243,6 @@ typedef struct uint32 SubscriptionReporting; CFE_ES_AppId_t AppId; uint32 StopRecurseFlags[OS_MAX_TASKS]; - void *ZeroCopyTail; CFE_SB_PipeD_t PipeTbl[CFE_PLATFORM_SB_MAX_PIPES]; CFE_SB_HousekeepingTlm_t HKTlmMsg; CFE_SB_StatsTlm_t StatTlmMsg; @@ -231,6 +254,13 @@ typedef struct CFE_ResourceId_t LastPipeId; CFE_SB_BackgroundFileStateInfo_t BackgroundFile; + + /* A list of buffers currently in-transit, owned by SB */ + CFE_SB_BufferLink_t InTransitList; + + /* A list of buffers currently issued to apps for zero-copy */ + CFE_SB_BufferLink_t ZeroCopyList; + } CFE_SB_Global_t; @@ -273,13 +303,10 @@ void CFE_SB_UnlockSharedData(const char *FuncName, int32 LineNumber); void CFE_SB_ReleaseBuffer (CFE_SB_BufferD_t *bd, CFE_SB_DestinationD_t *dest); int32 CFE_SB_WriteQueue(CFE_SB_PipeD_t *pd,uint32 TskId, const CFE_SB_BufferD_t *bd,CFE_SB_MsgId_t MsgId ); -int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd); void CFE_SB_ProcessCmdPipePkt(CFE_SB_Buffer_t *SBBufPtr); void CFE_SB_ResetCounters(void); void CFE_SB_SetMsgSeqCnt(CFE_MSG_Message_t *MsgPtr,uint32 Count); char *CFE_SB_GetAppTskName(CFE_ES_TaskId_t TaskId, char* FullName); -CFE_SB_BufferD_t *CFE_SB_GetBufferFromPool(CFE_SB_MsgId_t MsgId, size_t Size); -CFE_SB_BufferD_t *CFE_SB_GetBufferFromCaller(CFE_SB_MsgId_t MsgId, void *Address); int32 CFE_SB_DeletePipeWithAppId(CFE_SB_PipeId_t PipeId,CFE_ES_AppId_t AppId); int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_AppId_t AppId); int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, @@ -293,14 +320,10 @@ int32 CFE_SB_UnsubscribeWithAppId(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId, int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId, uint8 Scope, CFE_ES_AppId_t AppId); -int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, - CFE_SBR_RouteId_t RouteId, - CFE_SB_MsgId_t MsgId); int32 CFE_SB_TransmitMsgValidate(CFE_MSG_Message_t *MsgPtr, CFE_SB_MsgId_t *MsgIdPtr, CFE_MSG_Size_t *SizePtr, CFE_SBR_RouteId_t *RouteIdPtr); -int32 CFE_SB_ZeroCopyReleaseDesc(CFE_SB_Buffer_t *Ptr2Release, CFE_SB_ZeroCopyHandle_t BufferHandle); int32 CFE_SB_ZeroCopyReleaseAppId(CFE_ES_AppId_t AppId); void CFE_SB_IncrBufUseCnt(CFE_SB_BufferD_t *bd); void CFE_SB_DecrBufUseCnt(CFE_SB_BufferD_t *bd); @@ -314,6 +337,110 @@ void CFE_SB_FinishSendEvent(CFE_ES_TaskId_t TaskId, uint32 Bit); CFE_SB_DestinationD_t *CFE_SB_GetDestinationBlk(void); int32 CFE_SB_PutDestinationBlk(CFE_SB_DestinationD_t *Dest); +/** + * \brief For SB buffer tracking, get first/next position in a list + */ +static inline CFE_SB_BufferLink_t *CFE_SB_TrackingListGetNext(CFE_SB_BufferLink_t *Node) +{ + return Node->Next; +} + +/** + * \brief For SB buffer tracking, checks if this current position represents the end of the list + */ +static inline bool CFE_SB_TrackingListIsEnd(CFE_SB_BufferLink_t *List, CFE_SB_BufferLink_t *Node) +{ + /* Normally list nodes should never have NULL, buf if they do, do not follow it */ + return (Node == NULL || Node == List); +} + +/** + * \brief For SB buffer tracking, reset link state to default + * + * This turns the node into a singleton/lone object (not in a list) + * or resets the head link to be empty. + */ +void CFE_SB_TrackingListReset(CFE_SB_BufferLink_t *Link); + +/** + * \brief For SB buffer tracking, removes a node from a tracking list + * + * Extracts a single node from whatever list it is in. After this the + * node becomes a singleton owned by the caller. It may be put into + * another list or freed. + */ +void CFE_SB_TrackingListRemove(CFE_SB_BufferLink_t *Node); + +/** + * \brief For SB buffer tracking, adds a node to a tracking list + * + * Extracts a single node from the list its in. After this the + * node becomes a singleton owned by the caller. It must put it + * in another list or free it. + */ +void CFE_SB_TrackingListAdd(CFE_SB_BufferLink_t *List, CFE_SB_BufferLink_t *Node); + + +/** + * \brief Allocates a new buffer descriptor from the SB memory pool. + * + * \param[in] MaxMsgSize Maximum message content size that the buffer must be capable of holding + * \returns Pointer to buffer descriptor, or NULL on failure. + */ +CFE_SB_BufferD_t *CFE_SB_GetBufferFromPool(size_t MaxMsgSize); + +/** + * \brief Returns a buffer to SB memory pool + * + * \param[in] Pointer to descriptor to return + */ +void CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd); + +/** + * \brief Broadcast a SB buffer descriptor to all destinations in route + * + * Internal routine that implements the logic of transmitting a message buffer + * to all destinations subscribed in the SB route. + * + * As this function will broadcast the message to any number of destinations (0-many), + * and some may be successful and some may fail, the status cannot be expressed + * in any single error code, so this does not return any status. + * + * Instead, this routine handles all potential outcomes on its own, and does + * not expect the caller to handle any delivery issues. Also note that the general + * design pattern of the software bus is a "send and forget" model where the sender does + * not know (or care) what entities are subscribed to the data being generated. + * + * - For any undeliverable destination (limit, OSAL error, etc), a proper event is generated. + * - For any successful queueing, the buffer use count is incremented + * + * The caller is expected to hold a reference (use count) of the buffer prior to invoking + * this routine, representing itself, which is then consumed by this routine. + * + * \note _This call will "consume" the buffer by decrementing the buffer use count_ after + * broadcasting the message to all subscribed pipes. + * + * The caller should not access the buffer again after calling this function, as it may + * be deallocated at any time. If the caller wishes to continue accessing the buffer, + * it should explicitly increment the use count before calling this, which will prevent + * deallocation. + * + * \param[in] BufDscPtr Pointer to the buffer descriptor to broadcast + * \param[in] RouteId Route to send to + */ +void CFE_SB_BroadcastBufferToRoute(CFE_SB_BufferD_t *BufDscPtr, CFE_SBR_RouteId_t RouteId); + +/** + * \brief Perform basic sanity check on the Zero Copy handle + * + * \param[in] BufPtr pointer to the content buffer + * \param[in] ZeroCopyHandle Zero copy handle to check + * + * \returns CFE_SUCCESS if validation passed, or error code. + */ +int32 CFE_SB_ZeroCopyHandleValidate(CFE_SB_Buffer_t *BufPtr, + CFE_SB_ZeroCopyHandle_t ZeroCopyHandle); + /** * \brief Add a destination node * diff --git a/fsw/cfe-core/src/sb/cfe_sb_util.c b/fsw/cfe-core/src/sb/cfe_sb_util.c index 654f5f47b..e8501a49b 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_util.c +++ b/fsw/cfe-core/src/sb/cfe_sb_util.c @@ -39,6 +39,7 @@ #include "osapi.h" #include "cfe_error.h" #include "cfe_msg_api.h" +#include "cfe_es.h" #include @@ -75,6 +76,11 @@ size_t CFE_SB_MsgHdrSize(const CFE_MSG_Message_t *MsgPtr) bool hassechdr = false; CFE_MSG_Type_t type = CFE_MSG_Type_Invalid; + if (MsgPtr == NULL) + { + return CFE_SB_BAD_ARGUMENT; + } + CFE_MSG_GetHasSecondaryHeader(MsgPtr, &hassechdr); CFE_MSG_GetType(MsgPtr, &type); @@ -106,6 +112,11 @@ void *CFE_SB_GetUserData(CFE_MSG_Message_t *MsgPtr) uint8 *BytePtr; size_t HdrSize; + if(MsgPtr == NULL){ + CFE_ES_WriteToSysLog("CFE_SB:GetUserData-Failed invalid arguments\n"); + return 0; + } + BytePtr = (uint8 *)MsgPtr; HdrSize = CFE_SB_MsgHdrSize(MsgPtr); @@ -121,6 +132,11 @@ size_t CFE_SB_GetUserDataLength(const CFE_MSG_Message_t *MsgPtr) CFE_MSG_Size_t TotalMsgSize; size_t HdrSize; + if (MsgPtr == NULL) + { + return CFE_SB_BAD_ARGUMENT; + } + CFE_MSG_GetSize(MsgPtr, &TotalMsgSize); HdrSize = CFE_SB_MsgHdrSize(MsgPtr); @@ -136,11 +152,22 @@ void CFE_SB_SetUserDataLength(CFE_MSG_Message_t *MsgPtr, size_t DataLength) CFE_MSG_Size_t TotalMsgSize; size_t HdrSize; - HdrSize = CFE_SB_MsgHdrSize(MsgPtr); - TotalMsgSize = HdrSize + DataLength; + if(MsgPtr == NULL){ + CFE_ES_WriteToSysLog("CFE_SB:SetUserDataLength-Failed invalid arguments\n"); + } + else + { + HdrSize = CFE_SB_MsgHdrSize(MsgPtr); + TotalMsgSize = HdrSize + DataLength; - CFE_MSG_SetSize(MsgPtr, TotalMsgSize); - + if(TotalMsgSize <= CFE_MISSION_SB_MAX_SB_MSG_SIZE){ + CFE_MSG_SetSize(MsgPtr, TotalMsgSize); + } + else + { + CFE_ES_WriteToSysLog("CFE_SB:SetUserDataLength-Failed TotalMsgSize too large\n"); + } + } }/* end CFE_SB_SetUserDataLength */ #ifndef CFE_OMIT_DEPRECATED_6_8 @@ -288,7 +315,7 @@ int32 CFE_SB_MessageStringGet(char *DestStringPtr, const char *SourceStringPtr, * Cannot terminate the string, since there is no place for the NUL * In this case, do nothing */ - if (DestMaxSize == 0) + if (DestMaxSize == 0 || DestStringPtr == NULL ) { Result = CFE_SB_BAD_ARGUMENT; } @@ -335,28 +362,35 @@ int32 CFE_SB_MessageStringSet(char *DestStringPtr, const char *SourceStringPtr, { int32 Result; - Result = 0; - - while (SourceMaxSize > 0 && *SourceStringPtr != 0 && DestMaxSize > 0) + if (SourceStringPtr == NULL || DestStringPtr == NULL ) { - *DestStringPtr = *SourceStringPtr; - ++DestStringPtr; - ++SourceStringPtr; - ++Result; - --DestMaxSize; - --SourceMaxSize; + Result = CFE_SB_BAD_ARGUMENT; } - - /* - * Pad the remaining space with NUL chars, - * but this should NOT be included in the final size - */ - while (DestMaxSize > 0) + else { - /* Put the NUL in the last character */ - *DestStringPtr = 0; - ++DestStringPtr; - --DestMaxSize; + Result = 0; + + while (SourceMaxSize > 0 && *SourceStringPtr != 0 && DestMaxSize > 0) + { + *DestStringPtr = *SourceStringPtr; + ++DestStringPtr; + ++SourceStringPtr; + ++Result; + --DestMaxSize; + --SourceMaxSize; + } + + /* + * Pad the remaining space with NUL chars, + * but this should NOT be included in the final size + */ + while (DestMaxSize > 0) + { + /* Put the NUL in the last character */ + *DestStringPtr = 0; + ++DestStringPtr; + --DestMaxSize; + } } return Result; diff --git a/fsw/cfe-core/src/tbl/cfe_tbl_api.c b/fsw/cfe-core/src/tbl/cfe_tbl_api.c index 6e70c020e..1b58a2e69 100644 --- a/fsw/cfe-core/src/tbl/cfe_tbl_api.c +++ b/fsw/cfe-core/src/tbl/cfe_tbl_api.c @@ -66,6 +66,11 @@ int32 CFE_TBL_Register( CFE_TBL_Handle_t *TblHandlePtr, char TblName[CFE_TBL_MAX_FULL_NAME_LEN] = {""}; CFE_TBL_Handle_t AccessIndex; + if (TblHandlePtr == NULL || Name == NULL) + { + return CFE_TBL_BAD_ARGUMENT; + } + /* Check to make sure calling application is legit */ Status = CFE_ES_GetAppID(&ThisAppId); @@ -522,6 +527,11 @@ int32 CFE_TBL_Share( CFE_TBL_Handle_t *TblHandlePtr, CFE_TBL_RegistryRec_t *RegRecPtr = NULL; char AppName[OS_MAX_API_NAME] = {"UNKNOWN"}; + if (TblHandlePtr == NULL || TblName == NULL) + { + return CFE_TBL_BAD_ARGUMENT; + } + /* Get a valid Application ID for calling App */ Status = CFE_ES_GetAppID(&ThisAppId); @@ -692,6 +702,11 @@ int32 CFE_TBL_Load( CFE_TBL_Handle_t TblHandle, char AppName[OS_MAX_API_NAME] = {"UNKNOWN"}; bool FirstTime = false; + if (SrcDataPtr == NULL) + { + return CFE_TBL_BAD_ARGUMENT; + } + /* Verify access rights and get a valid Application ID for calling App */ Status = CFE_TBL_ValidateAccess(TblHandle, &ThisAppId); @@ -1000,6 +1015,11 @@ int32 CFE_TBL_GetAddress( void **TblPtr, int32 Status; CFE_ES_AppId_t ThisAppId; + if (TblPtr == NULL) + { + return CFE_TBL_BAD_ARGUMENT; + } + /* Assume failure at returning the table address */ *TblPtr = NULL; @@ -1066,6 +1086,11 @@ int32 CFE_TBL_GetAddresses( void **TblPtrs[], int32 Status; CFE_ES_AppId_t ThisAppId; + if (TblPtrs == NULL) + { + return CFE_TBL_BAD_ARGUMENT; + } + /* Assume failure at returning the table addresses */ for (i=0; i %s", OutBuffer); + + /* Same but as a default input, rather than in the buffer */ + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, NULL, sizeof(OutBuffer), 0, TEST_DEFAULT_INPUT, + TEST_DEFAULT_PATH, TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, TEST_DEFAULT_INPUT, "Fully-qualified pass thru -> %s", OutBuffer); + + /* nominal with no path input */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_NO_PATH, sizeof(OutBuffer), + sizeof(TEST_INPUT_NO_PATH), TEST_DEFAULT_INPUT, TEST_DEFAULT_PATH, + TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/dflpath/file.log", "No Path input -> %s", OutBuffer); + + /* nominal with no path input - should remove duplicate path separators */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_XTRA_SEPARATOR_PATH, sizeof(OutBuffer), + sizeof(TEST_XTRA_SEPARATOR_PATH), TEST_DEFAULT_INPUT, + TEST_DEFAULT_PATH, TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/xtra/sep/file.log", "No Path input, extra separators -> %s", OutBuffer); + + /* nominal with no extension input */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_NO_EXTENSION, sizeof(OutBuffer), + sizeof(TEST_INPUT_NO_EXTENSION), TEST_DEFAULT_INPUT, + TEST_DEFAULT_PATH, TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/path/to/file.dflext", "No Extension input -> %s", OutBuffer); + + /* nominal with no extension input, no separator (should be added) */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_NO_EXTENSION, sizeof(OutBuffer), + sizeof(TEST_INPUT_NO_EXTENSION), TEST_DEFAULT_INPUT, + TEST_DEFAULT_PATH, TEST_NO_SEPARATOR), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/path/to/file.nosep", "No Extension input, no separator -> %s", OutBuffer); + + /* nominal with neither path nor extension input */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_BASENAME, sizeof(OutBuffer), + sizeof(TEST_INPUT_BASENAME), TEST_DEFAULT_INPUT, TEST_DEFAULT_PATH, + TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/dflpath/file.dflext", "No Path nor Extension input -> %s", OutBuffer); + + /* Bad arguments for buffer pointer/size */ + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(NULL, TEST_INPUT_BASENAME, sizeof(OutBuffer), + sizeof(TEST_INPUT_BASENAME), NULL, NULL, NULL), + CFE_FS_BAD_ARGUMENT); + UtAssert_INT32_EQ( + CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_BASENAME, 0, sizeof(TEST_INPUT_BASENAME), NULL, NULL, NULL), + CFE_FS_BAD_ARGUMENT); + + /* Bad arguments for input */ + UtAssert_INT32_EQ( + CFE_FS_ParseInputFileNameEx(OutBuffer, NULL, sizeof(OutBuffer), 0, NULL, NULL, TEST_DEFAULT_EXTENSION), + CFE_FS_INVALID_PATH); + + /* Cases where the file name itself is actually an empty string */ + UtAssert_INT32_EQ( + CFE_FS_ParseInputFileNameEx(OutBuffer, "", sizeof(OutBuffer), 10, NULL, NULL, TEST_DEFAULT_EXTENSION), + CFE_FS_INVALID_PATH); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, "/path/", sizeof(OutBuffer), 10, NULL, TEST_DEFAULT_PATH, + TEST_DEFAULT_EXTENSION), + CFE_FS_INVALID_PATH); + + /* if the default path/extension is null it is just ignored, not an error. */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_BASENAME, sizeof(OutBuffer), + sizeof(TEST_INPUT_BASENAME), NULL, NULL, TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + /* If no path this still adds a leading / */ + UtAssert_StrCmp(OutBuffer, "/file.dflext", "No Path nor default -> %s", OutBuffer); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_BASENAME, sizeof(OutBuffer), + sizeof(TEST_INPUT_BASENAME), NULL, TEST_DEFAULT_PATH, NULL), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/dflpath/file", "No Extension nor default -> %s", OutBuffer); + + /* test corner case for termination where result fits exactly, including NUL (should work) */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_NO_PATH, 18, sizeof(TEST_INPUT_NO_PATH), NULL, + TEST_DEFAULT_PATH, TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/dflpath/file.log", "Exact Length input -> %s", OutBuffer); + UtAssert_INT32_EQ(OutBuffer[18], 0x7F); /* Confirm character after buffer was not touched */ + + /* test corner case for termination where result itself fits but cannot fit NUL char (should be error) */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_NO_PATH, 17, sizeof(TEST_INPUT_NO_PATH), NULL, + TEST_DEFAULT_PATH, TEST_DEFAULT_EXTENSION), + CFE_FS_FNAME_TOO_LONG); + UtAssert_INT32_EQ(OutBuffer[17], 0x7F); /* Confirm character after buffer was not touched */ + + /* test corner case for termination where result can ONLY fit NUL char (result should be terminated) */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, TEST_INPUT_NO_PATH, 1, sizeof(TEST_INPUT_NO_PATH), NULL, + TEST_DEFAULT_PATH, TEST_DEFAULT_EXTENSION), + CFE_FS_FNAME_TOO_LONG); + UtAssert_INT32_EQ(OutBuffer[0], 0); + UtAssert_INT32_EQ(OutBuffer[1], 0x7F); + + /* test case for where input is not terminated */ + /* only the specified number of chars should be used from input */ + memset(OutBuffer, 0x7F, sizeof(OutBuffer)); + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutBuffer, "abcdefgh", sizeof(OutBuffer), 4, NULL, TEST_DEFAULT_PATH, + TEST_DEFAULT_EXTENSION), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/dflpath/abcd.dflext", "Non terminated input -> %s", OutBuffer); + + + /* For coverage, also invoke the simplified CFE_FS_ParseInputFileName() */ + /* no more error paths here, as all real logic is in CFE_FS_ParseInputFileNameEx() */ + UtAssert_INT32_EQ(CFE_FS_ParseInputFileName(OutBuffer, TEST_INPUT_NO_EXTENSION, sizeof(OutBuffer), CFE_FS_FileCategory_TEXT_LOG), + CFE_SUCCESS); + UtAssert_StrCmp(OutBuffer, "/path/to/file.log", "Simplified API -> %s", OutBuffer); +} + +/* +** Test FS API that gets defaults for file system info +*/ +void Test_CFE_FS_DefaultFileStrings(void) +{ + /* + * Test case for: + * const char *CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_t FileCategory) + * const char *CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_t FileCategory) + * + * Note that some of these depend on platform-specific and/or user-configurable + * items, so the exact string outputs can vary. In general this just confirms + * that the returned pointer address, not the actual string content. + */ + + const char *Result; + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_UNKNOWN); + UtAssert_NULL(Result); + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_DYNAMIC_MODULE); + UtAssert_True(Result == GLOBAL_CONFIGDATA.Default_ModuleExtension, "Result (%lx) matches config (%lx)", + (unsigned long)Result, (unsigned long)GLOBAL_CONFIGDATA.Default_ModuleExtension); + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_BINARY_DATA_DUMP); + UtAssert_NOT_NULL(Result); + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_TEXT_LOG); + UtAssert_NOT_NULL(Result); + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_SCRIPT); + UtAssert_NOT_NULL(Result); + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_TEMP); + UtAssert_NOT_NULL(Result); + + Result = CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_MAX); + UtAssert_NULL(Result); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_UNKNOWN); + UtAssert_NULL(Result); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_DYNAMIC_MODULE); + UtAssert_True(Result == GLOBAL_CFE_CONFIGDATA.NonvolMountPoint, "Result (%lx) matches config (%lx)", + (unsigned long)Result, (unsigned long)GLOBAL_CFE_CONFIGDATA.NonvolMountPoint); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_BINARY_DATA_DUMP); + UtAssert_True(Result == GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint, "Result (%lx) matches config (%lx)", + (unsigned long)Result, (unsigned long)GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_TEXT_LOG); + UtAssert_True(Result == GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint, "Result (%lx) matches config (%lx)", + (unsigned long)Result, (unsigned long)GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_SCRIPT); + UtAssert_True(Result == GLOBAL_CFE_CONFIGDATA.NonvolMountPoint, "Result (%lx) matches config (%lx)", + (unsigned long)Result, (unsigned long)GLOBAL_CFE_CONFIGDATA.NonvolMountPoint); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_TEMP); + UtAssert_True(Result == GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint, "Result (%lx) matches config (%lx)", + (unsigned long)Result, (unsigned long)GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint); + + Result = CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_MAX); + UtAssert_NULL(Result); + + +} + /* ** Test FS API write extract file name from path function */ diff --git a/fsw/cfe-core/unit-test/fs_UT.h b/fsw/cfe-core/unit-test/fs_UT.h index 47b2573be..92c5fa1b5 100644 --- a/fsw/cfe-core/unit-test/fs_UT.h +++ b/fsw/cfe-core/unit-test/fs_UT.h @@ -123,6 +123,22 @@ void Test_CFE_FS_ReadHeader(void); ******************************************************************************/ void Test_CFE_FS_WriteHeader(void); +/*****************************************************************************/ +/** +** \brief Test FS API default file strings +** +** \par Description +** This function tests the FS API that gets filesystem info strings +** +** \par Assumptions, External Events, and Notes: +** None +** +** \returns +** This function does not return a value. +** +******************************************************************************/ +void Test_CFE_FS_DefaultFileStrings(void); + /*****************************************************************************/ /** ** \brief Test FS API set time stamp function @@ -196,6 +212,24 @@ void Test_CFE_FS_ByteSwapUint32(void); ******************************************************************************/ void Test_CFE_FS_IsGzFile(void); +/*****************************************************************************/ +/** +** \brief Test FS API parse input file name function +** +** \par Description +** This function tests the parse input file name function. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \returns +** This function does not return a value. +** +** \sa #UT_InitData, #UT_Report, #CFE_FS_ParseInputFileName +** +******************************************************************************/ +void Test_CFE_FS_ParseInputFileNameEx(void); + /*****************************************************************************/ /** ** \brief Test FS API write extract file name from path function diff --git a/fsw/cfe-core/unit-test/sb_UT.c b/fsw/cfe-core/unit-test/sb_UT.c index e6afc7715..2f2cd8346 100644 --- a/fsw/cfe-core/unit-test/sb_UT.c +++ b/fsw/cfe-core/unit-test/sb_UT.c @@ -2739,9 +2739,10 @@ void Test_TransmitMsg_API(void) SB_UT_ADD_SUBTEST(Test_TransmitMsg_ZeroCopyGetPtr); SB_UT_ADD_SUBTEST(Test_TransmitBuffer_IncrementSeqCnt); SB_UT_ADD_SUBTEST(Test_TransmitBuffer_NoIncrement); + SB_UT_ADD_SUBTEST(Test_TransmitMsg_ZeroCopyHandleValidate); SB_UT_ADD_SUBTEST(Test_TransmitMsg_ZeroCopyReleasePtr); SB_UT_ADD_SUBTEST(Test_TransmitMsg_DisabledDestination); - SB_UT_ADD_SUBTEST(Test_TransmitBufferFull); + SB_UT_ADD_SUBTEST(Test_BroadcastBufferToRoute); SB_UT_ADD_SUBTEST(Test_TransmitMsgValidate_MaxMsgSizePlusOne); SB_UT_ADD_SUBTEST(Test_TransmitMsgValidate_NoSubscribers); } /* end Test_TransmitMsg_API */ @@ -3049,42 +3050,30 @@ void Test_TransmitMsg_ZeroCopyGetPtr(void) { CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl; uint16 MsgSize = 10; + uint32 MemUse; /* Have GetPoolBuf stub return error on its next call (buf descriptor * allocation failed) */ UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 1, CFE_ES_ERR_MEM_BLOCK_SIZE); - ASSERT_TRUE((cpuaddr) CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl) == (cpuaddr) NULL); - - /* Have GetPoolBuf stub return error on its second call (actual buffer - * allocation failed) - */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 2, CFE_ES_ERR_MEM_BLOCK_SIZE); - ASSERT_TRUE((cpuaddr) CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl) == (cpuaddr) NULL); - - /* Have GetPoolBuf stub return error on its second call (null buffer - * returned and error returning the memory to the buffer) - */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 2, -1); - UT_SetDeferredRetcode(UT_KEY(CFE_ES_PutPoolBuf), 1, 0); - ASSERT_TRUE((cpuaddr) CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl) == (cpuaddr) NULL); + ASSERT_TRUE(CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl) == NULL); EVTCNT(0); /* Increase the peak memory and buffers in use above the expected values in * order to exercise branch paths */ - CFE_SB_Global.StatTlmMsg.Payload.MemInUse = 0; - CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse = sizeof(CFE_SB_ZeroCopyD_t) + MsgSize + - sizeof(CFE_SB_BufferD_t) + 1; + + /* predict memory use for a given descriptor (this needs to match what impl does) */ + MemUse = MsgSize + offsetof(CFE_SB_BufferD_t, Content); + CFE_SB_Global.StatTlmMsg.Payload.MemInUse = 0; + CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse = MemUse + 10; CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse = CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse + 2; - ASSERT_TRUE((cpuaddr) CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl) != (cpuaddr) NULL); + ASSERT_TRUE(CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl) != NULL); - ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse, sizeof(CFE_SB_ZeroCopyD_t) + MsgSize + - sizeof(CFE_SB_BufferD_t) + 1); - ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.MemInUse, sizeof(CFE_SB_ZeroCopyD_t) + MsgSize + - sizeof(CFE_SB_BufferD_t)); + ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse, MemUse + 10); /* unchanged */ + ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.MemInUse, MemUse); /* predicted value */ ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.PeakSBBuffersInUse, CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse + 1); @@ -3092,6 +3081,48 @@ void Test_TransmitMsg_ZeroCopyGetPtr(void) } /* end Test_TransmitMsg_ZeroCopyGetPtr */ +void Test_TransmitMsg_ZeroCopyHandleValidate(void) +{ + CFE_SB_Buffer_t *SendPtr; + CFE_SB_ZeroCopyHandle_t GoodZeroCpyBufHndl; + CFE_SB_ZeroCopyHandle_t BadZeroCpyBufHndl; + CFE_SB_ZeroCopyHandle_t NullZeroCpyBufHndl; + CFE_SB_BufferD_t TestBufDsc; + + /* Create a real/valid Zero Copy handle via the API */ + SendPtr = CFE_SB_ZeroCopyGetPtr(sizeof(SB_UT_Test_Tlm_t), &GoodZeroCpyBufHndl); + if (SendPtr == NULL) + { + UtAssert_Failed("Unexpected NULL pointer returned from ZeroCopyGetPtr"); + } + + /* The NULL handle is just zero */ + NullZeroCpyBufHndl = (CFE_SB_ZeroCopyHandle_t) { 0 }; + + /* Create an invalid Zero Copy handle that is not NULL but refers to a + * descriptor which is NOT from CFE_SB_ZeroCopyGetPtr(). */ + memset(&TestBufDsc, 0, sizeof(TestBufDsc)); + BadZeroCpyBufHndl = (CFE_SB_ZeroCopyHandle_t) { &TestBufDsc }; + + /* Good buffer pointer + Null Handle => BAD_ARGUMENT */ + ASSERT_EQ(CFE_SB_ZeroCopyHandleValidate(SendPtr, NullZeroCpyBufHndl), CFE_SB_BAD_ARGUMENT); + + /* Bad buffer pointer + Good Handle => BAD_ARGUMENT */ + ASSERT_EQ(CFE_SB_ZeroCopyHandleValidate(NULL, GoodZeroCpyBufHndl), CFE_SB_BAD_ARGUMENT); + + /* Good buffer pointer + Non Zero-Copy Handle => CFE_SB_BUFFER_INVALID */ + ASSERT_EQ(CFE_SB_ZeroCopyHandleValidate(SendPtr, BadZeroCpyBufHndl), CFE_SB_BUFFER_INVALID); + + /* Mismatched buffer pointer + Good Handle => CFE_SB_BUFFER_INVALID */ + ASSERT_EQ(CFE_SB_ZeroCopyHandleValidate(SendPtr+1, GoodZeroCpyBufHndl), CFE_SB_BUFFER_INVALID); + + /* Good buffer pointer + Good Handle => SUCCESS */ + ASSERT_EQ(CFE_SB_ZeroCopyHandleValidate(SendPtr, GoodZeroCpyBufHndl), CFE_SUCCESS); + + /* Clean-up */ + CFE_SB_ZeroCopyReleasePtr(SendPtr, GoodZeroCpyBufHndl); +} + /* ** Test successfully sending a message in zero copy mode (telemetry source ** sequence count increments) @@ -3103,7 +3134,7 @@ void Test_TransmitBuffer_IncrementSeqCnt(void) CFE_SB_PipeId_t PipeId; CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; uint32 PipeDepth = 10; - CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl = 0; + CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl; CFE_MSG_SequenceCount_t SeqCnt; CFE_MSG_Size_t Size = sizeof(SB_UT_Test_Tlm_t); CFE_MSG_Type_t Type = CFE_MSG_Type_Tlm; @@ -3115,16 +3146,13 @@ void Test_TransmitBuffer_IncrementSeqCnt(void) SETUP(CFE_SB_Subscribe(MsgId, PipeId)); + /* Create a real/valid Zero Copy handle via the API */ SendPtr = CFE_SB_ZeroCopyGetPtr(sizeof(SB_UT_Test_Tlm_t), &ZeroCpyBufHndl); if (SendPtr == NULL) { UtAssert_Failed("Unexpected NULL pointer returned from ZeroCopyGetPtr"); } - /* Test response to a get pool information error */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBufInfo), 1, -1); - ASSERT_EQ(CFE_SB_TransmitBuffer(SendPtr, ZeroCpyBufHndl, true), CFE_SB_BUFFER_INVALID); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetMsgId), &MsgId, sizeof(MsgId), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetSize), &Size, sizeof(Size), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &Type, sizeof(Type), false); @@ -3157,7 +3185,7 @@ void Test_TransmitBuffer_NoIncrement(void) CFE_SB_PipeId_t PipeId; CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; uint32 PipeDepth = 10; - CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl = 0; + CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl; CFE_MSG_SequenceCount_t SeqCnt = 22; CFE_MSG_Size_t Size = sizeof(SB_UT_Test_Tlm_t); CFE_MSG_Type_t Type = CFE_MSG_Type_Tlm; @@ -3175,10 +3203,6 @@ void Test_TransmitBuffer_NoIncrement(void) UtAssert_Failed("Unexpected NULL pointer returned from ZeroCopyGetPtr"); } - /* Test response to a get pool information error */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBufInfo), 1, -1); - ASSERT_EQ(CFE_SB_TransmitBuffer(SendPtr, ZeroCpyBufHndl, false), CFE_SB_BUFFER_INVALID); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetMsgId), &MsgId, sizeof(MsgId), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetSize), &Size, sizeof(Size), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &Type, sizeof(Type), false); @@ -3206,9 +3230,9 @@ void Test_TransmitMsg_ZeroCopyReleasePtr(void) CFE_SB_Buffer_t *ZeroCpyMsgPtr1 = NULL; CFE_SB_Buffer_t *ZeroCpyMsgPtr2 = NULL; CFE_SB_Buffer_t *ZeroCpyMsgPtr3 = NULL; - CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl1 = 0; - CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl2 = 0; - CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl3 = 0; + CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl1; + CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl2; + CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl3; uint16 MsgSize = 10; ZeroCpyMsgPtr1 = CFE_SB_ZeroCopyGetPtr(MsgSize, &ZeroCpyBufHndl1); @@ -3217,27 +3241,14 @@ void Test_TransmitMsg_ZeroCopyReleasePtr(void) SETUP(CFE_SB_ZeroCopyReleasePtr(ZeroCpyMsgPtr2, ZeroCpyBufHndl2)); /* Test response to an invalid buffer */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBufInfo), 1, -1); ASSERT_EQ(CFE_SB_ZeroCopyReleasePtr(ZeroCpyMsgPtr2, ZeroCpyBufHndl2), CFE_SB_BUFFER_INVALID); /* Test response to a null message pointer */ - ASSERT_EQ(CFE_SB_ZeroCopyReleasePtr(NULL, ZeroCpyBufHndl2), CFE_SB_BUFFER_INVALID); + ASSERT_EQ(CFE_SB_ZeroCopyReleasePtr(NULL, ZeroCpyBufHndl3), CFE_SB_BAD_ARGUMENT); /* Test response to an invalid message pointer */ - ASSERT_EQ(CFE_SB_ZeroCopyReleasePtr((CFE_SB_Buffer_t *) 0x1234, - ZeroCpyBufHndl2), CFE_SB_BUFFER_INVALID); - - /* Test path when return the descriptor to the pool fails in - * CFE_SB_ZeroCopyReleaseDesc - */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_PutPoolBuf), 1, -1); - ASSERT(CFE_SB_ZeroCopyReleasePtr(ZeroCpyMsgPtr2, ZeroCpyBufHndl2)); - - /* Test path when return the buffer to the pool fails in - * CFE_SB_ZeroCopyReleasePtr - */ - UT_SetDeferredRetcode(UT_KEY(CFE_ES_PutPoolBuf), 2, -1); - ASSERT(CFE_SB_ZeroCopyReleasePtr(ZeroCpyMsgPtr2, ZeroCpyBufHndl2)); + ASSERT_EQ(CFE_SB_ZeroCopyReleasePtr(ZeroCpyMsgPtr1, + ZeroCpyBufHndl3), CFE_SB_BUFFER_INVALID); /* Test successful release of the second buffer */ ASSERT(CFE_SB_ZeroCopyReleasePtr(ZeroCpyMsgPtr3, ZeroCpyBufHndl3)); @@ -3287,31 +3298,34 @@ void Test_TransmitMsg_DisabledDestination(void) } /* end Test_TransmitMsg_DisabledDestination */ /* -** Test successful CFE_SB_TransmitBufferFull +** Test successful CFE_SB_BroadcastBufferToRoute */ -void Test_TransmitBufferFull(void) +void Test_BroadcastBufferToRoute(void) { CFE_SB_PipeId_t PipeId; CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; CFE_SB_BufferD_t SBBufD; - CFE_SB_Buffer_t MsgBuf; int32 PipeDepth; CFE_SBR_RouteId_t RouteId; - SBBufD.Buffer = &MsgBuf; + memset(&SBBufD, 0, sizeof(SBBufD)); + SBBufD.MsgId = MsgId; + CFE_SB_TrackingListReset(&SBBufD.Link); + PipeDepth = 2; SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "TestPipe")); SETUP(CFE_SB_Subscribe(MsgId, PipeId)); RouteId = CFE_SBR_GetRouteId(MsgId); - ASSERT(CFE_SB_TransmitBufferFull(&SBBufD, RouteId, MsgId)); + /* No return from this function - it handles all errors */ + CFE_SB_BroadcastBufferToRoute(&SBBufD, RouteId); EVTCNT(2); TEARDOWN(CFE_SB_DeletePipe(PipeId)); -} /* end Test_TransmitBufferFull */ +} /* end Test_BroadcastBufferToRoute */ /* ** Test response to sending a message with the message size larger than allowed @@ -3520,31 +3534,54 @@ void Test_ReceiveBuffer_PendForever(void) void Test_CleanupApp_API(void) { CFE_SB_PipeId_t PipeId; - CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl = 0; - uint16 PipeDepth = 50; + CFE_SB_ZeroCopyHandle_t ZeroCpyBufHndl; + uint16 PipeDepth = 10; CFE_ES_AppId_t AppID; + CFE_ES_AppId_t AppID2; + + /* + * Reset global descriptor list + */ + CFE_SB_InitBuffers(); CFE_ES_GetAppID(&AppID); + AppID2 = CFE_ES_APPID_C(CFE_ResourceId_FromInteger(2)); SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "TestPipe")); - CFE_SB_ZeroCopyGetPtr(PipeDepth, &ZeroCpyBufHndl); - CFE_SB_ZeroCopyGetPtr(PipeDepth, &ZeroCpyBufHndl); + CFE_SB_ZeroCopyGetPtr(10, &ZeroCpyBufHndl); + + /* Mimic a different app ID getting a buffer */ + UT_SetAppID(AppID2); + CFE_SB_ZeroCopyGetPtr(10, &ZeroCpyBufHndl); + + /* Original app gets a second buffer */ + UT_SetAppID(AppID); + CFE_SB_ZeroCopyGetPtr(10, &ZeroCpyBufHndl); /* Set second application ID to provide complete branch path coverage */ CFE_SB_Global.PipeTbl[1].PipeId = SB_UT_PIPEID_1; CFE_SB_Global.PipeTbl[1].AppId = AppID; - ASSERT_TRUE(CFE_SB_Global.ZeroCopyTail != NULL); - /* Attempt with a bad application ID first in order to get full branch path * coverage in CFE_SB_ZeroCopyReleaseAppId */ CFE_SB_CleanUpApp(CFE_ES_APPID_UNDEFINED); + /* This should have freed no buffers */ + UtAssert_STUB_COUNT(CFE_ES_PutPoolBuf, 0); + /* Attempt again with a valid application ID */ CFE_SB_CleanUpApp(AppID); - ASSERT_TRUE(CFE_SB_Global.ZeroCopyTail == NULL); + /* This should have freed 2 out of the 3 buffers - + * the ones which were gotten by this app. */ + UtAssert_STUB_COUNT(CFE_ES_PutPoolBuf, 2); + + /* Clean up the second App */ + CFE_SB_CleanUpApp(AppID2); + + /* This should have freed the last buffer */ + UtAssert_STUB_COUNT(CFE_ES_PutPoolBuf, 3); EVTCNT(2); @@ -3843,13 +3880,17 @@ void Test_CFE_SB_Buffers(void) CFE_SB_Global.StatTlmMsg.Payload.MemInUse = 0; CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse = sizeof(CFE_SB_BufferD_t) * 4; - bd = CFE_SB_GetBufferFromPool(SB_UT_FIRST_VALID_MID, 0); + bd = CFE_SB_GetBufferFromPool(0); ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.PeakMemInUse, sizeof(CFE_SB_BufferD_t) * 4); EVTCNT(0); - ExpRtn = CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse; + /* + * If returning to the pool fails SB still isn't going to use the buffer anymore, + * so it shouldn't be tracked as "in use" - it is lost. + */ + ExpRtn = CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse - 1; UT_SetDeferredRetcode(UT_KEY(CFE_ES_PutPoolBuf), 1, -1); CFE_SB_ReturnBufferToPool(bd); ASSERT_EQ(CFE_SB_Global.StatTlmMsg.Payload.SBBuffersInUse, ExpRtn); diff --git a/fsw/cfe-core/unit-test/sb_UT.h b/fsw/cfe-core/unit-test/sb_UT.h index 2f09ea386..99dc04cf2 100644 --- a/fsw/cfe-core/unit-test/sb_UT.h +++ b/fsw/cfe-core/unit-test/sb_UT.h @@ -1936,6 +1936,21 @@ void Test_TransmitMsg_ZeroCopyGetPtr(void); ******************************************************************************/ void Test_TransmitBuffer_IncrementSeqCnt(void); +/*****************************************************************************/ +/** +** \brief Test the zero-copy handle validation performed by CFE_SB_ZeroCopyHandleValidate() +** +** \par Description +** Exercises the validation checks within this function +** +** \par Assumptions, External Events, and Notes: +** None +** +** \returns +** This function does not return a value. +******************************************************************************/ +void Test_TransmitMsg_ZeroCopyHandleValidate(void); + /*****************************************************************************/ /** ** \brief Test successfully sending a message in zero copy mode (telemetry @@ -1987,10 +2002,10 @@ void Test_TransmitMsg_DisabledDestination(void); /*****************************************************************************/ /** -** \brief Test successful CFE_SB_TransmitBufferFull +** \brief Test CFE_SB_BroadcastBufferToRoute ** ** \par Description -** This function tests successfully sending a message with the metadata. +** This function tests broadcasting a message buffer with the metadata. ** ** \par Assumptions, External Events, and Notes: ** None @@ -1998,7 +2013,7 @@ void Test_TransmitMsg_DisabledDestination(void); ** \returns ** This function does not return a value. ******************************************************************************/ -void Test_TransmitBufferFull(void); +void Test_BroadcastBufferToRoute(void); /*****************************************************************************/ /** diff --git a/fsw/cfe-core/ut-stubs/ut_fs_stubs.c b/fsw/cfe-core/ut-stubs/ut_fs_stubs.c index f3bdaf3cd..f7238c0dd 100644 --- a/fsw/cfe-core/ut-stubs/ut_fs_stubs.c +++ b/fsw/cfe-core/ut-stubs/ut_fs_stubs.c @@ -40,6 +40,62 @@ /* ** Functions */ + +/* + * Stub for CFE_FS_GetDefaultMountPoint() + */ +const char *CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_t FileCategory) +{ + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_GetDefaultMountPoint), FileCategory); + + int32 Status; + static const char DEFAULT_MOUNTPOINT[] = "/ut"; + const char *Result; + + Status = UT_DEFAULT_IMPL(CFE_FS_GetDefaultMountPoint); + Result = NULL; + + if (Status == CFE_SUCCESS) + { + /* If the test case supplied a buffer, return it, otherwise return fixed value */ + UT_GetDataBuffer(UT_KEY(CFE_FS_GetDefaultMountPoint), (void**)&Result, NULL, NULL); + if (Result == NULL) + { + Result = DEFAULT_MOUNTPOINT; + } + } + + return Result; +} + +/* + * Stub for CFE_FS_GetDefaultExtension() + */ +const char *CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_t FileCategory) +{ + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_GetDefaultExtension), FileCategory); + + int32 Status; + static const char DEFAULT_EXTENSION[] = ".ut"; + const char *Result; + + Status = UT_DEFAULT_IMPL(CFE_FS_GetDefaultExtension); + Result = NULL; + + if (Status == CFE_SUCCESS) + { + /* If the test case supplied a buffer, return it, otherwise return fixed value */ + UT_GetDataBuffer(UT_KEY(CFE_FS_GetDefaultExtension), (void**)&Result, NULL, NULL); + if (Result == NULL) + { + Result = DEFAULT_EXTENSION; + } + } + + return Result; +} + + /*****************************************************************************/ /** ** \brief CFE_FS_InitHeader stub function @@ -199,6 +255,65 @@ int32 CFE_FS_EarlyInit(void) return status; } +/*****************************************************************************/ +/* + * Stub for CFE_FS_ParseInputFileNameEx - see prototype for description + */ +int32 CFE_FS_ParseInputFileNameEx(char *OutputBuffer, const char *InputBuffer, size_t OutputBufSize, size_t InputBufSize, + const char *DefaultInput, const char *DefaultPath, const char *DefaultExtension) +{ + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), OutputBuffer); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), InputBuffer); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), OutputBufSize); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), InputBufSize); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), DefaultInput); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), DefaultPath); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileNameEx), DefaultExtension); + + int32 status; + + status = UT_DEFAULT_IMPL(CFE_FS_ParseInputFileNameEx); + + /* Copy any specific output supplied by test case */ + if (status >= 0 && + UT_Stub_CopyToLocal(UT_KEY(CFE_FS_ParseInputFileNameEx), OutputBuffer, OutputBufSize) == 0 && + OutputBufSize > 0 && DefaultInput != NULL) + { + /* Otherwise fall back to simple copy */ + strncpy(OutputBuffer, DefaultInput, OutputBufSize); + } + + return status; +} + +/*****************************************************************************/ +/* + * Stub for CFE_FS_ParseInputFileName - see prototype for description + */ +int32 CFE_FS_ParseInputFileName(char *OutputBuffer, const char *InputName, size_t OutputBufSize, + CFE_FS_FileCategory_t FileCategory) +{ + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileName), OutputBuffer); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileName), InputName); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileName), OutputBufSize); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_FS_ParseInputFileName), FileCategory); + + int32 status; + + status = UT_DEFAULT_IMPL(CFE_FS_ParseInputFileName); + + /* Copy any specific output supplied by test case */ + if (status >= 0 && + UT_Stub_CopyToLocal(UT_KEY(CFE_FS_ParseInputFileName), OutputBuffer, OutputBufSize) == 0 && + OutputBufSize > 0) + { + /* Otherwise fall back to simple copy */ + strncpy(OutputBuffer, InputName, OutputBufSize); + } + + return status; +} + /*****************************************************************************/ /** diff --git a/modules/sbr/private_inc/cfe_sbr_priv.h b/modules/sbr/private_inc/cfe_sbr_priv.h index 3d0fcce59..ecabbb6bb 100644 --- a/modules/sbr/private_inc/cfe_sbr_priv.h +++ b/modules/sbr/private_inc/cfe_sbr_priv.h @@ -31,12 +31,6 @@ */ #include "private/cfe_sbr.h" -/* - * Macro Definitions - */ - -/** \brief Invalid route id */ -#define CFE_SBR_INVALID_ROUTE_ID ((CFE_SBR_RouteId_t) {.RouteId = 0}) /****************************************************************************** * Function prototypes