diff options
Diffstat (limited to 'src/usr/initservice/baseinitsvc')
-rw-r--r-- | src/usr/initservice/baseinitsvc/initservice.C | 233 | ||||
-rw-r--r-- | src/usr/initservice/baseinitsvc/initservice.H | 220 | ||||
-rw-r--r-- | src/usr/initservice/baseinitsvc/initservicetaskentry.C | 49 | ||||
-rw-r--r-- | src/usr/initservice/baseinitsvc/initsvctasks.H | 85 | ||||
-rw-r--r-- | src/usr/initservice/baseinitsvc/makefile | 7 |
5 files changed, 594 insertions, 0 deletions
diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C new file mode 100644 index 000000000..0c3617023 --- /dev/null +++ b/src/usr/initservice/baseinitsvc/initservice.C @@ -0,0 +1,233 @@ +/** + * @file initservice.C + * + * Implements Initialization Service for Host boot. + * See initservice.H for details + * + */ + +#include <kernel/console.H> +#include <sys/vfs.h> +#include <sys/task.h> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <sys/sync.h> + + +#include "initservice.H" +#include "initsvctasks.H" + + + +namespace INITSERVICE +{ + +trace_desc_t *g_trac_initsvc = NULL; +TRAC_INIT(&g_trac_initsvc, "INITSERVICE", 4096); + + +/******************************************************************************/ +// InitService::getTheInstance return the only instance +/******************************************************************************/ +InitService& InitService::getTheInstance() +{ + return Singleton<InitService>::instance(); +} + +/******************************************************************************/ +// InitService::Initservice constructor +/******************************************************************************/ +InitService::InitService() +{ + +} + +/******************************************************************************/ +// InitService::~InitService destructor +/******************************************************************************/ +InitService::~InitService() +{ + +} + +/** + * @todo mechanism to set taskcommand in TaskArgs struct + * @todo check taskreturncode inside of TaskArgs + * @todo test errorlog inside of Taskargs + */ +errlHndl_t InitService::startTask( const TaskInfo *i_ptask, + TaskArgs::TaskArgs *io_pargs, + errlHndl_t &io_rerrl ) const +{ + tid_t tidrc = 0; + + assert(i_ptask->taskflags.task_type == START_TASK); + + tidrc = task_exec( i_ptask->taskname, io_pargs ); // launch the child + + if ( io_pargs ) + { + io_pargs->waitParentSync(); // sync up childtask + } + + if ( static_cast<int16_t>(tidrc) < 0 ) + { + io_rerrl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity + i_ptask->taskflags.module_id, // moduleid + INITSERVICE::START_TASK_FAILED, // reason Code + tidrc, // user1 = tidrc + 0 + ); + TRACDBIN( g_trac_initsvc, + "ERROR starting task:", + i_ptask->taskname, + strlen(i_ptask->taskname) ); + TRACDCOMP( g_trac_initsvc, + "tidrc=%d, errlog p = %p" , + (int16_t)tidrc, io_rerrl ); + + } // endif tidrc + else + { + TRACDBIN( g_trac_initsvc, + "Task finished OK :", + i_ptask->taskname, + strlen(i_ptask->taskname) ); + TRACDCOMP( g_trac_initsvc, + "task number %d, errlog p = %p", + tidrc, io_rerrl ); + } + + return io_rerrl; +} + + +void InitService::reportError(errlHndl_t &io_rerrl ) const +{ + + if ( io_rerrl == NULL ) + { + // this is OK, do nothing + } + else + { + + TRACDCOMP( g_trac_initsvc, + "Committing the error log %p.", + io_rerrl + ); + + errlCommit( io_rerrl ); + + } + + return; +} + + +/** + * @todo this will make a system call to post the error code. + */ +void InitService::setProgressCode( uint64_t &i_progresscode ) const +{ + + // do nothing for now +} + + +/** + * @note For task_type = NONE case, I'm assuming that trace will not crash + * if we have a NULL taskname string, printing it is useful for debug. + */ +void InitService::init( void *i_ptr ) +{ + errlHndl_t errl = NULL; // steps will return an error handle if failure + uint64_t nextTask = 0; + const TaskInfo *ptask = NULL; + TaskArgs::TaskArgs args; + + TRACFCOMP( g_trac_initsvc, + ENTER_MRK "Initialization Service is starting." ); + + // ---------------------------------------------------------------- + // loop through the task list and start up any tasks necessary + // ---------------------------------------------------------------- + + for ( nextTask=0; + nextTask<INITSERVICE::MAX_TASKS; + nextTask++ ) + { + // make a local copy of the base image task + ptask = &(iv_taskinfolist[nextTask]); + if ( ptask->taskflags.task_type == END_TASK_LIST ) + { + TRACDCOMP( g_trac_initsvc, + "End of Initialization Service task list.\n" ); + break; + } + + // dispatch tasks... + switch ( ptask->taskflags.task_type) + { + case NONE: + // task is a place holder, skip + TRACDBIN( g_trac_initsvc, + "task_type==NONE", + ptask->taskname, + strlen( ptask->taskname) ); + break; + case START_TASK: + TRACDBIN( g_trac_initsvc, + "task_type==START_TASK", + ptask->taskname, + strlen( ptask->taskname) ); + errl = startTask( ptask, // task struct + &args, // args + errl ); // errlog + break; + case START_FN: + TRACDCOMP( g_trac_initsvc, + "task_type==START_FN : %p", + ptask->taskfn ); + // $$TODO + break; + case BARRIER: + TRACDCOMP( g_trac_initsvc, + "task_type==BARRIER" ); + // $$TODO + break; + + default: + TRACDCOMP( g_trac_initsvc, + "Invalid task_type %d: ", + ptask->taskflags.task_type ); + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity + BASE_INITSVC_ERRL_ID, // moduleid + INVALID_TASK_TYPE, // reason Code + 0, // user1 = tidrc + 0 ); + break; + + } // endswitch + + // report an error + reportError( errl ); + + } // endfor + + // die if we drop out with an error + assert( errl == NULL); + + + TRACFCOMP( g_trac_initsvc, + EXIT_MRK "Initilization Service finished."); + + // return to _start(), which may end the task or die. + return; +} + + +} // namespace INITSERVICE diff --git a/src/usr/initservice/baseinitsvc/initservice.H b/src/usr/initservice/baseinitsvc/initservice.H new file mode 100644 index 000000000..dd0a7df32 --- /dev/null +++ b/src/usr/initservice/baseinitsvc/initservice.H @@ -0,0 +1,220 @@ +#ifndef __BASEINITSVC_INITSERVICE_H +#define __BASEINITSVC_INITSERVICE_H +/** + * @file initservice.H + * + * - Manage high-level host boot IPL flow + * - Perform can-continue processing + * - Perform automatic and manual Istep execution + * - Handle flow errors as appropriate. + * + */ + +/** + * High-level todo list + * + * @todo SP3: move startTask() and reportError() to private + * @todo SP3: add (NULL) detection to printk + * @@todo Add more macros to trace, discuss with Andrew and Nick + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <util/singleton.H> +#include <sys/vfs.h> // VFS_MODULE_NAME_MAX + +#include <trace/interface.H> +#include <initservice/taskargs.H> +#include <errl/errlentry.H> +#include <initservice/initsvcreasoncodes.H> + + +namespace INITSERVICE +{ + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + + +/******************************************************************************/ +// Typedef/Enumerations +/******************************************************************************/ + +/** + * @enum TaskType + * - NONE == placeholder, no task + * - START_TASK == task with _start() function entry point + * - START_FN == task with function pointer entry point + * - BARRIER == set barrier for next N tasks. + * - STOP_TASK == Execute the destructor on the task in extended image. + * ( not implemented yet) + * - END_TASK_LIST == last entry in the task list. + */ +enum TaskType +{ + UNDEFINED_TT = 0, + NONE, + START_TASK, + START_FN, + BARRIER, + STOP_TASK, + END_TASK_LIST, +}; +/** + * @enum ModuleType + * - BASE_IMAGE == module in the base image + * - EXT_IMAGE == module in the extended image + */ +enum ModuleType +{ + UNDEFINED_MT = 0, + BASE_IMAGE, + EXT_IMAGE, +}; + + +/** + * @struct TaskFlags + * + * - run _start() function on start + * - module type, BASE_MODULE or EXT_MODULE + * - module_id for errorlog if task fails + * + * @todo revisit these flags in sprint3 + */ +struct TaskFlags +{ + TaskType task_type; // this is a task, run _start() function + ModuleType module_type; // BASE_IMAGE or EXT_IMAGE + InitServiceModuleID module_id; // module id for errorlog +}; + +/** + * @struct _TaskInfo + * + * Holds information on each task in the system. + * - taskname + * - execution flags, see TaskFlags above + * + */ +struct TaskInfo +{ + const char taskname[VFS_MODULE_NAME_MAX]; + void (*taskfn)(void *ptr); + const TaskFlags taskflags; + +}; + + +/******************************************************************************/ +// InitService Class +/******************************************************************************/ + +// Singleton definition +class InitService; +typedef Singleton<InitService> theInitService; + +/** + * @class InitService Singleton Class + * + * This class is launched by _start() (see initservicetaskentry.C), + * which is launched by the kernel (init_main.C). + * + * Once started, it handles the rest of HostBoot Initialization. + * + * @returns none + */ +class InitService +{ + +public: + + friend class InitServiceTest; + + /** + * @brief Get singleton instance of this class. + * + * @return the (one and only) instance of InitService + */ + static InitService& getTheInstance(); + + /** + * @brief Provide an entry function into the class, called from _start() + * + * @param[in] i_args pointer to any arguments passed in from + * _start() and by extension the kernel, + * currently this is NULL . + */ + void init( void *i_args); + + /** + * @todo InitServiceTest should be able to find protected functions. + */ + // $$protected: + + /** + * @brief start a task + * + * @param[in] i_ptask pointer to a TaskInfo struct + * @param[in] io_pargs pointer to a TaskArgs struct, or NULL + * @param[inout] io_rerrl reference to an errorlog handle. + * errorlog will be filled out if error, + * otherwise untouched. + * + * @return NULL if success, errorlog handle for failure + * + */ + errlHndl_t startTask( const TaskInfo *i_ptask, + TaskArgs::TaskArgs *i_pargs, + errlHndl_t &io_rerrl ) const; + + + /** + * @brief report Error to the system. + * + * @param[in] io_rerrl - errlHndl_t pointer to a filled-out error entry + * errorlog will be committed, errorlog + * will be deleted, and pointer will be + * set to NULL on exit + * + * @return nothing + */ + void reportError( errlHndl_t &io_rerrl) const; + + + /** + * @brief set progress code for task. + * + * @param[in] i_progresscode - 64-bit progress code. + * + * @return nothing + * + */ + void setProgressCode( uint64_t &i_progresscode ) const; + + + +protected: + + /** + * @brief Constructor for the InitService object. + */ + InitService(); + + /** + * @brief Destructor for the InitService object. + */ + ~InitService(); + + +private: + + +}; // class InitService + +} // namespace INITSERVICE + +#endif diff --git a/src/usr/initservice/baseinitsvc/initservicetaskentry.C b/src/usr/initservice/baseinitsvc/initservicetaskentry.C new file mode 100644 index 000000000..62d531c07 --- /dev/null +++ b/src/usr/initservice/baseinitsvc/initservicetaskentry.C @@ -0,0 +1,49 @@ +/** + * @file initservicetaskentry.C + * task entry point for Initialization Service. + * init_main.C will call this by executing + * task_exec( "libinitservice.so", NULL ); + * From there we can execute the classes that will run in the task. + * + * At the end, we must run task_end(). + */ +#include <kernel/console.H> +#include <sys/vfs.h> +#include <sys/task.h> +#include <trace/interface.H> +#include <errl/errlentry.H> + +#include "initservice.H" + + + +namespace INITSERVICE +{ + +extern trace_desc_t *g_trac_initsvc; + +/** + * @brief task entry routine, called by init_main.C + * + */ + +extern "C" +void _start(void *ptr) +{ + TRACFCOMP( g_trac_initsvc, + ENTER_MRK "Executing Initialization Service module." ); + + + // create an instance of InitService + //InitService::InitService& is = InitService::getTheInstance(); + + // initialize the base modules in Hostboot. + InitService::getTheInstance().init( ptr ); + + TRACFCOMP( g_trac_initsvc, + EXIT_MRK "return from Initialization Service module." ); + + task_end(); +} + +} // INITSERVICE diff --git a/src/usr/initservice/baseinitsvc/initsvctasks.H b/src/usr/initservice/baseinitsvc/initsvctasks.H new file mode 100644 index 000000000..ae3362d31 --- /dev/null +++ b/src/usr/initservice/baseinitsvc/initsvctasks.H @@ -0,0 +1,85 @@ +/** + * @file initsvctasks.H + * + * TaskInfo structs for each task that will run. + */ + +#ifndef __INIT_SVC_TASKS_H +#define __INIT_SVC_TASKS_H + +#include <initservice/initsvcreasoncodes.H> +#include "initservice.H" + +namespace INITSERVICE +{ + +const uint64_t MAX_TASKS = 10; + +const TaskInfo iv_taskinfolist[] = { + + /** + * @brief Errorlog Task + */ + { + "liberrl.so" , // taskname + NULL, // no ptr to fn + { + NONE, // don't start + BASE_IMAGE, // Base Module + START_ERRL_ERRL_ID, // module id for errorlog + + } + }, + + + /** + * @brief PNOR Driver Task + */ + { + "libpnordd.so" , // taskname + NULL, // no pointer to fn + { + NONE, // don't start + BASE_IMAGE, // Base Module + START_PNORDD_ERRL_ID, // module id for errorlog + } + }, + + // ----- Extended Image ----------------------------------------------------- + + /** + * @brief extinitsvc, initializes extended module area + */ + { + "libextinitsvc.so" , // taskname + NULL, // no pointer to fn + { + START_TASK, // don't start + EXT_IMAGE, // Ext Module + START_EXTINITSVC_ERRL_ID, // module id for errorlog + } + }, + + + // --------------------------------------------------------------- + // ----- END OF LIST!!! --------------------------------------- + // --------------------------------------------------------------- + + /** + * @brief last task in the list + */ + { + "end" , // dummy string + NULL, // pointer to fn + { + END_TASK_LIST, // end of list + UNDEFINED_MT, // dummy module type + UNDEFINED_MODULE_ERRL_ID, // dummy errorlog + } + }, + +}; + + +}; // namespace INITSERVICE +#endif // __INIT_SVC_TASKS_H diff --git a/src/usr/initservice/baseinitsvc/makefile b/src/usr/initservice/baseinitsvc/makefile new file mode 100644 index 000000000..45b83ef7d --- /dev/null +++ b/src/usr/initservice/baseinitsvc/makefile @@ -0,0 +1,7 @@ +ROOTPATH = ../../../.. +MODULE = initservice + +OBJS = initservice.o \ + initservicetaskentry.o + +include ${ROOTPATH}/config.mk |