diff --git a/SECURITY.md b/SECURITY.md index b30de2d5a..f5cc7d7cf 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,13 +4,38 @@ To report a vulnerability for the cFE subsystem please [submit an issue](https://github.com/nasa/cFE/issues/new/choose). -For general cFS vulnerabilities please [open a cFS framework issue](https://github.com/nasa/cfs/issues/new/choose) and see our [top-level security policy](https://github.com/nasa/cFS/security/policy). +For general cFS vulnerabilities please [open a cFS framework issue](https://github.com/nasa/cfs/issues/new/choose) and see our [top-level security policy](https://github.com/nasa/cFS/security/policy) for additional information. In either case please use the "Bug Report" template and provide as much information as possible. Apply appropraite labels for each report. For security related reports, tag the issue with the "security" label. +## Testing + +**Disclaimer: nasa/cFE is not responsible for any liability incurred under the [Apache License 2.0](https://github.com/nasa/cFE/blob/main/LICENSE).** + +Testing is an important aspect our team values to improve cFE. + +To view tools used for the cFS bundle, see our [top-level security policy](https://github.com/nasa/cFS/security/policy). + +### CodeQL + +The [cFE CodeQL GitHub Actions workflow](https://github.com/nasa/cFE/actions/workflows/codeql-build.yml) is available to the public. To review the results, fork the cFE repository and run the CodeQL workflow. + +CodeQL is ran for every push and pull-request on all branches of cFE in GitHub Actions. + +For the CodeQL GitHub Actions setup, visit https://github.com/github/codeql-action. + +### Cppcheck + +The [cFE Cppcheck GitHub Actions workflow and results](https://github.com/nasa/cFE/actions/workflows/static-analysis.yml) are available to the public. To view the results, select a workflow and download the artifacts. + +Cppcheck is ran for every push on the main branch and every pull request on all branches of cFE in Github Actions. + +For more information about Cppcheck, visit http://cppcheck.sourceforge.net/. + ## Additional Support -For additional support, email us at cfs-program@lists.nasa.gov. For help using OSAL and cFS, [subscribe to our mailing list](https://lists.nasa.gov/mailman/listinfo/cfs-community) that includes all the community members/users of the NASA core Flight Software (cFS) product line. The mailing list is used to communicate any information related to the cFS product such as current releases, bug findings and fixes, enhancement requests, community meeting notifications, sending out meeting minutes, etc. +For additional support, submit a GitHub issue. You can also email the cfs community at cfs-community@lists.nasa.gov. -If you wish to report a cybersecurity incident or concern please contact the NASA Security Operations Center either by phone at 1-877-627-2732 or via email address soc@nasa.gov. +You can subscribe to the mailing list [here](https://lists.nasa.gov/mailman/listinfo/cfs-community) that includes all the community members/users of the NASA core Flight Software (cFS) product line. The mailing list is used to communicate any information related to the cFS product such as current releases, bug findings and fixes, enhancement requests, community meeting notifications, sending out meeting minutes, etc. +If you wish to report a cybersecurity incident or concern, please contact the NASA Security Operations Center either by phone at 1-877-627-2732 or via email address soc@nasa.gov. diff --git a/cmake/arch_build.cmake b/cmake/arch_build.cmake index ec964ae59..2287261c8 100644 --- a/cmake/arch_build.cmake +++ b/cmake/arch_build.cmake @@ -11,6 +11,15 @@ # ################################################################## +# define a custom property to track dependencies on CFE module targets. +# users should not typically maniplate this directly +define_property(TARGET PROPERTY CFE_MODULE_DEPENDENCIES + BRIEF_DOCS + "A set of CFE module dependencies" + FULL_DOCS + "This is a CFE-specific target property that is added to CFE modules that contains the module dependencies" +) + ################################################################## # @@ -97,6 +106,38 @@ function(add_cfe_app APP_NAME APP_SRC_FILES) endfunction(add_cfe_app) +################################################################## +# +# FUNCTION: add_cfe_app_dependency +# +# Adds a library dependency to a previously-created +# app/library target +# +# it adds the interface include directories and compile definitions +# of the dependency into the compilation for the module. +# +function(add_cfe_app_dependency MODULE_NAME DEPENDENCY_MODULE) + + # assemble a list of include directories and compile definitions + set(INCLUDE_LIST) + set(COMPILE_DEF_LIST) + foreach(DEP ${DEPENDENCY_MODULE} ${ARGN}) + list(APPEND INCLUDE_LIST "$") + list(APPEND COMPILE_DEF_LIST "$") + endforeach() + + target_include_directories(${MODULE_NAME} PUBLIC + ${INCLUDE_LIST} + ) + target_compile_definitions(${MODULE_NAME} PUBLIC + ${COMPILE_DEF_LIST} + ) + + # append to the custom property to track this dependency (this helpful for UT) + set_property(TARGET ${MODULE_NAME} APPEND PROPERTY CFE_MODULE_DEPENDENCIES ${DEPENDENCY_MODULE} ${ARGN}) + +endfunction(add_cfe_app_dependency) + ################################################################## # # FUNCTION: add_cfe_tables @@ -175,47 +216,194 @@ endfunction(add_cfe_tables) ################################################################## # -# FUNCTION: add_unit_test_lib +# FUNCTION: add_cfe_coverage_dependency +# +# Adds a stub library dependency to a previously-created +# coverage test runner target # -# Add a library for unit testing. This is basically the same as the -# normal CMake "add_library" but enables the code coverage compiler options. +# If a unit under test calls functions provided by another unit +# (such as a library) then the stubs from that library will be +# added to the LINK_LIBRARIES of the coverage test. # -function(add_unit_test_lib UT_NAME UT_SRCS) - add_library(utl_${UT_NAME} STATIC ${UT_SRCS} ${ARGN}) - set_target_properties(utl_${UT_NAME} PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -pg --coverage") -endfunction(add_unit_test_lib) +function(add_cfe_coverage_dependency MODULE_NAME UNIT_NAME DEPENDENCY_MODULE) + + # the stub library correlating to the module should be named: + # coverage-${MODULE_NAME}-stubs + # (assuming it was added by the add_cfe_coverage_stubs above) + set(DEP_LIST) + foreach(DEP ${DEPENDENCY_MODULE} ${ARGN}) + list(APPEND DEP_LIST "coverage-${DEP}-stubs") + endforeach() + + target_link_libraries(coverage-${MODULE_NAME}-${UNIT_NAME}-testrunner + ${DEP_LIST} + ) + +endfunction(add_cfe_coverage_dependency) + ################################################################## # -# FUNCTION: add_unit_test_exe +# FUNCTION: add_cfe_coverage_test +# +# Add executable target for coverage testing. This builds the target +# units with extra compiler flags for coverage instrumentation, along with +# a "testrunner" executable to run the tests. It also registers +# that testrunner with ctest via the add_test() function. +# +# NOTE: The first argument (MODULE_NAME) must match the name that was previously +# passed to the add_cfe_app() function - as this references that previous +# target to use the same compile definitions and include paths. # -# Create unit test executable. This links the UT main executive with -# a library that is placed under test (created via add_unit_test_lib) -# It also registers the final executable target with ctest so it will -# be run during the "make test" target or when ctest is run. +# The executable target name follows the pattern: +# "coverage-${MODULE_NAME}-${UNIT_NAME}-testrunner" # -function(add_unit_test_exe UT_NAME UT_SRCS) - add_executable(${UT_NAME} ${utexec_MISSION_DIR}/src/utexec.c ${UT_SRCS} ${ARGN}) +# The calling script may call target_link_libraries() (or other target functions) +# to customize this target as needed. +# +function(add_cfe_coverage_test MODULE_NAME UNIT_NAME TESTCASE_SRC UT_SRCS) + + # A consistent name convention for all targets generated by this funtion + set(TEST_NAME "coverage-${MODULE_NAME}-${UNIT_NAME}") + set(OBJECT_TARGET "${TEST_NAME}-object") + set(RUNNER_TARGET "${TEST_NAME}-testrunner") + + # Compile the source unit(s) under test as a separate library + # This is done so that special coverage-specific compile flags can be used on these files + add_library(${OBJECT_TARGET} OBJECT + ${UT_SRCS} + ) - get_target_property(UTCDEFS ${UT_NAME} COMPILE_DEFINITIONS) - list(APPEND UTCDEFS "DEFAULT_REF_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"") + # Apply the UT_COVERAGE_COMPILE_FLAGS to the units under test + # This should enable coverage analysis on platforms that support this + target_compile_options(${OBJECT_TARGET} PRIVATE + ${UT_COVERAGE_COMPILE_FLAGS} + ) + + # Include the same set of include dirs/definitions that is used from the app target + target_include_directories(${OBJECT_TARGET} PUBLIC + $ + ) + target_compile_definitions(${OBJECT_TARGET} PUBLIC + $ + ) + + # Compile a test runner application, which contains the + # actual coverage test code (test cases) and the unit under test + add_executable(${RUNNER_TARGET} + ${TESTCASE_SRC} + $ + ) - get_target_property(UTCFLAGS ${UT_NAME} COMPILE_FLAGS) - if (UTCFLAGS STREQUAL "UTCFLAGS-NOTFOUND") - set(UTCFLAGS) - endif() - set(UTCFLAGS "${UTCFLAGS} -I${utexec_MISSION_DIR}/inc -I${CMAKE_CURRENT_SOURCE_DIR}") + # Include the same set of include dirs/definitions that is used from the app target + target_include_directories(${RUNNER_TARGET} PUBLIC + $ + ) + target_compile_definitions(${RUNNER_TARGET} PUBLIC + $ + ) + + # This also needs to be linked with UT_COVERAGE_LINK_FLAGS (for coverage) + # This is also linked with any other stub libraries needed, + # as well as the UT assert framework + target_link_libraries(${RUNNER_TARGET} + ${UT_COVERAGE_LINK_FLAGS} + ut_cfe-core_stubs + ut_assert + ) - get_target_property(UTLFLAGS ${UT_NAME} LINK_FLAGS) - if (UTLFLAGS STREQUAL "UTLFLAGS-NOTFOUND") - set(UTLFLAGS) + # for whatever app/lib dependencies the real FSW app had, the unit test + # should have the same dependencies but on the stubs instead. + get_target_property(MODULE_DEPENDENCIES ${MODULE_NAME} CFE_MODULE_DEPENDENCIES) + if (MODULE_DEPENDENCIES) + add_cfe_coverage_dependency(${MODULE_NAME} ${UNIT_NAME} ${MODULE_DEPENDENCIES}) + endif(MODULE_DEPENDENCIES) + + # Add it to the set of tests to run as part of "make test" + add_test(${TEST_NAME} ${RUNNER_TARGET}) + foreach(TGT ${INSTALL_TARGET_LIST}) + install(TARGETS ${RUNNER_TARGET} DESTINATION ${TGT}/${UT_INSTALL_SUBDIR}) + endforeach() + +endfunction(add_cfe_coverage_test) + + +################################################################## +# +# FUNCTION: add_cfe_coverage_unit_include +# +# Add an "override" include directory for a specific unit test +# +# This can be used if a coverage test needs to override certain +# C library header files only for a specific unit under test. The +# include path is added only for the particular source files in the +# specified coverage test unit. (Not for the coverage test itself). +# +# The executable target name follows the pattern: +# "coverage-${MODULE_NAME}-${UNIT_NAME}-testrunner" +# +function(add_cfe_coverage_unit_include MODULE_NAME UNIT_NAME OVERRIDE_INCLUDE_DIRS) + # For the object target only, the "override" includes should be injected + # into the include path. Note it is important that this is only included + # for the specific unit under test (object lib) not the coverage + # test executable or test cases, since these typically need the real + # version of these functions. + target_include_directories(coverage-${MODULE_NAME}-${UNIT_NAME}-object PRIVATE + ${OVERRIDE_INCLUDE_DIRS} ${ARGN} + ) + +endfunction(add_cfe_coverage_unit_include) + + +################################################################## +# +# FUNCTION: add_cfe_coverage_stubs +# +# Add stub library target for coverage testing. The stub library should +# contain a stub implementation for every function defined in the public +# API of the current module. +# +# NOTE: The first argument (MODULE_NAME) should match a name that was previously +# passed to the add_cfe_app() function - as this references that previous +# target to use the same compile definitions and include paths. +# (however this does also allow extra stub libs to be created that are not +# related to an existing module) +# +# The stub library target name follows the pattern: +# "coverage-${MODULE_NAME}-stubs" +# +# The calling script may call target_link_libraries() (or other target functions) +# to customize this target as needed. +# +# NOTE: To simplify linking and avoid possible problems there should ideally be a 1:1 +# relationship between module source files and the stub files. Each stub file +# should provide the same set of functions that the fsw source file provides. +# (although its is not strictly required, it does help keep things more manageable). +# +function(add_cfe_coverage_stubs MODULE_NAME STUB_SRCS) + + set(STUB_TARGET "coverage-${MODULE_NAME}-stubs") + + add_library(${STUB_TARGET} STATIC + ${STUB_SRCS} ${ARGN} + ) + + # If the MODULE_NAME refers to an existing CFE APP/LIB target, then + # use the same set of include dirs/definitions that is used from the app target + # This is not required; "extra" stub libs may be created that are not + # directly associated with an existing module. + if (TARGET ${MODULE_NAME}) + target_include_directories(${STUB_TARGET} PUBLIC + $ + ) + target_compile_definitions(${STUB_TARGET} PUBLIC + $ + ) endif() - set(UTLFLAGS "${UTLFLAGS} -pg --coverage") - - set_target_properties(${UT_NAME} PROPERTIES LINK_FLAGS "${UTLFLAGS}" COMPILE_DEFINITIONS "${UTCDEFS}" COMPILE_FLAGS "${UTCFLAGS}") - target_link_libraries(${UT_NAME} utl_${UT_NAME}) - add_test(${UT_NAME} ${UT_NAME}) -endfunction(add_unit_test_exe) + + target_link_libraries(${STUB_TARGET} ut_assert) + +endfunction(add_cfe_coverage_stubs) ################################################################## diff --git a/cmake/generate_build_env.cmake b/cmake/generate_build_env.cmake new file mode 100644 index 000000000..ea179281e --- /dev/null +++ b/cmake/generate_build_env.cmake @@ -0,0 +1,48 @@ +################################################################## +# +# cFS version metadata collection script +# +# This small script runs at build time (as opposed to prep time) +# and is intended to extract information about the current +# build environment - this may change after initial makefile creation +# +################################################################## + +# All 3 of these may be passed via environment variables to force a particular +# date, user, or hostname i.e. if hoping to reproduce an exact binary of a prior build +# They are free-form strings, will be built/linked into the final CONFIGDATA object. + +# Get the current date and time +set(BUILDDATE $ENV{BUILDDATE}) +if (NOT BUILDDATE) + execute_process( + COMMAND date "+%Y%m%d%H%M" + OUTPUT_VARIABLE BUILDDATE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif(NOT BUILDDATE) + +# Get the build host +set(BUILDHOST $ENV{HOSTNAME}) +if (NOT BUILDHOST) + execute_process( + COMMAND hostname + OUTPUT_VARIABLE BUILDHOST + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif (NOT BUILDHOST) + +# Get the user ID +set(BUILDUSER $ENV{USER}) +if (NOT BUILDUSER) + execute_process( + COMMAND whoami + OUTPUT_VARIABLE BUILDUSER + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif (NOT BUILDUSER) + +# Use configure_file() command to generate the final output file because this can detect +# and only update it if it changes. +set(CFE_KEYVALUE_TABLE_NAME "CFE_BUILD_ENV_TABLE") +configure_file(${BIN}/cfe_build_env.in ${BIN}/src/cfe_build_env_table.c @ONLY) diff --git a/cmake/generate_git_module_version.cmake b/cmake/generate_git_module_version.cmake new file mode 100644 index 000000000..7a2559324 --- /dev/null +++ b/cmake/generate_git_module_version.cmake @@ -0,0 +1,75 @@ +################################################################## +# +# cFS version metadata collection script +# +# This small script runs at build time (as opposed to prep time) +# and is intended to extract version metadata from the current source +# tree. It is done each time that the code is built, since the +# metadata could change at any time (i.e. a different branch could +# be checked out, or additional changes committed) +# +# Currently only git is supported as a version control source, however +# it could be extended to others by adding the appropriate command +# +################################################################## + +set(GIT_EXECUTABLE git) + +function(get_version DEP) + if (DEP STREQUAL "MISSION") + set(NAME ${MISSION_NAME}) + set(DIR ${MISSION_SOURCE_DIR}) + else() + if(EXISTS ${${DEP}_MISSION_DIR}/version_info.cmake) + include(${${DEP}_MISSION_DIR}/version_info.cmake) + else() + set(NAME ${DEP}) + endif() + set(DIR ${${DEP}_MISSION_DIR}) + endif() + message("inside get_version for ${DEP}") + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty + WORKING_DIRECTORY ${DIR} + OUTPUT_VARIABLE GIT_DESC_OUTPUT + RESULT_VARIABLE GIT_RESULT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Export output to parent scope + set(${DEP}_NAME "${NAME}" PARENT_SCOPE) + + # If result was successful, then string-ify it, otherwise use NULL + if (GIT_RESULT EQUAL 0) + set(${DEP}_VERSION "\"git:${GIT_DESC_OUTPUT}\"" PARENT_SCOPE) + else() + set(${DEP}_VERSION "NULL" PARENT_SCOPE) + endif() + +endfunction() + + +# First read in any variables that are passed in from the parent process +# There may be many of these and they may not all be passable via -D options +file(STRINGS "${BIN}/mission_vars.cache" PARENTVARS) +set(VARNAME) +foreach(PV ${PARENTVARS}) + if (VARNAME) + set(${VARNAME} ${PV}) + set(VARNAME) + else() + set(VARNAME ${PV}) + endif() +endforeach(PV ${PARENTVARS}) + +# Get version for all mission apps/dependencies (they may be different) +foreach(DEP "MISSION" ${MISSION_DEPS}) + get_version(${DEP}) +endforeach() + + +# Use configure_file() command to generate the final output file because this can detect +# and only update it if it changes. +set(CFE_KEYVALUE_TABLE_NAME "CFE_MODULE_VERSION_TABLE") +configure_file(${BIN}/cfe_module_version.in ${BIN}/src/cfe_module_version_table.c @ONLY) diff --git a/cmake/mission_build.cmake b/cmake/mission_build.cmake index 66b0d43c1..7920af487 100644 --- a/cmake/mission_build.cmake +++ b/cmake/mission_build.cmake @@ -72,6 +72,95 @@ function(initialize_globals) endfunction(initialize_globals) +################################################################## +# +# FUNCTION: generate_build_version_templates +# +# Generates file templates for use with configure_file() which is +# invoked at build time to get the required information. +# +# Note that some information may change between generation and build +# times, hence why only a template can be generated here, the final +# file content must be generated via a build rule. +# +function(generate_build_version_templates) + + # File header for build info template (tag file as auto-generated) + string(CONCAT GENERATED_FILE_HEADER + "/* This file is auto-generated from CMake build system. Do not manually edit! */\n" + "#include \"target_config.h\"\n" + "const CFE_ConfigKeyValue_t @CFE_KEYVALUE_TABLE_NAME@[] = {\n" + ) + + # File trailer for build info template + string(CONCAT GENERATED_FILE_TRAILER + "{ NULL, NULL } /* End of list */\n" + "};\n" + "/* End of file */\n" + ) + + # These variables are deferred until build time + foreach (VAR BUILDDATE BUILDUSER BUILDHOST) + list (APPEND GENERATED_FILE_CONTENT "{ \"${VAR}\", \"@${VAR}@\" },") + endforeach () + string(REPLACE ";" "\n" GENERATED_FILE_CONTENT "${GENERATED_FILE_CONTENT}") + + # Write a template for build/config information + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_BINARY_DIR}/cfe_build_env.in) + + # Content for version info - all are deferred until build time + set(GENERATED_FILE_CONTENT) + foreach(DEP "MISSION" ${MISSION_DEPS}) + list (APPEND GENERATED_FILE_CONTENT "{ \"${DEP}\", @${DEP}_VERSION@ },") + endforeach() + string(REPLACE ";" "\n" GENERATED_FILE_CONTENT "${GENERATED_FILE_CONTENT}") + + # Write a template for version information + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_BINARY_DIR}/cfe_module_version.in) + + # The actual version information (to fill out the template above) is obtained at build time + # via a script that is executed as a build target. If this script exists in the mission defs + # directory (user-supplied) then use that. Otherwise a pre-canned "git" version is included + # as a fallback, which should work for source trees assembled via git submodules or subtrees. + if (EXISTS "${MISSION_DEFS}/generate_module_version.cmake") + set(VERSION_SCRIPT "${MISSION_DEFS}/generate_module_version.cmake") + else() + set(VERSION_SCRIPT "${CFE_SOURCE_DIR}/cmake/generate_git_module_version.cmake") + endif() + + add_custom_target(cfe-module-version + COMMAND + ${CMAKE_COMMAND} -D BIN=${CMAKE_BINARY_DIR} + -P "${VERSION_SCRIPT}" + WORKING_DIRECTORY + ${CMAKE_SOURCE_DIR} + VERBATIM + ) + + add_custom_target(cfe-build-env + COMMAND + ${CMAKE_COMMAND} -D BIN=${CMAKE_BINARY_DIR} + -P "${CFE_SOURCE_DIR}/cmake/generate_build_env.cmake" + WORKING_DIRECTORY + ${CMAKE_SOURCE_DIR} + VERBATIM + ) + + # Content for build info - these vars can be evaulated right now, no need to defer + set(GENERATED_FILE_HEADER "/* Automatically generated from CMake build system */") + string(CONCAT GENERATED_FILE_CONTENT + "const char CFE_MISSION_NAME[] = \"${MISSION_NAME}\";\n" + "const char CFE_MISSION_CONFIG[] = \"${MISSIONCONFIG}\";\n" + ) + set(GENERATED_FILE_TRAILER "/* End of file */") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_BINARY_DIR}/src/cfe_mission_strings.c) + + add_custom_target(mission-version + DEPENDS cfe-module-version cfe-build-env + ) + +endfunction(generate_build_version_templates) + ################################################################## # @@ -267,17 +356,8 @@ function(prepare) endif (NOT "${${VARL}}" STREQUAL "") endforeach(VARL ${VARLIST}) file(WRITE "${CMAKE_BINARY_DIR}/mission_vars.cache" "${MISSION_VARCACHE}") - - # Generate version information for the executable file. This is done by executing a small CMAKE - # at _build_ time (not at prep time since it might change between now and then) that collects - # the info out of the version control system in use (git is currently assumed). - add_custom_target(mission-version - COMMAND - ${CMAKE_COMMAND} -D BIN=${CMAKE_BINARY_DIR} - -P ${CFE_SOURCE_DIR}/cmake/version.cmake - WORKING_DIRECTORY - ${CMAKE_SOURCE_DIR} - ) + + generate_build_version_templates() # Generate the tools for the native (host) arch add_subdirectory(${MISSION_SOURCE_DIR}/tools tools) diff --git a/cmake/sample_defs/cpu1_platform_cfg.h b/cmake/sample_defs/cpu1_platform_cfg.h index 8ab9735b8..92cf6efa8 100644 --- a/cmake/sample_defs/cpu1_platform_cfg.h +++ b/cmake/sample_defs/cpu1_platform_cfg.h @@ -822,69 +822,6 @@ */ #define CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE "/ram/cfe_es_startup.scr" -/** -** \cfeescfg Default Shell Filename -** -** \par Description: -** The value of this constant defines the filename used to store the shell -** output after a shell command is received by ES. This file contains the -** entire shell output. The fsw also sends the shell output in series of fixed -** size telemetry packets. This filename is used only when no filename -** is specified in the shell command. -** -** \par Limits -** The length of each string, including the NULL terminator cannot exceed the -** #OS_MAX_PATH_LEN value. -*/ -#define CFE_PLATFORM_ES_DEFAULT_SHELL_FILENAME "/ram/ShellCmd.out" - - -/** -** \cfeescfg Define Max Shell Command Size -** -** \par Description: -** Defines the maximum size in characters of the shell command. -** -** \par Limits -** There is a lower limit of 64 and an upper limit of #OS_MAX_CMD_LEN. Units are -** characters. -*/ -#define CFE_PLATFORM_ES_MAX_SHELL_CMD 64 - - -/** -** \cfeescfg Define Shell Command Telemetry Pkt Segment Size -** -** \par Description: -** Defines the size of the shell command tlm packet segments.The shell command -** output size is dependant on the shell command itself. If the shell output -** size is greater than the size of the packet defined here, the fsw will -** generate a series of tlm packets (of the size defined here) that can be -** reconstructed by the ground system. -** -** \par Limits -** There is a lower limit of 32 and an upper limit of #CFE_MISSION_SB_MAX_SB_MSG_SIZE. -*/ -#define CFE_PLATFORM_ES_MAX_SHELL_PKT 64 - -/** -** \cfeescfg Define OS Task Delay Value for ES Shell Command -** -** \par Description: -** This parameter defines the length of time (in milliseconds) ES will -** delay when sending shell command packets over the software bus to not -** flood the pipe on large messages. -** -** Note: The milliseconds passed into OS_TaskDelay are converted into the -** units the underlying OS uses to measure time passing. Many platforms -** limit the precision of this value however, a delay may not be -** needed at all in which the value may be set to zero. -** -** \par Limits -** Not Applicable -*/ -#define CFE_PLATFORM_ES_SHELL_OS_DELAY_MILLISEC 200 - /** ** \cfeescfg Default Application Information Filename ** diff --git a/cmake/sample_defs/sample_mission_cfg.h b/cmake/sample_defs/sample_mission_cfg.h index c6a241853..7f8b7e895 100644 --- a/cmake/sample_defs/sample_mission_cfg.h +++ b/cmake/sample_defs/sample_mission_cfg.h @@ -382,7 +382,6 @@ #define CFE_MISSION_TBL_REG_TLM_MSG 12 #define CFE_MISSION_SB_ALLSUBS_TLM_MSG 13 #define CFE_MISSION_SB_ONESUB_TLM_MSG 14 -#define CFE_MISSION_ES_SHELL_TLM_MSG 15 #define CFE_MISSION_ES_MEMSTATS_TLM_MSG 16 /** @@ -401,51 +400,6 @@ */ #define CFE_MISSION_ES_MAX_APPLICATIONS 16 - -/** -** \cfeescfg Define Max Shell Command Size for messages -** -** \par Description: -** Defines the maximum size in characters of the shell command. -** -** This affects the layout of command/telemetry messages but does not affect run -** time behavior or internal allocation. -** -** \par Limits -** All CPUs within the same SB domain (mission) must share the same definition -** Note this affects the size of messages, so it must not cause any message -** to exceed the max length. -** -** This value should be kept as a multiple of 4, to maintain alignment of -** any possible neighboring fields without implicit padding. -*/ -#define CFE_MISSION_ES_MAX_SHELL_CMD 64 - - -/** -** \cfeescfg Define Shell Command Telemetry Pkt Segment Size for messages -** -** \par Description: -** Defines the size of the shell command tlm packet segments.The shell command -** output size is dependant on the shell command itself. If the shell output -** size is greater than the size of the packet defined here, the fsw will -** generate a series of tlm packets (of the size defined here) that can be -** reconstructed by the ground system. -** -** This affects the layout of command/telemetry messages but does not affect run -** time behavior or internal allocation. -** -** \par Limits -** All CPUs within the same SB domain (mission) must share the same definition -** Note this affects the size of messages, so it must not cause any message -** to exceed the max length. -** -** This value should be kept as a multiple of 4, to maintain alignment of -** any possible neighboring fields without implicit padding. -** -*/ -#define CFE_MISSION_ES_MAX_SHELL_PKT 64 - /** ** \cfeescfg Define Max Number of Performance IDs for messages ** diff --git a/cmake/target/CMakeLists.txt b/cmake/target/CMakeLists.txt index 6ef722b6a..826874f74 100644 --- a/cmake/target/CMakeLists.txt +++ b/cmake/target/CMakeLists.txt @@ -21,30 +21,108 @@ if (NOT DEFINED ${TGTNAME}_PROCESSORID) message(FATAL_ERROR "${TGTNAME}_PROCESSORID must be defined to link a final exe") endif (NOT DEFINED ${TGTNAME}_PROCESSORID) -# Create a file for the statically-linked module list for this target -# do this for both PSP and CFS static modules -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp" - "/* Automatically generated based on target config */\n") +string(CONCAT GENERATED_FILE_HEADER + "/* This file is auto-generated from CMake build system. Do not manually edit! */\n" + "#include \"target_config.h\"\n" +) + +string(CONCAT GENERATED_FILE_TRAILER + "/* End of file */\n" +) + +# Generate a list of PSP modules along with a pointer to its API structure/entry point +set(GENERATED_EXTERNS) +set(GENERATED_KEYVALS) foreach(PSPMOD ${${TGTNAME}_PSP_MODULELIST}) - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp" "LOAD_PSP_MODULE(${PSPMOD})\n") + list(APPEND GENERATED_EXTERNS "extern char CFE_PSP_${PSPMOD}_API;\n") + list(APPEND GENERATED_KEYVALS "{ .Name = \"${PSPMOD}\", .Api = &CFE_PSP_${PSPMOD}_API },\n") endforeach(PSPMOD ${${TGTNAME}_PSP_MODULELIST}) -execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp" - "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc") -file (REMOVE "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp" - "/* Automatically generated based on target config */\n") +string(CONCAT GENERATED_FILE_CONTENT + ${GENERATED_EXTERNS} + "const CFE_StaticModuleLoadEntry_t CFE_PSP_MODULE_LIST[] = {\n" + ${GENERATED_KEYVALS} + "{ NULL } /* End of list */\n" + "};\n" +) + +configure_file(${CFE_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_CURRENT_BINARY_DIR}/cfe_psp_module_list.c) + +# Generate lists of modules that will be statically linked into this CFE core target +set(GENERATED_ENTRIES_CORE_MODULES) +foreach(DEP ${MISSION_CORE_MODULES}) + list(APPEND GENERATED_ENTRIES_CORE_MODULES "{ \"${DEP}\" },\n") +endforeach() + +set(GENERATED_ENTRIES_STATIC_APPS) +foreach(DEP ${${TGTNAME}_STATIC_APPLIST}) + list(APPEND GENERATED_ENTRIES_STATIC_APPS "{ \"${DEP}\" },\n") +endforeach() + +string(CONCAT GENERATED_FILE_CONTENT + "CFE_ConfigName_t CFE_CORE_MODULE_LIST[] = {\n" + ${GENERATED_ENTRIES_CORE_MODULES} + "{ NULL } /* End of list */\n" + "};\n" + "CFE_ConfigName_t CFE_STATIC_APP_LIST[] = {\n" + ${GENERATED_ENTRIES_STATIC_APPS} + "{ NULL } /* End of list */\n" + "};\n" +) + +configure_file(${CFE_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_CURRENT_BINARY_DIR}/cfe_static_module_list.c) + +# Generate a list of symbol names that must be known at runtime without OS loader support +set(GENERATED_EXTERNS) +set(GENERATED_KEYVALS) foreach(CFSSYM ${${TGTNAME}_STATIC_SYMLIST}) - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp" "STATIC_CFS_SYMBOL(${CFSSYM})\n") + string(REPLACE "," ";" CFSSYM "${CFSSYM}") + list(GET CFSSYM 0 SYM_NAME) + list(GET CFSSYM 1 SYM_MODULE) + list(APPEND GENERATED_EXTERNS "extern void ${SYM_NAME} (void);\n") + list(APPEND GENERATED_KEYVALS "{ .Name = \"${SYM_NAME}\", .Address = &{SYM_NAME}, .Module = \"${SYM_MODULE}\" },") endforeach(CFSSYM ${${TGTNAME}_STATIC_SYMLIST}) -execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp" - "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc") -file (REMOVE "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp") + +string(CONCAT GENERATED_FILE_HEADER + "/* This file is auto-generated from CMake build system. Do not manually edit! */\n" + "#include \"osapi-module.h\"\n" +) + +string(CONCAT GENERATED_FILE_CONTENT + ${GENERATED_EXTERNS} + "OS_static_symbol_record_t OS_STATIC_SYMBOL_TABLE[] = {\n" + ${GENERATED_KEYVALS} + "{ NULL } /* End of list */\n" + "};\n" +) + +configure_file(${CFE_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_CURRENT_BINARY_DIR}/cfe_static_symbol_list.c) + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cfe_build_env_table.c + COMMAND ${CMAKE_COMMAND} -E copy + ${MISSION_BINARY_DIR}/src/cfe_build_env_table.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_build_env_table.c + DEPENDS + ${MISSION_BINARY_DIR}/src/cfe_build_env_table.c +) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cfe_module_version_table.c + COMMAND ${CMAKE_COMMAND} -E copy + ${MISSION_BINARY_DIR}/src/cfe_module_version_table.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_module_version_table.c + DEPENDS + ${MISSION_BINARY_DIR}/src/cfe_module_version_table.c +) # Target for the final executable -add_executable(core-${TGTNAME} src/target_config.c) +add_executable(core-${TGTNAME} + ${MISSION_BINARY_DIR}/src/cfe_mission_strings.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_module_version_table.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_build_env_table.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_psp_module_list.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_static_symbol_list.c + ${CMAKE_CURRENT_BINARY_DIR}/cfe_static_module_list.c + src/target_config.c +) target_compile_definitions(core-${TGTNAME} PRIVATE CFE_DEFAULT_MODULE_EXTENSION="${CMAKE_SHARED_MODULE_SUFFIX}" @@ -54,8 +132,7 @@ target_compile_definitions(core-${TGTNAME} PRIVATE CFE_CPU_ID_VALUE=${${TGTNAME}_PROCESSORID} ) -target_include_directories(core-${TGTNAME} PRIVATE - "${CMAKE_CURRENT_BINARY_DIR}" +target_include_directories(core-${TGTNAME} PRIVATE "${CMAKE_BINARY_DIR}/${CFE_CORE_TARGET}/inc" ) diff --git a/cmake/target/inc/target_config.h b/cmake/target/inc/target_config.h index 4c19bb6e1..dd05c1706 100644 --- a/cmake/target/inc/target_config.h +++ b/cmake/target/inc/target_config.h @@ -76,6 +76,27 @@ typedef const struct CFE_StaticModuleApi_t *Api; } CFE_StaticModuleLoadEntry_t; +/** + * A record containing a configuration name + * This is a single entry in a list of simple strings. + */ +typedef const struct +{ + const char *Name; +} CFE_ConfigName_t; + + +/** + * A record containing a configuration key-value pair + * The data are simple strings defined at compile time, and + * do not change until next build (always const). + */ +typedef const struct +{ + const char *Key; + const void *Value; +} CFE_ConfigKeyValue_t; + /** * Core Flight Executive configuration information. */ @@ -139,12 +160,30 @@ extern Target_CfeConfigData GLOBAL_CFE_CONFIGDATA; */ typedef const struct { - const char *MissionVersion; /**< Version string acquired from version control system at build time */ - const char *CfeVersion; /**< Version string acquired from version control system at build time */ - const char *OsalVersion; /**< Version string acquired from version control system at build time */ + const char *MissionName; /**< The Mission Name from confguration */ + + /* + * Note: the version strings in these fields should reflect the administratively-assigned + * "semantic version" identifiers, typically from a "version.h" header file of + * some type which is manually updated at various points in the development cycle. + * + * This is separate/distinct from the source control based revision + * information, although it may be similar/related. All automatically + * obtained source revision info is in the "ModuleVersionList" below. + */ + const char *MissionVersion; /**< Version string from mission source tree at build time (currently unused/unset) */ + const char *CfeVersion; /**< Version string from CFE source tree at build time */ + const char *OsalVersion; /**< Version string from OSAL source tree at build time */ + const char *Config; /**< Configuration used for build */ - const char *Date; /**< Date and time of build */ - const char *User; /**< User ID and build machine */ + + /* + * Note: date and user info have been moved into the BuildEnvironment below, + * but these members must exist in this structure (for now) for compatibility. + * These pointers will be NULL at runtime. + */ + const char *Date; /**< Not set. Get value from BuildEnvironment instead. */ + const char *User; /**< Not set. Get value from BuildEnvironment instead. */ /* * Default values for CPU ID and CPU Name @@ -160,6 +199,11 @@ typedef const struct Target_PspConfigData *PspConfig; /**< PSP configuration sub-structure */ CFE_StaticModuleLoadEntry_t *PspModuleList; /**< List of PSP modules (API structures) statically linked into the core EXE */ + CFE_ConfigKeyValue_t *BuildEnvironment; /**< Environment details of build system at the last time CFE core was built */ + CFE_ConfigKeyValue_t *ModuleVersionList; /**< List of module versions at the last time CFE core was built */ + CFE_ConfigName_t *CoreModuleList; /**< List of CFE core support module names that are statically linked */ + CFE_ConfigName_t *StaticAppList; /**< List of additional CFS Applications that are statically linked into this binary */ + } Target_ConfigData; diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index 33c6d49aa..6bda3825c 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -38,8 +38,8 @@ #include "cfe_es.h" #include "cfe_time.h" #include "private/cfe_es_resetdata_typedef.h" -#include "cfecfs_version_info.h" -#include "cfecfs_build_info.h" +#include "cfe_version.h" /* for CFE_VERSION_STRING */ +#include "osapi-version.h" /* for OS_VERSION_STRING */ #ifndef CFE_CPU_NAME_VALUE @@ -62,6 +62,78 @@ #define CFE_DEFAULT_CORE_FILENAME "" #endif +/* + * Many configdata items are instantiated by the + * build system, where it generates a .c file containing + * the data, which is then compiled and linked with this file. + */ + +extern const char CFE_MISSION_NAME[]; /**< Name of CFE mission */ +extern const char CFE_MISSION_CONFIG[]; /**< Configuration name used for build */ + +/** + * A list of modules which are statically linked into CFE core. + * + * For module names which appear in this list, the code is directly + * linked into the core executable binary file, and therefore means + * several things: + * + * - the module code is guaranteed to be present + * - functions it provides may be used by CFE core apps + * - it cannot be updated/changed without rebuilding CFE core. + */ +extern CFE_ConfigName_t CFE_CORE_MODULE_LIST[]; + +/** + * A list of CFS apps which are also statically linked with this binary. + * + * These apps can be started without dynamically loading any modules, + * however the entry point must be separately provided in order to avoid + * needing any support from the OS dynamic loader subsystem. + */ +extern CFE_ConfigName_t CFE_STATIC_APP_LIST[]; + +/** + * A key-value table containing certain environment information from the build system + * at the time CFE core was built. + * + * This contains basic information such as the time of day, build host, and user. + */ +extern CFE_ConfigKeyValue_t CFE_BUILD_ENV_TABLE[]; + +/** + * Version control (source code) versions of all modules + * + * This list includes all modules known to the build system as determined by the + * version control system in use (e.g. git). It is generated by a post-build step + * to query version control and should change automatically every time code is + * checked in or out. + * + * Notably this includes _all_ modules known to the build system at the time CFE + * core was built, regardless of whether those modules are configured for runtime + * (dynamic) or static linkage. + * + * For dynamic modules, this means the version info can become outdated if/when + * a single module is rebuilt/reloaded after the original CFE build. The keys in + * this table may be be checked against the CFE_STATIC_MODULE_LIST above to + * determine if static or dynamic linkage was used. In the case of dynamic linkage, + * then this table only represents the version of the module that was present at the + * time CFE was built, not necessarily the version on the target filesystem. + */ +extern CFE_ConfigKeyValue_t CFE_MODULE_VERSION_TABLE[]; + +/** + * A list of PSP modules included in this build of CFE core. + * + * These are always statically linked, and this table contains a pointer + * to its API structure, which in turn contains its entry point. + */ +extern CFE_StaticModuleLoadEntry_t CFE_PSP_MODULE_LIST[]; + + +/** + * A structure that encapsulates all the CFE static configuration + */ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA = { /* @@ -89,47 +161,6 @@ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA = .RamDiskTotalSectors = CFE_PLATFORM_ES_RAM_DISK_NUM_SECTORS }; -/* - * PSP Static Module load section - * - * This is in here (the target-specific file) rather than the PSP config data structure - * because it can be different for different targets even those that share the same basic PSP. - * - * For instance, if two boards use the same basic HW hardware but one of them has a special - * timer interrupt for synchronization, only this second target would include a PSP module - * to bind to that special interrupt. - * - * In order to reference the driver from a dynamically generated set, - * two inclusions of the same file are done using different definitions - * of the LOAD_PSP_MODULE() macro. The first pass creates "extern" references - * to the API objects, the second pass generates a table of pointers to them. - */ - -/* - * Definition of LOAD_*_MODULE for the first pass, creates an extern declaration - * for the API object which must be named appropriately. - */ -#define LOAD_PSP_MODULE(name) extern CFE_StaticModuleApi_t CFE_PSP_##name##_API; -#include "psp_module_list.inc" -#undef LOAD_PSP_MODULE - -/* - * Definition of LOAD_PSP_MODULE for the second pass, creates an entry with - * the name and a pointer to the API object. - * - * This is done here in the target file and NOT in the PSP because it is - * configured specifically to each target. The contents of the "psp_module_list.inc" - * file are generated by the build scripts and are different for each target. - */ -#define LOAD_PSP_MODULE(name) { .Name = #name, .Api = &CFE_PSP_##name##_API }, -static CFE_StaticModuleLoadEntry_t GLOBAL_PSP_MODULELIST[] = -{ -#include "psp_module_list.inc" - { .Name = NULL } -}; -#undef LOAD_PSP_MODULE - - /** * Instantiation of global system-wide configuration struct * This contains build info plus pointers to the PSP and CFE @@ -138,12 +169,10 @@ static CFE_StaticModuleLoadEntry_t GLOBAL_PSP_MODULELIST[] = */ Target_ConfigData GLOBAL_CONFIGDATA = { - .MissionVersion = MISSION_VERSION, - .CfeVersion = CFE_VERSION, - .OsalVersion = OSAL_VERSION, - .Config = MISSION_CONFIG, - .Date = MISSION_BUILDDATE, - .User = MISSION_BUILDUSER "@" MISSION_BUILDHOST, + .MissionName = CFE_MISSION_NAME, + .CfeVersion = CFE_SRC_VERSION, + .OsalVersion = OS_VERSION, + .Config = CFE_MISSION_CONFIG, .Default_CpuName = CFE_CPU_NAME_VALUE, .Default_CpuId = CFE_CPU_ID_VALUE, .Default_SpacecraftId = CFE_SPACECRAFT_ID_VALUE, @@ -151,26 +180,10 @@ Target_ConfigData GLOBAL_CONFIGDATA = .Default_CoreFilename = CFE_DEFAULT_CORE_FILENAME, .CfeConfig = &GLOBAL_CFE_CONFIGDATA, .PspConfig = &GLOBAL_PSP_CONFIGDATA, - .PspModuleList = GLOBAL_PSP_MODULELIST, + .PspModuleList = CFE_PSP_MODULE_LIST, + .BuildEnvironment = CFE_BUILD_ENV_TABLE, + .ModuleVersionList = CFE_MODULE_VERSION_TABLE, + .CoreModuleList = CFE_CORE_MODULE_LIST, + .StaticAppList = CFE_STATIC_APP_LIST, }; - - -/* - * Instantiate a list of symbols that should be statically linked into the - * final executable. - * - * This table is in turn used by OSAL if the OS_STATIC_LOADER feature is - * enabled, such that OS_SymbolLookup may return values from this table - * in lieu of an OS/library-provided dynamic lookup function. - */ -#define STATIC_CFS_SYMBOL(n,m) extern void n (void); -#include "cfs_static_symbol_list.inc" -#undef STATIC_CFS_SYMBOL -#define STATIC_CFS_SYMBOL(n,m) { .Name = #n, .Address = n, .Module = #m }, -OS_static_symbol_record_t OS_STATIC_SYMBOL_TABLE[] = -{ -#include "cfs_static_symbol_list.inc" - { NULL, NULL } /* End of list marker */ -}; -#undef STATIC_CFS_SYMBOL diff --git a/cmake/version.cmake b/cmake/version.cmake deleted file mode 100644 index 5a0bdb8c7..000000000 --- a/cmake/version.cmake +++ /dev/null @@ -1,133 +0,0 @@ -################################################################## -# -# cFS version metadata collection script -# -# This small script runs at build time (as opposed to prep time) -# and is intended to extract version metadata from the current source -# tree. It is done each time that the code is built, since the -# metadata could change at any time (i.e. a different branch could -# be checked out, or additional changes committed) -# -# This generates two header files: -# cfecfs_version_info.h -- contains version control metadata -# cfecfs_build_info.h -- contains build information (user,host,etc) -# -# Currently only git is supported as a version control source, however -# it could be extended to others by adding the appropriate command -# -################################################################## - -set(GIT_EXECUTABLE git) - -function(get_version DEP) - if (DEP STREQUAL "MISSION") - set(NAME ${MISSION_NAME}) - set(DIR ${MISSION_SOURCE_DIR}) - else() - if(EXISTS ${${DEP}_MISSION_DIR}/version_info.cmake) - include(${${DEP}_MISSION_DIR}/version_info.cmake) - else() - set(NAME ${DEP}) - endif() - set(DIR ${${DEP}_MISSION_DIR}) - endif() - execute_process( - COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty - WORKING_DIRECTORY ${DIR} - OUTPUT_VARIABLE GIT_DESC_OUTPUT - RESULT_VARIABLE GIT_RESULT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if (NOT GIT_RESULT EQUAL 0) - set(GIT_DESC_OUTPUT "error/unknown") - endif() - set(${DEP}_NAME "${NAME}" PARENT_SCOPE) - set(${DEP}_VERSION "${GIT_DESC_OUTPUT}" PARENT_SCOPE) -endfunction() - - -# First read in any variables that are passed in from the parent process -# There may be many of these and they may not all be passable via -D options -file(STRINGS "${BIN}/mission_vars.cache" PARENTVARS) -set(VARNAME) -foreach(PV ${PARENTVARS}) - if (VARNAME) - set(${VARNAME} ${PV}) - set(VARNAME) - else() - set(VARNAME ${PV}) - endif() -endforeach(PV ${PARENTVARS}) - -# Set other well-known locations -set(OSAL_MISSION_DIR ${MISSION_SOURCE_DIR}/osal) - -# Start the template for configure_file() -- -# see below why it is done this way and not written directly -file(WRITE ${BIN}/cfecfs_version_info.h.in - "/* Auto-generated version information file */\n" - "#define MISSION_CONFIG \"\@MISSIONCONFIG\@\"\n" - "#define MISSION_NAME \"\@MISSION_NAME\@\"\n") - -# Get version for all mission apps/dependencies (they may be different) -foreach(DEP "MISSION" ${MISSION_DEPS}) - get_version(${DEP}) - string(TOUPPER ${${DEP}_NAME} MACRONAME) - string(REGEX REPLACE "[^A-Z0-9_]+" "_" MACRONAME "${MACRONAME}") - file(APPEND ${BIN}/cfecfs_version_info.h.in "#define ${MACRONAME}_VERSION \"\@${DEP}_VERSION\@\"\n") -endforeach() - -string(TOUPPER ${MISSION_NAME} MACRONAME) -file(APPEND ${BIN}/cfecfs_version_info.h.in "\n#define MISSION_VERSION ${MACRONAME}_VERSION\n\n /* end */\n") - -# Same for build information - -# note this is done separately because the build time might change often - -# only the final target EXE should include build.h (nothing else in the mission) to minimize rebuilds -file(WRITE ${BIN}/cfecfs_build_info.h.in - "/* Auto-generated build information file */\n" - "#define MISSION_BUILDDATE \"\@BUILDDATE\@\"\n" - "#define MISSION_BUILDUSER \"\@USERNAME\@\"\n" - "#define MISSION_BUILDHOST \"\@HOSTNAME\@\"\n\n") - -# OVERRIDE NOTE: -# All 3 of these may be passed via environment variables to force a particular -# date, user, or hostname i.e. if hoping to reproduce an exact binary of a prior build -# They are actually free-form strings so they can be anything up to 64 chars. - -# Get the current date and time -set(BUILDDATE $ENV{BUILDDATE}) -if (NOT BUILDDATE) - execute_process( - COMMAND date "+%Y%m%d%H%M" - OUTPUT_VARIABLE BUILDDATE - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -endif(NOT BUILDDATE) - -# Get the build host -set(HOSTNAME $ENV{HOSTNAME}) -if (NOT HOSTNAME) - execute_process( - COMMAND hostname - OUTPUT_VARIABLE HOSTNAME - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -endif (NOT HOSTNAME) - -# Get the user ID -set(USERNAME $ENV{USER}) -if (NOT USERNAME) - execute_process( - COMMAND whoami - OUTPUT_VARIABLE USERNAME - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -endif (NOT USERNAME) - -# Use configure_file() command to generate the final output file because this can detect -# and only update it if it changes. -configure_file(${BIN}/cfecfs_version_info.h.in ${BIN}/inc/cfecfs_version_info.h @ONLY) -configure_file(${BIN}/cfecfs_build_info.h.in ${BIN}/inc/cfecfs_build_info.h @ONLY) - - diff --git a/docs/cFE Application Developers Guide.md b/docs/cFE Application Developers Guide.md index 7ec10cda6..749935a04 100644 --- a/docs/cFE Application Developers Guide.md +++ b/docs/cFE Application Developers Guide.md @@ -1436,8 +1436,8 @@ SAMPLE_AppData_t; SAMPLE_AppData; In this example, the Developer has created a Pipe, called "SAMPLE_PIPE_1" with a depth of 10. The Pipe name shall be at least one character and no more than OS_MAX_API_NAME characters long. Developers should prefix their Pipe -names with the Application's abbreviated name. Although the Pipe names will -not collide with other Application Pipe names in the cFE, the +names with the Application's abbreviated name, because Pipe names will +collide with other Application Pipe names in the cFE. Also the Developer/Operator could become confused if every Application named their Pipe(s) "MY_PIPE". It should be noted, however, that all Pipes for a single Application must have unique names. diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index 4974eb62c..f2618019b 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -1208,9 +1208,11 @@ int32 CFE_ES_GetTaskInfo(CFE_ES_TaskInfo_t *TaskInfo, CFE_ES_TaskId_t TaskId) TaskInfo->TaskId = CFE_ES_TaskRecordGetID(TaskRecPtr); /* - ** Get the Execution counter for the task + ** Get the other stats for the task */ TaskInfo->ExecutionCounter = TaskRecPtr->ExecutionCounter; + TaskInfo->StackSize = TaskRecPtr->StartParams.StackSize; + TaskInfo->Priority = TaskRecPtr->StartParams.Priority; /* ** Get the Application Details diff --git a/fsw/cfe-core/src/es/cfe_es_task.c b/fsw/cfe-core/src/es/cfe_es_task.c index 75bae1b7e..a24cf3c6d 100644 --- a/fsw/cfe-core/src/es/cfe_es_task.c +++ b/fsw/cfe-core/src/es/cfe_es_task.c @@ -184,6 +184,161 @@ void CFE_ES_TaskMain(void) } /* End of CFE_ES_TaskMain() */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* CFE_ES_FindConfigKeyValue() -- Find value for given config key */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +const char *CFE_ES_FindConfigKeyValue(const CFE_ConfigKeyValue_t *ConfigList, const char *KeyName) +{ + const char *ValuePtr; + + ValuePtr = NULL; + if (KeyName != NULL && ConfigList != NULL) + { + while (ConfigList->Key != NULL) + { + if (strcmp(KeyName, ConfigList->Key) == 0) + { + ValuePtr = ConfigList->Value; + break; + } + + ++ConfigList; + } + } + + return ValuePtr; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* CFE_ES_GenerateSingleVersionEvent() -- Send CFE_ES_VERSION_INF_EID */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int32 CFE_ES_GenerateSingleVersionEvent(const char *ModuleType, const char *ModuleName) +{ + int32 Status; + const char *VersionString; + + /* The mission version which should appear in the version list under the mission name */ + VersionString = CFE_ES_FindConfigKeyValue(GLOBAL_CONFIGDATA.ModuleVersionList, ModuleName); + + /* If NULL that means the source code was either uncontrolled or there was no way to determine its version */ + if (VersionString == NULL) + { + VersionString = "[unknown]"; + } + + /* + * Advertise the mission version information + */ + Status = CFE_EVS_SendEvent(CFE_ES_VERSION_INF_EID, CFE_EVS_EventType_INFORMATION, + "Version Info: %s %s, version %s", + ModuleType, ModuleName, VersionString); + + return Status; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* CFE_ES_GenerateVersionEvents() -- Send CFE_ES_VERSION_INF_EID's */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void CFE_ES_GenerateVersionEvents(void) +{ + int32 Status; + CFE_ConfigName_t *ModuleNamePtr; + CFE_StaticModuleLoadEntry_t *StaticModulePtr; + + /* + * Advertise the mission version information + */ + Status = CFE_ES_GenerateSingleVersionEvent("Mission", GLOBAL_CONFIGDATA.MissionName); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("ES:Error sending mission version event:RC=0x%08X\n", (unsigned int)Status); + } + + /* + * Also Advertise the version information for all statically-linked core modules. + * Send a separate CFE_ES_VERSION_INF_EID for every component. + */ + ModuleNamePtr = GLOBAL_CONFIGDATA.CoreModuleList; + if (ModuleNamePtr != NULL) + { + while (Status == CFE_SUCCESS && ModuleNamePtr->Name != NULL) + { + Status = CFE_ES_GenerateSingleVersionEvent("Core Module", ModuleNamePtr->Name); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("ES:Error sending core module version event:RC=0x%08X\n", (unsigned int)Status); + } + ++ModuleNamePtr; + } + } + + /* + * Advertise PSP module versions + */ + StaticModulePtr = GLOBAL_CONFIGDATA.PspModuleList; + if (StaticModulePtr != NULL) + { + while (Status == CFE_SUCCESS && StaticModulePtr->Name != NULL) + { + Status = CFE_ES_GenerateSingleVersionEvent("PSP Module", StaticModulePtr->Name); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("ES:Error sending PSP module version event:RC=0x%08X\n", (unsigned int)Status); + } + ++StaticModulePtr; + } + } +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* CFE_ES_GenerateBuildInfoEvents() -- Send CFE_ES_BUILD_INF_EID */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void CFE_ES_GenerateBuildInfoEvents(void) +{ + int32 Status; + const char *BuildDate; + const char *BuildUser; + const char *BuildHost; + + BuildDate = CFE_ES_FindConfigKeyValue(GLOBAL_CONFIGDATA.BuildEnvironment, "BUILDDATE"); + BuildUser = CFE_ES_FindConfigKeyValue(GLOBAL_CONFIGDATA.BuildEnvironment, "BUILDUSER"); + BuildHost = CFE_ES_FindConfigKeyValue(GLOBAL_CONFIGDATA.BuildEnvironment, "BUILDHOST"); + + /* Ensure all strings are set to something non-NULL */ + if (BuildDate == NULL) + { + BuildDate = "[unknown]"; + } + + if (BuildUser == NULL) + { + BuildUser = "[unknown]"; + } + + if (BuildHost == NULL) + { + BuildHost = "[unknown]"; + } + + Status = CFE_EVS_SendEvent(CFE_ES_BUILD_INF_EID, CFE_EVS_EventType_INFORMATION, + "Build %s by %s@%s, config %s", BuildDate, BuildUser, BuildHost, GLOBAL_CONFIGDATA.Config); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("ES:Error sending build info event:RC=0x%08X\n", (unsigned int)Status); + } +} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ @@ -196,9 +351,6 @@ int32 CFE_ES_TaskInit(void) int32 Status; uint32 SizeofCfeSegment; cpuaddr CfeSegmentAddr; - char EventBuffer[CFE_MISSION_EVS_MAX_MESSAGE_LENGTH]; - char VersionBuffer[CFE_MISSION_EVS_MAX_MESSAGE_LENGTH]; - uint32 Remaining; /* ** Register the Application @@ -329,74 +481,21 @@ int32 CFE_ES_TaskInit(void) return(Status); } -#ifdef CFE_PSP_VERSION - - Status = CFE_EVS_SendEvent(CFE_ES_INITSTATS_INF_EID, CFE_EVS_EventType_INFORMATION, - "%s%s. cFE chksm %d", - CFS_VERSIONS, CFE_PSP_VERSION, (int)CFE_ES_TaskData.HkPacket.Payload.CFECoreChecksum); - -#else /* if CFE_PSP_VERSION not defined use integer version macros*/ - Status = CFE_EVS_SendEvent(CFE_ES_INITSTATS_INF_EID, CFE_EVS_EventType_INFORMATION, - "\n%sv%d.%d.%d.%d\n cFE chksm %d", - CFS_VERSIONS, - CFE_PSP_MAJOR_VERSION, CFE_PSP_MINOR_VERSION, CFE_PSP_REVISION, CFE_PSP_MISSION_REV, - (int)CFE_ES_TaskData.HkPacket.Payload.CFECoreChecksum); - -#endif /* CFE_PSP_VERSION */ + Status = CFE_EVS_SendEvent(CFE_ES_INITSTATS_INF_EID, CFE_EVS_EventType_INFORMATION, + "cFS Versions: cfe %s, osal %s, psp %s. cFE chksm %d", + GLOBAL_CONFIGDATA.CfeVersion, GLOBAL_CONFIGDATA.OsalVersion, CFE_PSP_VERSION, (int)CFE_ES_TaskData.HkPacket.Payload.CFECoreChecksum); if ( Status != CFE_SUCCESS ) { - CFE_ES_WriteToSysLog("ES:Error sending version event:RC=0x%08X\n", (unsigned int)Status); + CFE_ES_WriteToSysLog("ES:Error sending init stats event:RC=0x%08X\n", (unsigned int)Status); return(Status); } /* - ** Advertise the build and version information at start up - ** If unique and non-error, reports component information + * Generate all module version and build info events. */ - if (strstr(GLOBAL_CONFIGDATA.MissionVersion, "error")) - { - snprintf(EventBuffer, sizeof(EventBuffer), "Mission %s", GLOBAL_CONFIGDATA.Config); - } - else - { - snprintf(EventBuffer, sizeof(EventBuffer), "Mission %s.%s", - GLOBAL_CONFIGDATA.MissionVersion, GLOBAL_CONFIGDATA.Config); - } - Remaining = sizeof(EventBuffer)-strlen(EventBuffer)-1; - if(Remaining > 0 && strcmp(GLOBAL_CONFIGDATA.MissionVersion, GLOBAL_CONFIGDATA.CfeVersion)) - { - snprintf(VersionBuffer, sizeof(VersionBuffer), ", CFE git version: %s", - GLOBAL_CONFIGDATA.CfeVersion); - VersionBuffer[Remaining] = 0; - strcat(EventBuffer, VersionBuffer); - Remaining = sizeof(EventBuffer)-strlen(EventBuffer)-1; - } - if(Remaining > 0 && strcmp(GLOBAL_CONFIGDATA.MissionVersion, GLOBAL_CONFIGDATA.OsalVersion)) - { - snprintf(VersionBuffer, sizeof(VersionBuffer), ", OSAL git version: %s", - GLOBAL_CONFIGDATA.OsalVersion); - VersionBuffer[Remaining] = 0; - strcat(EventBuffer, VersionBuffer); - } - - Status = CFE_EVS_SendEvent(CFE_ES_VERSION_INF_EID, - CFE_EVS_EventType_INFORMATION, "%s", EventBuffer); - if ( Status != CFE_SUCCESS ) - { - CFE_ES_WriteToSysLog("ES:Error sending version event:RC=0x%08X\n", (unsigned int)Status); - return(Status); - } - - Status = CFE_EVS_SendEvent(CFE_ES_BUILD_INF_EID, - CFE_EVS_EventType_INFORMATION, - "Build %s %s", - GLOBAL_CONFIGDATA.Date, GLOBAL_CONFIGDATA.User); - if ( Status != CFE_SUCCESS ) - { - CFE_ES_WriteToSysLog("ES:Error sending build info event:RC=0x%08X\n", (unsigned int)Status); - return(Status); - } + CFE_ES_GenerateVersionEvents(); + CFE_ES_GenerateBuildInfoEvents(); /* * Initialize the "background task" which is a low priority child task @@ -743,7 +842,6 @@ int32 CFE_ES_HousekeepingCmd(const CFE_MSG_CommandHeader_t *data) return CFE_SUCCESS; } /* End of CFE_ES_HousekeepingCmd() */ - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* CFE_ES_NoopCmd() -- ES task ground command (NO-OP) */ @@ -757,30 +855,17 @@ int32 CFE_ES_NoopCmd(const CFE_ES_NoopCmd_t *Cmd) ** For unit testing purposes, it helps to put this first - the UT ** is checking for the last event sent to be NOOP_INF_EID. */ - CFE_EVS_SendEvent(CFE_ES_BUILD_INF_EID, - CFE_EVS_EventType_INFORMATION, - "Build %s %s", - GLOBAL_CONFIGDATA.Date, GLOBAL_CONFIGDATA.User); + CFE_ES_GenerateBuildInfoEvents(); /* ** This command will always succeed. */ CFE_ES_TaskData.CommandCounter++; - -#ifdef CFE_PSP_VERSION - CFE_EVS_SendEvent(CFE_ES_NOOP_INF_EID, CFE_EVS_EventType_INFORMATION, - "No-op command:\n %s%s", - CFS_VERSIONS, CFE_PSP_VERSION); - -#else /* CFE_PSP_VERSION */ - CFE_EVS_SendEvent(CFE_ES_NOOP_INF_EID, CFE_EVS_EventType_INFORMATION, - "No-op command:\n %sv%d.%d.%d.%d", - CFS_VERSIONS, - CFE_PSP_MAJOR_VERSION, CFE_PSP_MINOR_VERSION, CFE_PSP_REVISION, CFE_PSP_MISSION_REV); + "No-op command:\n cFS Versions: cfe %s, osal %s, psp %s", + GLOBAL_CONFIGDATA.CfeVersion, GLOBAL_CONFIGDATA.OsalVersion, CFE_PSP_VERSION); -#endif /* CFE_PSP_VERSION */ return CFE_SUCCESS; } /* End of CFE_ES_NoopCmd() */ diff --git a/fsw/cfe-core/src/es/cfe_es_verify.h b/fsw/cfe-core/src/es/cfe_es_verify.h index b27beafbc..63d48f4cc 100644 --- a/fsw/cfe-core/src/es/cfe_es_verify.h +++ b/fsw/cfe-core/src/es/cfe_es_verify.h @@ -120,30 +120,6 @@ #error CFE_PLATFORM_ES_USER_RESERVED_SIZE cannot be greater than UINT32_MAX (4 Gigabytes)! #endif -/* -** The size of a command to the OS that lies under the cFE -*/ -#if CFE_PLATFORM_ES_MAX_SHELL_CMD < 64 - #error CFE_PLATFORM_ES_MAX_SHELL_CMD cannot be less than 64! -#endif - -/* -** The size of a command to the OS that lies under the cFE must avoid overflow -*/ -#if CFE_PLATFORM_ES_MAX_SHELL_CMD > OS_MAX_CMD_LEN - #error CFE_PLATFORM_ES_MAX_SHELL_CMD cannot be greater than OS_MAX_CMD_LEN! -#endif - -/* -** The size of the chunks to break the output of the shell command into - * to send down in telemetry -*/ -#if CFE_PLATFORM_ES_MAX_SHELL_PKT < 32 - #error CFE_PLATFORM_ES_MAX_SHELL_PKT cannot be less than 32! -#elif CFE_PLATFORM_ES_MAX_SHELL_PKT > CFE_MISSION_SB_MAX_SB_MSG_SIZE - #error CFE_PLATFORM_ES_MAX_SHELL_PKT cannot be greater than CFE_MISSION_SB_MAX_SB_MSG_SIZE! -#endif - /* ** SysLog mode */ @@ -353,12 +329,6 @@ #if ((CFE_MISSION_MAX_FILE_LEN % 4) != 0) #error CFE_MISSION_MAX_FILE_LEN must be a multiple of 4 #endif -#if ((CFE_MISSION_ES_MAX_SHELL_CMD % 4) != 0) - #error CFE_MISSION_ES_MAX_SHELL_CMD must be a multiple of 4 -#endif -#if ((CFE_MISSION_ES_MAX_SHELL_PKT % 4) != 0) - #error CFE_MISSION_ES_MAX_SHELL_PKT must be a multiple of 4 -#endif #if ((CFE_MISSION_ES_CDS_MAX_NAME_LENGTH % 4) != 0) #error CFE_MISSION_ES_CDS_MAX_NAME_LENGTH must be a multiple of 4 #endif diff --git a/fsw/cfe-core/src/inc/cfe_es.h b/fsw/cfe-core/src/inc/cfe_es.h index 2e00165bf..0da600fc7 100644 --- a/fsw/cfe-core/src/inc/cfe_es.h +++ b/fsw/cfe-core/src/inc/cfe_es.h @@ -1176,8 +1176,12 @@ CFE_Status_t CFE_ES_WriteToSysLog(const char *SpecStringPtr, ...) OS_PRINTF(1,2) ** a single value. Nominally, the user should set this value to zero. ** ** \param[in] TypeCRC One of the following CRC algorithm selections: -** \arg \c CFE_MISSION_ES_CRC_8 - (Not currently implemented) -** \arg \c CFE_MISSION_ES_CRC_16 - a CRC-16 algorithm +** \arg \c CFE_MISSION_ES_CRC_8 - (Not currently implemented) +** \arg \c CFE_MISSION_ES_CRC_16 - CRC-16/ARC
+** Polynomial: 0x8005
+** Initialization: 0x0000
+** Reflect Input/Output: true
+** XorOut: 0x0000 ** \arg \c CFE_MISSION_ES_CRC_32 - (not currently implemented) ** ** \return The result of the CRC calculation on the specified memory block, or error code \ref CFEReturnCodes diff --git a/fsw/cfe-core/src/inc/cfe_es_events.h b/fsw/cfe-core/src/inc/cfe_es_events.h index 29cbe4312..1d2d3d93a 100644 --- a/fsw/cfe-core/src/inc/cfe_es_events.h +++ b/fsw/cfe-core/src/inc/cfe_es_events.h @@ -1409,24 +1409,30 @@ #define CFE_ES_TASKINFO_WR_ERR_EID 90 -/** \brief 'Mission %s.%s, %s, %s' -** \event 'Mission %s.%s, %s, %s' +/** \brief 'Version Info: %s, %s' +** \event 'Version Info: %s, %s' ** ** \par Type: INFORMATION ** ** \par Cause: ** ** This event message is always automatically issued when the Executive Services -** Task completes its Initialization +** Task completes its Initialization and as part of the Noop command ** -** The \c Mission field identifies the tagged build identifiers and configuration name. -** If available, this will also indicate the revision control identifiers for CFE and OSAL -** that this binary was built with. +** A separate version info event will be generated for every module which is statically +** linked into the CFE core executable (e.g. OSAL, PSP, MSG, SBR, etc). +** +** The version information reported in this event is derived from the source revision +** control system at build time, as opposed to manually-assigned semantic version numbers. +** It is intendended to uniquely identify the actual source code that is currently running, +** to the extent this is possible. +** +** The \c Mission version information also identifies the build configuration name, if available. **/ #define CFE_ES_VERSION_INF_EID 91 -/** \brief 'Build %s %s' -** \event 'Build %s %s' +/** \brief 'Build %s by %s@%s, config %s' +** \event 'Build %s by %s@%s, config %s' ** ** \par Type: INFORMATION ** @@ -1439,6 +1445,9 @@ ** the build host machine for the current running binary. The first string is the ** build date/time, and the second string is formatted as "user@hostname" ** +** This additionally reports the configuration name that was selected by the user, +** which may affect various platform/mission limits. +** ** By default, if not specified/overridden, the default values of these variables will be: ** BUILDDATE ==> the output of "date +%Y%m%d%H%M" ** HOSTNAME ==> the output of "hostname" diff --git a/fsw/cfe-core/src/inc/cfe_es_msg.h b/fsw/cfe-core/src/inc/cfe_es_msg.h index 83ba04c39..de4bd34e9 100644 --- a/fsw/cfe-core/src/inc/cfe_es_msg.h +++ b/fsw/cfe-core/src/inc/cfe_es_msg.h @@ -1497,11 +1497,14 @@ typedef struct CFE_ES_AppInfo */ typedef struct CFE_ES_TaskInfo { - CFE_ES_TaskId_t TaskId; /**< \brief Task Id */ - uint32 ExecutionCounter; /**< \brief Task Execution Counter */ - char TaskName[CFE_MISSION_MAX_API_LEN]; /**< \brief Task Name */ - CFE_ES_AppId_t AppId; /**< \brief Parent Application ID */ - char AppName[CFE_MISSION_MAX_API_LEN]; /**< \brief Parent Application Name */ + CFE_ES_TaskId_t TaskId; /**< \brief Task Id */ + uint32 ExecutionCounter; /**< \brief Task Execution Counter */ + char TaskName[CFE_MISSION_MAX_API_LEN]; /**< \brief Task Name */ + CFE_ES_AppId_t AppId; /**< \brief Parent Application ID */ + char AppName[CFE_MISSION_MAX_API_LEN]; /**< \brief Parent Application Name */ + CFE_ES_MemOffset_t StackSize; /**< Size of task stack */ + CFE_ES_TaskPriority_Atom_t Priority; /**< Priority of task */ + uint8 Spare[2]; /**< Spare bytes for alignment */ } CFE_ES_TaskInfo_t; /**