diff --git a/cmake/sample_defs/cpu1_cfe_es_startup.scr b/cmake/sample_defs/cpu1_cfe_es_startup.scr deleted file mode 100644 index c1ae84981..000000000 --- a/cmake/sample_defs/cpu1_cfe_es_startup.scr +++ /dev/null @@ -1,30 +0,0 @@ -CFE_LIB, /cf/sample_lib.so, SAMPLE_LibInit, SAMPLE_LIB, 0, 0, 0x0, 0; -CFE_APP, /cf/sample_app.so, SAMPLE_AppMain, 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; -! -! Startup script fields: -! 1. Object Type -- CFE_APP for an Application, or CFE_LIB for a library. -! 2. Path/Filename -- This is a cFE Virtual filename, not a vxWorks device/pathname -! 3. Entry Point -- This is the "main" function for Apps. -! 4. CFE Name -- The cFE name for the the APP or Library -! 5. Priority -- This is the Priority of the App, not used for Library -! 6. Stack Size -- This is the Stack size for the App, not used for the Library -! 7. Load Address -- This is the Optional Load Address for the App or Library. Currently not implemented -! so keep it at 0x0. -! 8. Exception Action -- This is the Action the cFE should take if the App has an exception. -! 0 = Just restart the Application -! Non-Zero = Do a cFE Processor Reset -! -! Other Notes: -! 1. The software will not try to parse anything after the first '!' character it sees. That -! is the End of File marker. -! 2. Common Application file extensions: -! Linux = .so ( ci.so ) -! OS X = .bundle ( ci.bundle ) -! Cygwin = .dll ( ci.dll ) -! vxWorks = .o ( ci.o ) -! RTEMS with S-record Loader = .s3r ( ci.s3r ) -! RTEMS with CEXP Loader = .o ( ci.o ) - diff --git a/cmake/sample_defs/cpu1_platform_cfg.h b/cmake/sample_defs/cpu1_platform_cfg.h index be21bc89d..658200304 100644 --- a/cmake/sample_defs/cpu1_platform_cfg.h +++ b/cmake/sample_defs/cpu1_platform_cfg.h @@ -823,10 +823,10 @@ /** -** \cfeescfg ES Nonvolatile Startup Filename +** \cfeescfg ES Startup Table Filename ** ** \par Description: -** The value of this constant defines the path and name of the file that +** The value of this constant defines the path and name of the table file that ** contains a list of modules that will be loaded and started by the cFE after ** the cFE finishes its startup sequence. ** @@ -834,23 +834,9 @@ ** The length of each string, including the NULL terminator cannot exceed the ** #OS_MAX_PATH_LEN value. */ -#define CFE_PLATFORM_ES_NONVOL_STARTUP_FILE "/cf/cfe_es_startup.scr" +#define CFE_PLATFORM_ES_TBL_FILE "/cf/cfe_es_start.tbl" -/** -** \cfeescfg ES Volatile Startup Filename -** -** \par Description: -** The value of this constant defines the path and name of the file that -** contains a list of modules that will be loaded and started by the cFE after -** the cFE finishes its startup sequence. -** -** \par Limits -** The length of each string, including the NULL terminator cannot exceed the -** #OS_MAX_PATH_LEN value. -*/ -#define CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE "/ram/cfe_es_startup.scr" - /** ** \cfeescfg Default Shell Filename ** diff --git a/cmake/sample_defs/tables/cpu1_cfe_es_start.c b/cmake/sample_defs/tables/cpu1_cfe_es_start.c new file mode 100644 index 000000000..c76d57dbe --- /dev/null +++ b/cmake/sample_defs/tables/cpu1_cfe_es_start.c @@ -0,0 +1,93 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** File: +** cfe_es_start.c +** +** Purpose: +** Provides the load-time configuration of which shared libraries and applications should +** be loaded into the cFS instance. +** +** References: +** +** Notes: +** +** Modification History: +** +*/ + +/* +** Required header files. +*/ + +#include "cfe_tbl_filedef.h" /* Required for the CFE_TBL_FILEDEF macro */ +#include "cfe_es_table.h" + +CFE_ES_AppLibTbl_t CFE_ES_AppLibTbl = { + /** Libraries **/ + .Libs = { + /** { , } **/ + { /* Lib #0 */ + .Name = "SAMPLE_LIB", + .FileName = "/cf/sample_lib.so", + .EntryPoint = "SAMPLE_LibInit" + }, + }, + /** Applications **/ + { + /** { , , , , , + <1 == reset processor on err> } **/ + { /* App #0 */ + .Name = "SAMPLE_APP", + .FileName = "/cf/sample_app.so", + .EntryPoint = "SAMPLE_AppMain", + .StackSize = 16384, + .Priority = 50, + .ExceptionAction = 0 + }, + { /* App #1 */ + .Name = "CI_LAB", + .FileName = "/cf/ci_lab.so", + .EntryPoint = "CI_Lab_AppMain", + .StackSize = 16384, + .Priority = 60, + .ExceptionAction = 0 + }, + { /* App #2 */ + .Name = "TO_LAB", + .FileName = "/cf/to_lab.so", + .EntryPoint = "TO_Lab_AppMain", + .StackSize = 16384, + .Priority = 70, + .ExceptionAction = 0 + }, + { /* App #3 */ + .Name = "SCH_LAB_APP", + .FileName = "/cf/sch_lab.so", + .EntryPoint = "SCH_Lab_AppMain", + .StackSize = 16384, + .Priority = 80, + .ExceptionAction = 0 + }, + } +}; + +CFE_TBL_FILEDEF(CFE_ES_AppLibTbl, CFE_ES.CFE_ES_AppLibTbl, ES App and Lib Table, cfe_es_start.tbl) diff --git a/cmake/sample_defs/targets.cmake b/cmake/sample_defs/targets.cmake index 03d72f454..330999aea 100644 --- a/cmake/sample_defs/targets.cmake +++ b/cmake/sample_defs/targets.cmake @@ -86,15 +86,12 @@ SET(FT_INSTALL_SUBDIR "host/functional-test") # Each target board can have its own HW arch selection and set of included apps SET(TGT1_NAME cpu1) SET(TGT1_APPLIST sample_app sample_lib ci_lab to_lab sch_lab) -SET(TGT1_FILELIST cfe_es_startup.scr) # CPU2/3 are duplicates of CPU1. These are not built by default anymore but are # commented out to serve as an example of how one would configure multiple cpus. #SET(TGT2_NAME cpu2) #SET(TGT2_APPLIST sample_app ci_lab to_lab sch_lab) -#SET(TGT2_FILELIST cfe_es_startup.scr) #SET(TGT3_NAME cpu3) #SET(TGT3_APPLIST sample_app ci_lab to_lab sch_lab) -#SET(TGT3_FILELIST cfe_es_startup.scr) diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index 1bde3d10b..19a7e9f6a 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -67,7 +67,7 @@ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA = * Default values for Startup file. * This is a suggested value, but the PSP may provide a different file */ - .NonvolStartupFile = CFE_PLATFORM_ES_NONVOL_STARTUP_FILE, + .NonvolStartupFile = CFE_PLATFORM_ES_TBL_FILE, /* * Sizes of other memory segments diff --git a/fsw/cfe-core/CMakeLists.txt b/fsw/cfe-core/CMakeLists.txt index d7337425e..cfc897e63 100644 --- a/fsw/cfe-core/CMakeLists.txt +++ b/fsw/cfe-core/CMakeLists.txt @@ -36,9 +36,8 @@ foreach(MODULE ${CFE_CORE_MODULES} config shared) endforeach(MODULE ${CFE_CORE_MODULES}) add_library(${CFE_CORE_TARGET} STATIC ${CFE_ALL_MODULE_SRCS}) +add_cfe_tables(ES cfe_es_start.c) if (ENABLE_UNIT_TESTS) add_subdirectory(unit-test) endif (ENABLE_UNIT_TESTS) - - diff --git a/fsw/cfe-core/src/es/cfe_es_apps.c b/fsw/cfe-core/src/es/cfe_es_apps.c index 579d50eeb..8ff34161b 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.c +++ b/fsw/cfe-core/src/es/cfe_es_apps.c @@ -67,283 +67,6 @@ *************************************************************************** */ -/* -** Name: -** CFE_ES_StartApplications -** -** Purpose: -** This routine loads/starts cFE applications. -** -*/ -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 */ - const char *TokenList[CFE_ES_STARTSCRIPT_MAX_TOKENS_PER_LINE]; - uint32 NumTokens; - uint32 BuffLen = 0; /* Length of the current buffer */ - int32 AppFile = 0; - char c; - int32 ReadStatus; - bool LineTooLong = false; - bool FileOpened = false; - - /* - ** Get the ES startup script filename. - ** If this is a Processor Reset, try to open the file in the volatile disk first. - */ - if ( ResetType == CFE_PSP_RST_TYPE_PROCESSOR ) - { - /* - ** Open the file in the volatile disk. - */ - AppFile = OS_open( CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE, O_RDONLY, 0); - - if ( AppFile >= 0 ) - { - CFE_ES_WriteToSysLog ("ES Startup: Opened ES App Startup file: %s\n", - CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE); - FileOpened = true; - } - else - { - CFE_ES_WriteToSysLog ("ES Startup: Cannot Open Volatile Startup file, Trying Nonvolatile.\n"); - FileOpened = false; - } - - } /* end if */ - - /* - ** This if block covers two cases: A Power on reset, and a Processor reset when - ** the startup file on the volatile file system could not be opened. - */ - if ( FileOpened == false ) - { - /* - ** Try to Open the file passed in to the cFE start. - */ - AppFile = OS_open( (const char *)StartFilePath, O_RDONLY, 0); - - if ( AppFile >= 0 ) - { - CFE_ES_WriteToSysLog ("ES Startup: Opened ES App Startup file: %s\n",StartFilePath); - FileOpened = true; - } - else - { - CFE_ES_WriteToSysLog ("ES Startup: Error, Can't Open ES App Startup file: %s EC = 0x%08X\n", - StartFilePath, (unsigned int)AppFile ); - FileOpened = false; - } - - } - - /* - ** If the file is opened in either the Nonvolatile or the Volatile disk, process it. - */ - if ( FileOpened == true) - { - memset(ES_AppLoadBuffer,0x0,ES_START_BUFF_SIZE); - BuffLen = 0; - NumTokens = 0; - TokenList[0] = ES_AppLoadBuffer; - - /* - ** Parse the lines from the file. If it has an error - ** or reaches EOF, then abort the loop. - */ - while(1) - { - ReadStatus = OS_read(AppFile, &c, 1); - if ( ReadStatus == OS_FS_ERROR ) - { - CFE_ES_WriteToSysLog ("ES Startup: Error Reading Startup file. EC = 0x%08X\n",(unsigned int)ReadStatus); - break; - } - else if ( ReadStatus == 0 ) - { - /* - ** EOF Reached - */ - break; - } - else if(c != '!') - { - if ( c <= ' ') - { - /* - ** Skip all white space in the file - */ - ; - } - else if ( c == ',' ) - { - /* - ** replace the field delimiter with a null - ** This is used to separate the tokens - */ - if ( BuffLen < ES_START_BUFF_SIZE ) - { - ES_AppLoadBuffer[BuffLen] = 0; - } - else - { - LineTooLong = true; - } - BuffLen++; - - if ( NumTokens < (CFE_ES_STARTSCRIPT_MAX_TOKENS_PER_LINE-1)) - { - /* - * NOTE: pointer never deferenced unless "LineTooLong" is false. - */ - ++NumTokens; - TokenList[NumTokens] = &ES_AppLoadBuffer[BuffLen]; - } - } - else if ( c != ';' ) - { - /* - ** Regular data gets copied in - */ - if ( BuffLen < ES_START_BUFF_SIZE ) - { - ES_AppLoadBuffer[BuffLen] = c; - } - else - { - LineTooLong = true; - } - BuffLen++; - } - else - { - if ( LineTooLong == true ) - { - /* - ** The was too big for the buffer - */ - CFE_ES_WriteToSysLog ("ES Startup: ES Startup File Line is too long: %u bytes.\n",(unsigned int)BuffLen); - LineTooLong = false; - } - else - { - /* - ** Send the line to the file parser - ** Ensure termination of the last token and send it along - */ - ES_AppLoadBuffer[BuffLen] = 0; - CFE_ES_ParseFileEntry(TokenList, 1 + NumTokens); - } - BuffLen = 0; - NumTokens = 0; - } - } - else - { - /* - ** break when EOF character '!' is reached - */ - break; - } - } - /* - ** close the file - */ - OS_close(AppFile); - - } -} - -/* -**--------------------------------------------------------------------------------------- -** Name: CFE_ES_ParseFileEntry -** -** Purpose: This function parses the startup file line for an individual -** cFE application. -**--------------------------------------------------------------------------------------- -*/ -int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) -{ - const char *FileName; - const char *AppName; - const char *EntryPoint; - const char *EntryType; - unsigned int Priority; - unsigned int StackSize; - unsigned int ExceptionAction; - uint32 ApplicationId; - int32 CreateStatus = CFE_ES_ERR_APP_CREATE; - - /* - ** Check to see if the correct number of items were parsed - */ - if ( NumTokens < 8 ) - { - CFE_ES_WriteToSysLog("ES Startup: Invalid ES Startup file entry: %u\n",(unsigned int)NumTokens); - return (CreateStatus); - } - - EntryType = TokenList[0]; - FileName = TokenList[1]; - EntryPoint = TokenList[2]; - AppName = TokenList[3]; - - /* - * NOTE: In previous CFE versions the sscanf() function was used to convert - * these string values into integers. This approach of using the pre-tokenized strings - * and strtoul() is safer but the side effect is that it will also be more "permissive" in - * what is accepted vs. rejected by this function. - * - * For instance if the startup script contains "123xyz", this will be converted to the value - * 123 instead of triggering a validation failure as it would have in CFE <= 6.5.0. - * - * This permissive parsing should not be relied upon, as it may become more strict again in - * future CFE revisions. - */ - Priority = strtoul(TokenList[4], NULL, 0); - StackSize = strtoul(TokenList[5], NULL, 0); - ExceptionAction = strtoul(TokenList[7], NULL, 0); - - if(strcmp(EntryType,"CFE_APP")==0) - { - CFE_ES_WriteToSysLog("ES Startup: Loading file: %s, APP: %s\n", - FileName, AppName); - - /* - ** Validate Some parameters - ** Exception action should be 0 ( Restart App ) or - ** 1 ( Processor reset ). If it's non-zero, assume it means - ** reset CPU. - */ - if ( ExceptionAction > CFE_ES_ExceptionAction_RESTART_APP ) - ExceptionAction = CFE_ES_ExceptionAction_PROC_RESTART; - /* - ** Now create the application - */ - CreateStatus = CFE_ES_AppCreate(&ApplicationId, FileName, - EntryPoint, AppName, (uint32) Priority, - (uint32) StackSize, (uint32) ExceptionAction ); - } - else if(strcmp(EntryType,"CFE_LIB")==0) - { - CFE_ES_WriteToSysLog("ES Startup: Loading shared library: %s\n",FileName); - - /* - ** Now load the library - */ - CreateStatus = CFE_ES_LoadLibrary(&ApplicationId, FileName, - EntryPoint, AppName); - - } - else - { - CFE_ES_WriteToSysLog("ES Startup: Unexpected EntryType %s in startup file.\n",EntryType); - } - - return (CreateStatus); - -} - /* **--------------------------------------------------------------------------------------- ** Name: ES_AppCreate diff --git a/fsw/cfe-core/src/es/cfe_es_apps.h b/fsw/cfe-core/src/es/cfe_es_apps.h index fe1715c84..79871aa20 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.h +++ b/fsw/cfe-core/src/es/cfe_es_apps.h @@ -140,11 +140,6 @@ typedef struct ** Function prototypes */ -/* -** Internal function start applications based on the startup script -*/ -void CFE_ES_StartApplications(uint32 ResetType, const char *StartFilePath ); - /* ** Internal function to parse/execute a line of the cFE application startup 'script' */ diff --git a/fsw/cfe-core/src/es/cfe_es_global.h b/fsw/cfe-core/src/es/cfe_es_global.h index 756fce951..1d924c4ff 100644 --- a/fsw/cfe-core/src/es/cfe_es_global.h +++ b/fsw/cfe-core/src/es/cfe_es_global.h @@ -44,6 +44,7 @@ #include "cfe_es_apps.h" #include "cfe_es_cds.h" #include "cfe_es_perf.h" +#include "cfe_es_table.h" #include "cfe_time.h" #include "cfe_platform_cfg.h" #include "cfe_evs.h" diff --git a/fsw/cfe-core/src/es/cfe_es_start.c b/fsw/cfe-core/src/es/cfe_es_start.c index c8799f30f..bc92b1e12 100644 --- a/fsw/cfe-core/src/es/cfe_es_start.c +++ b/fsw/cfe-core/src/es/cfe_es_start.c @@ -192,13 +192,6 @@ void CFE_ES_Main(uint32 StartType, uint32 StartSubtype, uint32 ModeId, const cha CFE_ES_WriteToSysLog("ES Startup: CFE_ES_Main entering CORE_READY state\n"); CFE_ES_Global.SystemState = CFE_ES_SystemState_CORE_READY; - /* - ** Start the cFE Applications from the disk using the file - ** specified in the CFE_PLATFORM_ES_NONVOL_STARTUP_FILE or CFE_PLATFORM_ES_VOLATILE_STARTUP_FILE - ** ( defined in the cfe_platform_cfg.h file ) - */ - CFE_ES_StartApplications(StartType, StartFilePath ); - /* * Wait for applications to be in at least "LATE_INIT" * diff --git a/fsw/cfe-core/src/es/cfe_es_task.c b/fsw/cfe-core/src/es/cfe_es_task.c index de746cfc3..c7838418d 100644 --- a/fsw/cfe-core/src/es/cfe_es_task.c +++ b/fsw/cfe-core/src/es/cfe_es_task.c @@ -207,6 +207,8 @@ int32 CFE_ES_TaskInit(void) cpuaddr CfeSegmentAddr; char EventBuffer[CFE_MISSION_EVS_MAX_MESSAGE_LENGTH]; char VersionBuffer[CFE_MISSION_EVS_MAX_MESSAGE_LENGTH]; + CFE_TBL_Handle_t TblHandle; + CFE_ES_AppLibTbl_t *AppLibTbl = NULL; /* ** Register the Application @@ -398,6 +400,73 @@ int32 CFE_ES_TaskInit(void) return(Status); } + /* + ** Bind and load the CFE_TBL tables. + */ + + Status = CFE_TBL_Register( + &TblHandle, "CFE_ES_AppLibTbl", sizeof(*AppLibTbl), CFE_TBL_OPT_DEFAULT, NULL); + if (Status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Unable to reg app table (Status=%d)\n", (int)Status); + } + + if (Status == CFE_SUCCESS) + { + Status = CFE_TBL_Load(TblHandle, CFE_TBL_SRC_FILE, GLOBAL_CFE_CONFIGDATA.NonvolStartupFile); + if (Status != CFE_SUCCESS) + { + CFE_TBL_Unregister(TblHandle); + CFE_ES_WriteToSysLog("ES Startup: Unable to load app table (Status=%d)\n", (int)Status); + } + } + + if (Status == CFE_SUCCESS) + { + CFE_TBL_GetAddress((void **)&AppLibTbl, TblHandle); + } + + if (Status == CFE_SUCCESS) + { + int i = 0; + uint32 ID = 0; + + for (i = 0; i < CFE_PLATFORM_ES_MAX_LIBRARIES; i++) + { + CFE_ES_LibTblEntry_t *e = &AppLibTbl->Libs[i]; + + if (*e->Name == '\0') break; /**< first empty name signals end of the table */ + + CFE_ES_WriteToSysLog("ES Startup: Loading lib: %s, %s\n", e->FileName, e->Name); + Status = CFE_ES_LoadLibrary(&ID, e->FileName, e->EntryPoint, e->Name); + + if(Status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Failed to load lib: %s\n", e->FileName); + /* ...but continue to process more libraries */ + } + } + + for (i = 0; i < CFE_PLATFORM_ES_MAX_APPLICATIONS; i++) + { + CFE_ES_AppTblEntry_t *e = &AppLibTbl->Apps[i]; + + if (*e->Name == '\0') break; /**< first empty name signals end of the table */ + + CFE_ES_WriteToSysLog("ES Startup: Loading file: %s, %s\n", e->FileName, e->Name); + + Status = CFE_ES_AppCreate(&ID, e->FileName, e->EntryPoint, e->Name, (uint32) e->Priority, (uint32) e->StackSize, (uint32) e->ExceptionAction); + + if(Status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Failed to load app %s\n", e->FileName); + /* ...but continue to process more apps */ + } + } + + /* we're done with the table, the data's been copied into other structures */ + CFE_TBL_Unregister(TblHandle); + } return(CFE_SUCCESS); diff --git a/fsw/cfe-core/src/inc/cfe_es_table.h b/fsw/cfe-core/src/inc/cfe_es_table.h new file mode 100644 index 000000000..9b34c5e6c --- /dev/null +++ b/fsw/cfe-core/src/inc/cfe_es_table.h @@ -0,0 +1,36 @@ +#ifndef cfe_es_table_h +#define cfe_es_table_h + +#include "cfe_platform_cfg.h" +#include "osconfig.h" + +typedef struct +{ + char Name[OS_MAX_API_NAME]; /**< \cfetlmmnemonic \ES_APPNAME \brief The registered name of the library */ + char FileName[OS_MAX_PATH_LEN]; /**< \cfetlmmnemonic \ES_APPFILENAME \brief The filename of the file containing the library */ + char EntryPoint[OS_MAX_API_NAME]; /**< \cfetlmmnemonic \ES_APPENTRYPT \brief The entry point label for the library */ +} +CFE_ES_LibTblEntry_t; + +typedef struct +{ + char Name[OS_MAX_API_NAME]; /**< \cfetlmmnemonic \ES_APPNAME \brief The registered name of the application */ + char FileName[OS_MAX_PATH_LEN]; /**< \cfetlmmnemonic \ES_APPFILENAME \brief The filename of the file containing the application */ + char EntryPoint[OS_MAX_API_NAME]; /**< \cfetlmmnemonic \ES_APPENTRYPT \brief The entry point label for the application */ + uint32 StackSize; /**< \cfetlmmnemonic \ES_STACKSIZE */ + uint16 Priority; /**< \cfetlmmnemonic \ES_PRIORITY \brief The priority of the application */ + uint8 ExceptionAction; /**< \cfetlmmnemonic \ES_EXCEPTNACTN \brief What should occur if application has an exception (restart application or restart processor) */ +} +CFE_ES_AppTblEntry_t; + +typedef struct +{ + /** indicate the end of the libraries with a zero-length Name */ + CFE_ES_LibTblEntry_t Libs[CFE_PLATFORM_ES_MAX_LIBRARIES]; + + /** indicate the end of the applications with zero-length Name */ + CFE_ES_AppTblEntry_t Apps[CFE_PLATFORM_ES_MAX_APPLICATIONS]; +} +CFE_ES_AppLibTbl_t; + +#endif /* cfe_es_table_h */