summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/build/doxygen/doxygen.conf8
-rwxr-xr-xsrc/build/tools/addCopyright.pl4
-rw-r--r--src/include/usr/initservice/initsvcreasoncodes.H6
-rw-r--r--src/include/usr/initservice/initsvcstructs.H (renamed from src/usr/initservice/common/initsvcstructs.H)8
-rw-r--r--src/include/usr/initservice/taskargs.H17
-rw-r--r--src/include/usr/isteps/isteplist.H155
-rw-r--r--src/include/usr/isteps/isteps.H50
-rw-r--r--src/makefile4
-rw-r--r--src/usr/initservice/baseinitsvc/initservice.C495
-rw-r--r--src/usr/initservice/baseinitsvc/initservice.H84
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvc.C381
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvc.H18
-rw-r--r--src/usr/initservice/initsvctasktest2/makefile28
-rw-r--r--src/usr/initservice/initsvctasktest2/tasktest2.C (renamed from src/usr/initservice/initsvcunittesttask2/tasktest2.C)0
-rw-r--r--src/usr/initservice/initsvctasktest2/tasktest2.H (renamed from src/usr/initservice/initsvcunittesttask2/tasktest2.H)6
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.C546
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.H135
-rw-r--r--src/usr/initservice/istepdispatcher/isteplist.H81
-rw-r--r--src/usr/initservice/istepdispatcher/makefile3
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommand.C113
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommon.H269
-rw-r--r--src/usr/initservice/istepdispatcher/splessstatus.C93
-rw-r--r--src/usr/initservice/makefile5
-rw-r--r--src/usr/initservice/taskargs/taskargs.C7
-rw-r--r--src/usr/initservice/test/initservicetest.H123
-rw-r--r--src/usr/initservice/test/splesstest.H396
-rw-r--r--src/usr/isteps/istep1.C80
27 files changed, 2320 insertions, 795 deletions
diff --git a/src/build/doxygen/doxygen.conf b/src/build/doxygen/doxygen.conf
index f8f2f4015..ec64e3b5c 100644
--- a/src/build/doxygen/doxygen.conf
+++ b/src/build/doxygen/doxygen.conf
@@ -433,7 +433,7 @@ WARN_IF_DOC_ERROR = YES
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
-WARN_NO_PARAMDOC = NO
+WARN_NO_PARAMDOC = YES
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
@@ -448,7 +448,7 @@ WARN_FORMAT = "$file:$line: $text"
# and error messages should be written. If left blank the output is written
# to stderr.
-WARN_LOGFILE =
+WARN_LOGFILE = doxywarnings.log
#---------------------------------------------------------------------------
# configuration options related to the input files
@@ -821,7 +821,7 @@ LATEX_HIDE_INDICES = NO
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
-GENERATE_RTF = NO
+GENERATE_RTF = YES
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@@ -1121,7 +1121,7 @@ GROUP_GRAPHS = YES
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
-UML_LOOK = NO
+UML_LOOK = YES
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
diff --git a/src/build/tools/addCopyright.pl b/src/build/tools/addCopyright.pl
index 9d12fe921..256be9d3e 100755
--- a/src/build/tools/addCopyright.pl
+++ b/src/build/tools/addCopyright.pl
@@ -133,13 +133,15 @@ while (defined($_ = shift))
##
if ( $operation =~ m/validate/i )
{
+
if ( ! -e $_ )
{
print "---------------------------------------------------------\n";
print "Skipping deleted file: $_\n";
print "---------------------------------------------------------\n";
next;
- }
+ }
+
if ("Unknown" eq $filetype)
{
print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
diff --git a/src/include/usr/initservice/initsvcreasoncodes.H b/src/include/usr/initservice/initsvcreasoncodes.H
index 4ff3fb076..bc4eb3c44 100644
--- a/src/include/usr/initservice/initsvcreasoncodes.H
+++ b/src/include/usr/initservice/initsvcreasoncodes.H
@@ -20,6 +20,7 @@
// Origin: 30
//
// IBM_PROLOG_END
+
/**
* @file initsvcreasoncodes.H
*
@@ -92,7 +93,10 @@ enum InitServiceReasonCode
INVALID_TASK_TYPE = INITSVC_COMP_ID | 0x02,
START_FN_FAILED = INITSVC_COMP_ID | 0x03,
NULL_FN_PTR = INITSVC_COMP_ID | 0x04,
-
+ ISTEP_FAILED_NO_ERRLOG = INITSVC_COMP_ID | 0x05,
+ INITSVC_FAILED_NO_ERRLOG = INITSVC_COMP_ID | 0x06,
+ EXTINITSVC_FAILED_NO_ERRLOG = INITSVC_COMP_ID | 0x07,
+ CXXTEST_FAILED_NO_ERRLOG = INITSVC_COMP_ID | 0x08,
};
diff --git a/src/usr/initservice/common/initsvcstructs.H b/src/include/usr/initservice/initsvcstructs.H
index bf351cc6d..bc459da4b 100644
--- a/src/usr/initservice/common/initsvcstructs.H
+++ b/src/include/usr/initservice/initsvcstructs.H
@@ -20,19 +20,20 @@
// Origin: 30
//
// IBM_PROLOG_END
-
#ifndef __COMMON_INITSVCSTRUCTS_H
#define __COMMON_INITSVCSTRUCTS_H
/**
* @file initsvcstructs.H
*
* common structs for initservice, extinitsvc, istepdispatcher
+ *
*/
/******************************************************************************/
// Includes
/******************************************************************************/
#include <stdint.h>
+#include <sys/vfs.h> // VFS_MODULE_MAX
namespace INITSERVICE
{
@@ -54,11 +55,11 @@ namespace INITSERVICE
* - START_TASK == BASE_IMAGE: call _start() function entry point
* EXT_IMAGE: call _init(), then _start()
* - START_FN == task with function pointer entry point
- * - BARRIER == set barrier for next N tasks.
* - UNINIT_TASK == call _fini() to call static destructor(s) on the task.
* (extended image only)
* - END_TASK_LIST == last entry in the task list.
*/
+
enum TaskType
{
UNDEFINED_TT = 0,
@@ -66,7 +67,6 @@ enum TaskType
INIT_TASK,
START_TASK,
START_FN,
- BARRIER,
UNINIT_TASK,
END_TASK_LIST,
};
@@ -95,7 +95,7 @@ enum ModuleType
*/
struct TaskFlags
{
- TaskType task_type; // this is a task, run _start() function
+ TaskType task_type; // task execution flags
ModuleType module_type; // BASE_IMAGE or EXT_IMAGE
InitServiceModuleID module_id; // module id for errorlog
};
diff --git a/src/include/usr/initservice/taskargs.H b/src/include/usr/initservice/taskargs.H
index c4d81e1a5..fdc24e291 100644
--- a/src/include/usr/initservice/taskargs.H
+++ b/src/include/usr/initservice/taskargs.H
@@ -66,7 +66,7 @@ namespace INITSERVICE
{
/**
- * @const TASKARGS_UNDEFINED64
+ * @def TASKARGS_UNDEFINED64
* iv_taskreturncode and iv_taskcommand are initialized to this value -
* if parent or child change them, it can be easily recognized
*
@@ -112,6 +112,7 @@ public:
* Currently there is no difference between parent and child
* but this may change.
*
+ * @return none
*/
void waitParentSync();
@@ -124,6 +125,7 @@ public:
* Currently there is no difference between parent and child
* but this may change.
*
+ * @return none
*/
void waitChildSync();
@@ -135,6 +137,7 @@ public:
*
* @param[in] i_returncode;
*
+ * @return none.
*/
void postReturnCode( const uint64_t i_returncode );
@@ -156,6 +159,8 @@ public:
* Parent can pass commands and info to the child using this function
*
* @param[in] i_command;
+ *
+ * @return none
*/
void setCommand( const uint64_t i_command );
@@ -165,7 +170,7 @@ public:
*
* Child can get commands from the parent using this function
*
- *@return value of iv_taskcommand;
+ * @return value of iv_taskcommand;
*
* @todo might overload this later if we need to pass structs,
* buffers, etc.
@@ -182,6 +187,7 @@ public:
*
* @param[in] i_errl;
*
+ * @return none
*/
void postErrorLog( errlHndl_t i_errl );
@@ -191,6 +197,11 @@ public:
*
* Parent task can use this to get an errorlog from the child
*
+ * @note This routine sets the iv_errl pointer to the errorlog to NULL
+ * after returning it, so we do not end up with 2 copies of the
+ * pointer. The caller must commit or otherwise handle the
+ * errorlog to avoid a memory leak.
+ *
* @return iv_errl
*
*/
@@ -202,6 +213,8 @@ public:
* - barrier is left alone,
* - if iv_errl is non zero, we commit it here just to avoid
* a memory leak.
+ *
+ * @return none
*/
void clear();
diff --git a/src/include/usr/isteps/isteplist.H b/src/include/usr/isteps/isteplist.H
new file mode 100644
index 000000000..730310b87
--- /dev/null
+++ b/src/include/usr/isteps/isteplist.H
@@ -0,0 +1,155 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/isteps/isteplist.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __ISTEPS_H
+#define __ISTEPS_H
+
+/**
+ * @file isteplist.H
+ *
+ * TaskInfo structs for each task that will run in the extended image.
+ */
+
+#include <vector>
+
+#include <initservice/initsvcreasoncodes.H>
+#include <initservice/initsvcstructs.H>
+
+#include "isteps.H"
+
+
+namespace INITSERVICE
+{
+
+const uint64_t MAX_SUBSTEPS = 25;
+
+/**
+ * @struct ExtTaskInfo
+ *
+ * struct to store the TaskInfo for this IStep, plus the number of items in
+ * the istep (calculated at compiletime).
+ */
+struct ExtTaskInfo
+{
+ const TaskInfo *const pti;
+ const uint64_t numitems;
+};
+
+const TaskInfo istep0[] = {
+
+ {
+ "istep0_substep0" , // istep name
+ ISTEPS::IStep0sub0, // pointer to fn
+ {
+ NONE, // task type
+ EXT_IMAGE, // Extended Module
+ ISTEP_1_ERRL_ID, // module id
+ }
+ },
+
+ {
+ "istep0_substep1" , // istep name
+ ISTEPS::IStep0sub1, // pointer to fn
+ {
+ NONE, // task type
+ EXT_IMAGE, // Extended Module
+ ISTEP_1_ERRL_ID, // module id
+ }
+ },
+
+ // ---------------------------------------------------------------
+ // ----- END OF LIST!!! ---------------------------------------
+ // ---------------------------------------------------------------
+ /**
+ * @brief last task in the list
+ */
+ {
+ "end_istep0" , // dummy string
+ NULL, // pointer to fn
+ {
+ END_TASK_LIST, // end of list
+ UNDEFINED_MT, // dummy module type
+ UNDEFINED_MODULE_ERRL_ID, // dummy errorlog
+ }
+ },
+};
+
+// make a struct from the above with the number of items included
+const ExtTaskInfo g_istep0 = {
+ &(istep0[0]),
+ ( sizeof(istep0)/sizeof(TaskInfo) ) // numitems
+};
+
+
+const TaskInfo istep1[] = {
+
+ /**
+ * @brief targeting task, initializes extended module area
+ */
+ {
+ "istep1_sub0" , // istep name
+ ISTEPS::IStep1sub0, // pointer to fn
+ {
+ NONE, // task type
+ EXT_IMAGE, // Extended Module
+ ISTEP_1_ERRL_ID, // module id
+ }
+ },
+
+ // ---------------------------------------------------------------
+ // ----- 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
+ }
+ },
+};
+
+// make a struct from the above with the number of items included
+ExtTaskInfo g_istep1 = {
+ istep1,
+ ( sizeof(istep1)/sizeof(TaskInfo) )
+};
+
+
+// initialize an array of ExtTaskInfo
+const ExtTaskInfo g_isteps[] = {
+ g_istep0,
+ g_istep1,
+};
+
+// publish the size of the g_isteps array
+const uint64_t MAX_ISTEPS = sizeof(g_isteps)/sizeof(TaskInfo *) ;
+
+
+}; // namespace
+
+#endif
diff --git a/src/include/usr/isteps/isteps.H b/src/include/usr/isteps/isteps.H
new file mode 100644
index 000000000..b8dac9132
--- /dev/null
+++ b/src/include/usr/isteps/isteps.H
@@ -0,0 +1,50 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/isteps/isteps.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/**
+ * @file isteps.H
+ *
+ * Prototypes of ISteps launched by IStepDispatcher
+ * used by isteplist.H
+ *
+ */
+
+
+/******************************************************************************/
+// Includes
+/******************************************************************************/
+#include <stdint.h>
+
+namespace ISTEPS
+{
+
+extern "C"
+void IStep0sub0( void * io_pArgs );
+
+extern "C"
+void IStep0sub1( void * io_pArgs );
+
+extern "C"
+void IStep1sub0( void * io_pArgs );
+
+
+} // namespace
diff --git a/src/makefile b/src/makefile
index 542c7db34..e7db13c28 100644
--- a/src/makefile
+++ b/src/makefile
@@ -50,8 +50,8 @@ DIRECT_BOOT_MODULES = example
RUNTIME_MODULES =
TESTCASE_MODULES = cxxtest testerrl testdevicefw testsyslib \
testscom testxscom testtargeting testinitservice testkernel \
- testhwpf testecmddatabuffer tasktest2 testcxxtest testpnor \
- testi2c
+ testhwpf testecmddatabuffer initsvctasktest2 testcxxtest \
+ testpnor testi2c
RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic
diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C
index ca56b626a..38458f12f 100644
--- a/src/usr/initservice/baseinitsvc/initservice.C
+++ b/src/usr/initservice/baseinitsvc/initservice.C
@@ -29,74 +29,50 @@
*
*/
-#include <kernel/console.H>
-#include <sys/vfs.h>
-#include <vfs/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"
-
-
+#include <kernel/console.H>
+#include <sys/vfs.h>
+#include <vfs/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);
+TRAC_INIT(&g_trac_initsvc, "INITSERVICE", 4096 );
-/******************************************************************************/
-// InitService::getTheInstance return the only instance
-/******************************************************************************/
-InitService& InitService::getTheInstance()
+errlHndl_t InitService::startTask( const TaskInfo *i_ptask,
+ TaskArgs::TaskArgs *io_pargs ) const
{
- return Singleton<InitService>::instance();
-}
+ tid_t l_tidrc = 0;
+ errlHndl_t l_errl = NULL;
-/******************************************************************************/
-// InitService::Initservice constructor
-/******************************************************************************/
-InitService::InitService()
-{
-
-}
-
-/******************************************************************************/
-// InitService::~InitService destructor
-/******************************************************************************/
-InitService::~InitService()
-{
-
-}
-
-
-errlHndl_t InitService::startTask( const TaskInfo *i_ptask,
- TaskArgs::TaskArgs *io_pargs ) const
-{
- tid_t tidrc = 0;
- errlHndl_t lo_errl = NULL;
-
- assert(i_ptask->taskflags.task_type == START_TASK);
+ assert( i_ptask != NULL );
+ assert( i_ptask->taskflags.task_type == START_TASK );
// Base modules have already been loaded and initialized,
// extended modules have not.
- if(i_ptask->taskflags.module_type == EXT_IMAGE)
+ if ( i_ptask->taskflags.module_type == EXT_IMAGE )
{
// load module and call _init()
- lo_errl = VFS::module_load( i_ptask->taskname );
+ l_errl = VFS::module_load( i_ptask->taskname );
}
- if( !lo_errl)
+ if ( ! l_errl )
{
- tidrc = task_exec( i_ptask->taskname, io_pargs ); // launch the child
+ // launch a task and wait for it.
+ l_tidrc = task_exec( i_ptask->taskname, io_pargs );
- if ( static_cast<int16_t>(tidrc) < 0 )
+ // process the return - kernel returns a 16-bit signed # as a
+ // threadid/error
+ if ( static_cast<int16_t> (l_tidrc) < 0 )
{
// task failed to launch, post an errorlog and dump some trace
/*@ errorlog tag
@@ -110,293 +86,284 @@ errlHndl_t InitService::startTask( const TaskInfo *i_ptask,
* The module id will identify the task.
*
*/
- lo_errl = 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:",
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ i_ptask->taskflags.module_id,
+ INITSERVICE::START_TASK_FAILED,
+ l_tidrc,
+ 0 );
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR starting task %s : tidrc=%d, errlog p = %p",
i_ptask->taskname,
- strlen(i_ptask->taskname) );
- TRACDCOMP( g_trac_initsvc,
- "tidrc=%d, errlog p = %p" ,
- (int16_t)tidrc, lo_errl );
-
- } // endif tidrc
+ l_tidrc,
+ l_errl );
+ } // endif tidrc
else
{
// task launched OK.
- 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, lo_errl );
+ "Task %s launched OK: tid=%d",
+ i_ptask->taskname,
+ l_tidrc );
+ // if InitService passed in a taskargs, wait for barrier.
if ( io_pargs )
{
- io_pargs->waitParentSync(); // sync up childtask
+ io_pargs->waitParentSync();
}
- }
- }
- // else module load failed. have error log
+ } // endelse
+ } // endif ! l_errl
- return lo_errl;
-}
+ // return any errorlog to the caller
+ return l_errl;
+}
-errlHndl_t InitService::executeFn( const TaskInfo *i_ptask,
- TaskArgs *io_pargs ) const
+errlHndl_t InitService::executeFn( const TaskInfo *i_ptask,
+ TaskArgs *io_pargs ) const
{
- tid_t tidrc = 0;
- errlHndl_t lo_errl = NULL;
+ tid_t l_tidrc = 0;
+ errlHndl_t l_errl = NULL;
- if ( i_ptask->taskfn == NULL )
+ assert( i_ptask != NULL );
+ assert( i_ptask->taskfn != NULL ) ;
+
+ // valid function, launch it
+ l_tidrc = task_create( i_ptask->taskfn, io_pargs);
+ if (static_cast<int16_t> (l_tidrc) < 0)
{
- TRACDBIN( g_trac_initsvc,
- "ERROR: NULL function pointer:",
- i_ptask->taskname,
- strlen(i_ptask->taskname) );
/*@ errorlog tag
* @errortype ERRL_SEV_CRITICAL_SYS_TERM
* @moduleid see task list
- * @reasoncode NULL_FN_PTR
+ * @reasoncode START_FN_FAILED
* @userdata1 0
* @userdata2 0
*
* @devdesc Initialization Service attempted to start a
- * function within a module but found a NULL pointer
- * instead of the function.
+ * function within a module but the function
+ * failed to launch
* The module id will identify the task.
*/
- lo_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
- i_ptask->taskflags.module_id, // moduleid
- INITSERVICE::NULL_FN_PTR, // reason Code
- 0,
- 0 );
-
- // fall through to end and return bad error log
- }
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ i_ptask->taskflags.module_id,
+ INITSERVICE::START_FN_FAILED,
+ l_tidrc,
+ 0 );
+
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR starting function %s: tidrc=%d, errlog p = %p" ,
+ i_ptask->taskname,
+ l_tidrc,
+ l_errl );
+
+ } // endif tidrc
else
{
- // valid function, launch it
- tidrc = task_create( i_ptask->taskfn, io_pargs );
- if ( static_cast<int16_t>(tidrc) < 0 )
- {
- /*@ errorlog tag
- * @errortype ERRL_SEV_CRITICAL_SYS_TERM
- * @moduleid see task list
- * @reasoncode NULL_FN_PTR
- * @userdata1 0
- * @userdata2 0
- *
- * @devdesc Initialization Service attempted to start a
- * function within a module but the function
- * failed to launch
- * The module id will identify the task.
- */
- lo_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
- i_ptask->taskflags.module_id, // moduleid
- INITSERVICE::START_FN_FAILED, // reason Code
- tidrc, // user1 = tidrc
- 0 );
-
- TRACDBIN( g_trac_initsvc,
- ENTER_MRK "ERROR starting function:",
- i_ptask->taskname,
- strlen(i_ptask->taskname) );
- TRACDCOMP( g_trac_initsvc,
- EXIT_MRK "tidrc=%d, errlog p = %p" ,
- (int16_t)tidrc, lo_errl );
+ TRACDCOMP( g_trac_initsvc,
+ "Function %s launched OK : task number %d",
+ i_ptask->taskname,
+ l_tidrc );
- } // endif tidrc
- else
+ // task launched OK.
+ if ( io_pargs )
{
- TRACDBIN( g_trac_initsvc,
- ENTER_MRK "function launched OK :",
- i_ptask->taskname,
- strlen(i_ptask->taskname) );
- TRACDCOMP( g_trac_initsvc,
- EXIT_MRK "task number %d, errlog p = %p",
- tidrc, lo_errl );
-
- // task launched OK.
- if ( io_pargs )
- {
- io_pargs->waitParentSync(); // sync up parent task
- }
+ io_pargs->waitParentSync(); // sync up parent task
}
+ }
- } // end else
+ return l_errl;
+}
- return lo_errl;
+/**
+ * @todo this will make a system call to post the progress code.
+ *
+ */
+void InitService::setProgressCode( uint64_t i_progresscode ) const
+{
+
+ // do nothing for now
}
-void InitService::reportError(errlHndl_t &io_rerrl ) const
+errlHndl_t InitService::dispatchTask( const TaskInfo *i_ptask,
+ TaskArgs *io_pargs ) const
{
+ errlHndl_t l_errl = NULL;
- if ( io_rerrl == NULL )
- {
- // this is OK, do nothing
- }
- else
- {
+ // dispatch tasks...
+ switch ( i_ptask->taskflags.task_type)
+ {
+ case NONE:
+ // task is a place holder, skip
TRACDCOMP( g_trac_initsvc,
- "Committing the error log %p.",
- io_rerrl );
-
- errlCommit( io_rerrl );
+ "task_type==NONE : %s",
+ i_ptask->taskname );
+ break;
+ case START_TASK:
+ TRACDCOMP( g_trac_initsvc,
+ "task_type==START_TASK: %s",
+ i_ptask->taskname );
+ l_errl = startTask( i_ptask,
+ io_pargs );
+ break;
+ case START_FN:
+ TRACDCOMP( g_trac_initsvc,
+ "task_type==START_FN : %s %p",
+ i_ptask->taskname,
+ i_ptask->taskfn );
+ l_errl = executeFn( i_ptask,
+ io_pargs );
+ break;
+ case UNINIT_TASK:
+ TRACDCOMP( g_trac_initsvc,
+ "task_type=UNINIT_TASK : %s ",
+ i_ptask->taskname );
+ l_errl = VFS::module_unload( i_ptask->taskname );
+ break;
+ default:
+ /**
+ * @note If there is a bad TaskInfo struct we just stop here.
+ */
+ TRACFCOMP( g_trac_initsvc,
+ "Invalid task_type %d: ABORT",
+ i_ptask->taskflags.task_type );
+ assert( 0 );
+ break;
- }
+ } // endswitch
+ return l_errl;
}
-/**
- * @todo this will make a system call to post the error code.
- */
-void InitService::setProgressCode( uint64_t i_progresscode ) const
+void InitService::init( void *i_ptr )
{
-
- // do nothing for now
-}
+ errlHndl_t l_errl = NULL;
+ uint64_t l_task = 0;
+ const TaskInfo *l_ptask = NULL;
+ TaskArgs::TaskArgs l_args;
+ uint64_t l_childrc = 0;
-/**
- * @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." );
+ 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++ )
+ // loop through the task list and start up any tasks necessary
+ for ( l_task=0;
+ l_task < INITSERVICE::MAX_TASKS;
+ l_task++ )
{
// make a local copy of the base image task
- ptask = &(g_taskinfolist[nextTask]);
- if ( ptask->taskflags.task_type == END_TASK_LIST )
+ l_ptask = &(g_taskinfolist[ l_task]);
+ if ( l_ptask->taskflags.task_type == END_TASK_LIST )
{
TRACDCOMP( g_trac_initsvc,
"End of Initialization Service task list.\n" );
break;
}
- args.clear(); // clear args struct for next task
-
- // 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
- break;
- case START_FN:
- TRACDCOMP( g_trac_initsvc,
- "task_type==START_FN : %p",
- ptask->taskfn );
- errl = executeFn( ptask,
- &args );
- break;
- case BARRIER:
- TRACDCOMP( g_trac_initsvc,
- "task_type==BARRIER" );
- // $$TODO
- break;
+ l_args.clear(); // clear args struct for next task
- case UNINIT_TASK:
- TRACDBIN( g_trac_initsvc,
- "task_type=UNINIT_TASK : ",
- ptask->taskname,
- strlen(ptask->taskname) );
- errl = VFS::module_unload( ptask->taskname );
- break;
+ // dispatch the task and return good or errorlog
+ l_errl = dispatchTask( l_ptask,
+ &l_args );
- default:
- TRACDCOMP( g_trac_initsvc,
- "Invalid task_type %d: ",
- ptask->taskflags.task_type );
- /*@ errorlog tag
- * @errortype ERRL_SEV_CRITICAL_SYS_TERM
- * @moduleid BASE_INITSVC_ERRL_ID
- * @reasoncode INVALID_TASK_TYPE
- * @userdata1 task_type value
- * @userdata2 0
- *
- * @devdesc Initialization Service found an invalid
- * Task Type in the task list.
- * The module id will identify the task.
- * task_type value will be the invalid type.
- */
- errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
- BASE_INITSVC_ERRL_ID, // moduleid
- INVALID_TASK_TYPE, // reason Code
- ptask->taskflags.task_type,
- 0 );
+ // process errorlogs returned from the task that was launched
+ if ( l_errl )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR: dispatching task, errorlog=0x%p",
+ l_errl );
+ // drop out with the error
break;
+ }
- } // endswitch
- // report an error
- reportError( errl );
+ // make local copies of the values in TaskArgs that are returned from
+ // the child.
+ // this also clears the errorlog from the TaskArgs struct, so
+ // use it or lose it ( see taskargs.H for details ).
+ l_childrc = l_args.getReturnCode();
+ l_errl = l_args.getErrorLog();
- if ( args.getReturnCode() != TASKARGS_UNDEFINED64 )
+ if ( l_errl )
{
TRACFCOMP( g_trac_initsvc,
- ERR_MRK "InitService TaskArgs returned 0x%llx, errlog=%p",
- args.getReturnCode(),
- args.getErrorLog()
- );
-
- errlHndl_t childerrl = args.getErrorLog(); // local copy
- reportError( childerrl ); // report child error
+ " ERROR: Child task returned 0x%llx, errlog=0x%p",
+ l_childrc,
+ l_errl );
+ // drop out with the error
+ break;
}
-
-
-
- } // endfor
+ else
+ {
+ // Check child results for a valid nonzero return code.
+ // If we have one, and no errorlog, then we create and
+ // post our own errorlog here.
+ if ( ( l_childrc != TASKARGS_UNDEFINED64 )
+ && ( l_childrc != 0 )
+ )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "Child task returned 0x%llx, no errlog",
+ l_childrc );
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid see task list
+ * @reasoncode INITSVC_FAILED_NO_ERRLOG
+ * @userdata1 returncode from task
+ * @userdata2 0
+ *
+ * @devdesc The task returned with an error,
+ * but there was no errorlog returned.
+ *
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ l_ptask->taskflags.module_id,
+ INITSERVICE::INITSVC_FAILED_NO_ERRLOG,
+ l_childrc,
+ 0 );
+ // drop out with the error
+ break;
+ } // end if
+ } // end else
+ } // endfor
// die if we drop out with an error
- assert( errl == NULL);
-
+ if ( l_errl )
+ {
+ // commit the log first, then stop right here.
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR: extra errorlog found: %p",
+ l_errl );
+ errlCommit( l_errl );
+ assert( 0 );
+ }
TRACFCOMP( g_trac_initsvc,
EXIT_MRK "Initilization Service finished.");
- // return to _start(), which may end the task or die.
+ // return to _start()
+}
+
+
+InitService& InitService::getTheInstance( )
+{
+ return Singleton<InitService>::instance();
}
-} // namespace
+InitService::InitService( )
+{ }
+
+
+InitService::~InitService( )
+{ }
+
+} // namespace
diff --git a/src/usr/initservice/baseinitsvc/initservice.H b/src/usr/initservice/baseinitsvc/initservice.H
index 80a4a2d81..a31d108c8 100644
--- a/src/usr/initservice/baseinitsvc/initservice.H
+++ b/src/usr/initservice/baseinitsvc/initservice.H
@@ -26,6 +26,7 @@
/**
* @file initservice.H
*
+ * Base image Initialization Service
* - Manage high-level host boot IPL flow
* - Perform can-continue processing
* - Perform automatic and manual Istep execution
@@ -33,14 +34,6 @@
*
*/
-/**
- * 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
/******************************************************************************/
@@ -53,7 +46,7 @@
#include <initservice/initsvcreasoncodes.H>
#include <initservice/taskargs.H>
-#include "../common/initsvcstructs.H"
+#include <initservice/initsvcstructs.H>
namespace INITSERVICE
{
@@ -71,8 +64,9 @@ namespace INITSERVICE
/******************************************************************************/
/**
- * @class InitService Singleton Class
+ * @class InitService
*
+ * Singleton Class
* This class is launched by _start() (see initservicetaskentry.C),
* which is launched by the kernel (init_main.C).
*
@@ -84,6 +78,7 @@ class InitService
public:
+
friend class InitServiceTest;
/**
@@ -97,18 +92,18 @@ public:
* @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 .
+ * _start() and by extension the kernel,
+ * currently this is always NULL .
+ *
+ * @return nothing
+ *
*/
void init( void *i_args);
- /**
- * @todo InitServiceTest should be able to find protected functions.
- */
- // $$protected:
- /**
- * @brief start a task using the taskname string in the TaskInfo struct.
+ /**
+ * @brief Start a task using the taskname string in the TaskInfo struct.
+ *
* taskname string will be something like "libtargeting.so", which
* is the name of the compiled and linked targetting module.
* The module is expected to have implemented a extern "C"
@@ -122,9 +117,14 @@ public:
*
*
* @param[in] i_ptask pointer to a TaskInfo struct
- * @param[in] io_pargs pointer to a TaskArgs struct, or NULL
+ * @param[in,out] io_pargs pointer to a TaskArgs struct, or NULL
+ * On input, TaskArgs struct will have
+ * command, returncode, and errlog fields
+ * cleared. task can fill in these values
+ * on return.
*
- * @return NULL if success, errorlog handle for failure
+ * @return pointer to errorlog
+ * @retval NULL if success, filled in errorlog handle for failure
*
* @note startTask() can also be used to launch an asynchronous task
* by calling it with i_pargs set to NULL. This will disable
@@ -132,46 +132,54 @@ public:
*
*/
errlHndl_t startTask( const TaskInfo *i_ptask,
- TaskArgs::TaskArgs *i_pargs ) const;
+ TaskArgs::TaskArgs *io_pargs ) const;
/**
- * @brief executeFn
- * Execute an function
+ * @brief Execute an function
*
* @param[in] i_ptask - pointer to an TaskInfo struct
* @param[in,out] i_pargs - pointer to a TaskArgs struct
+ * On input, TaskArgs struct will have
+ * command, returncode, and errlog fields
+ * cleared. Task can fill in these values
+ * on return.
*
- * @return errlHndl_t handle, NULL if success, filled out errorlog
- * if failure
+ * @return pointer to errorlog
+ * @retval NULL if success, filled out errorlog if failure
*/
errlHndl_t executeFn( const TaskInfo *i_ptask,
TaskArgs *i_pargs ) const;
-
/**
- * @brief report Error to the system.
+ * @brief set progress code for task.
+ * This is supposed to make a system call to post the error to
+ * SP and will also write a SCOM reg
+ *
+ * @TODO need progress code categories defined.
*
- * @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
+ * @param[in] i_progresscode - 64-bit progress code.
*
* @return nothing
+ *
*/
- void reportError( errlHndl_t &io_rerrl) const;
+ void setProgressCode( uint64_t i_progresscode ) const;
/**
- * @brief set progress code for task.
+ * @brief dispatch Task depending on what type of task it is,
+ * etc.
*
- * @param[in] i_progresscode - 64-bit progress code.
- *
- * @return nothing
+ * @param[in] i_ptask - pointer to a TaskInfo struct, which should
+ * contain all the info to run the task.
+ * @param[in,out] io_pargs - pointer to a TaskArgs struct. It is
+ * possible that this will not be used at all.
*
+ * @return pointer to errlog
+ * @retval returns NULL, or a pointer to a filled out errorlog
*/
- void setProgressCode( uint64_t i_progresscode ) const;
-
+ errlHndl_t dispatchTask( const TaskInfo *i_ptask,
+ TaskArgs *io_pargs ) const;
protected:
diff --git a/src/usr/initservice/extinitsvc/extinitsvc.C b/src/usr/initservice/extinitsvc/extinitsvc.C
index 886176375..b5ab6b64e 100644
--- a/src/usr/initservice/extinitsvc/extinitsvc.C
+++ b/src/usr/initservice/extinitsvc/extinitsvc.C
@@ -29,20 +29,20 @@
*
*/
-#include <kernel/console.H>
-#include <vfs/vfs.H>
-#include <sys/task.h>
-#include <sys/sync.h>
-#include <sys/misc.h>
-#include <sys/time.h>
-#include <usr/cxxtest/TestSuite.H>
+#include <kernel/console.H>
+#include <vfs/vfs.H>
+#include <sys/task.h>
+#include <sys/sync.h>
+#include <sys/misc.h>
+#include <sys/time.h>
+#include <usr/cxxtest/TestSuite.H>
-#include <trace/interface.H>
-#include <errl/errlentry.H>
-#include <initservice/taskargs.H> // task entry routine
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <initservice/taskargs.H> // task entry routine
-#include "extinitsvc.H"
-#include "extinitsvctasks.H"
+#include "extinitsvc.H"
+#include "extinitsvctasks.H"
namespace INITSERVICE
@@ -50,62 +50,21 @@ namespace INITSERVICE
extern trace_desc_t *g_trac_initsvc;
+
/**
- * @brief _start() - task entry point for this module
- *
- * @parms[in,out] - pointer to TaskArgs struct
- *
+ * @brief set up _start() task entry procedure using the macro in taskargs.H
*/
-extern "C"
-void _start( void *io_pArgs )
-{
- TaskArgs::TaskArgs *pTaskArgs =
- reinterpret_cast<TaskArgs::TaskArgs *>(io_pArgs);
-
- // initialize the extended modules in Hostboot.
- ExtInitSvc::getTheInstance().init( io_pArgs );
-
- if ( pTaskArgs )
- {
- pTaskArgs->waitChildSync();
- }
-
- task_end();
-}
-
-
-
-/******************************************************************************/
-// ExtInitSvc::getTheInstance return the only instance
-/******************************************************************************/
-ExtInitSvc& ExtInitSvc::getTheInstance()
-{
- return Singleton<ExtInitSvc>::instance();
-}
-
-/******************************************************************************/
-// ExtInitSvc::ExtInitSvc constructor
-/******************************************************************************/
-ExtInitSvc::ExtInitSvc()
-{
-
-}
-
-/******************************************************************************/
-// ExtInitSvc::~ExtInitSvc destructor
-/******************************************************************************/
-ExtInitSvc::~ExtInitSvc()
-{
-
-}
+TASK_ENTRY_MACRO( ExtInitSvc::getTheInstance().init );
void ExtInitSvc::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;
+ errlHndl_t l_errl = NULL;
+ uint64_t l_task = 0;
+ const TaskInfo *l_ptask = NULL;
+ TaskArgs::TaskArgs l_args;
+ uint64_t l_childrc = 0;
+
TRACFCOMP( g_trac_initsvc,
"Extended Initialization Service is starting." );
@@ -113,165 +72,207 @@ void ExtInitSvc::init( void *i_ptr )
// ----------------------------------------------------------------
// loop through the task list and start up any tasks necessary
// ----------------------------------------------------------------
- for ( nextTask=0;
- nextTask<MAX_EXT_TASKS;
- nextTask++ )
+ for ( l_task=0;
+ l_task<INITSERVICE::MAX_EXT_TASKS;
+ l_task++ )
{
// make a local copy of the extended image task
- ptask = &(g_exttaskinfolist[nextTask]);
- if ( ptask->taskflags.task_type == END_TASK_LIST )
+ l_ptask = &(g_exttaskinfolist[l_task]);
+ if ( l_ptask->taskflags.task_type == END_TASK_LIST )
{
TRACDCOMP( g_trac_initsvc,
"End of ExtInitSvc task list." );
break;
}
- args.clear(); // clear args for next task
-
- // 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 INIT_TASK:
- TRACDBIN( g_trac_initsvc,
- "task_type==INIT_TASK : ",
- ptask->taskname,
- strlen(ptask->taskname) );
- errl = VFS::module_load( ptask->taskname );
- break;
-
- case START_TASK: // call _init(), _start(), stay resident
- TRACDBIN( g_trac_initsvc,
- "task_type=START_TASK : ",
- ptask->taskname,
- strlen(ptask->taskname) );
- errl = InitService::getTheInstance().startTask( ptask,
- &args );
- break;
-
- case START_FN:
- TRACDCOMP( g_trac_initsvc,
- "task_type==START_FN : %p",
- ptask->taskfn );
- errl = InitService::getTheInstance().executeFn( ptask,
- &args );
- // $$TODO
- break;
- case BARRIER:
- TRACDCOMP( g_trac_initsvc,
- "task_type==BARRIER" );
- // $$TODO
- break;
+ l_args.clear();
- case UNINIT_TASK:
- TRACDBIN( g_trac_initsvc,
- "task_type=UNINIT_TASK : ",
- ptask->taskname,
- strlen(ptask->taskname) );
- errl = VFS::module_unload( ptask->taskname );
- break;
+ // dispatch the task
+ l_errl = InitService::getTheInstance().dispatchTask( l_ptask,
+ &l_args );
- default:
- TRACDCOMP( g_trac_initsvc,
- "Invalid task_type: %d",
- ptask->taskflags.task_type );
- /*@ errorlog tag
- * @errortype ERRL_SEV_CRITICAL_SYS_TERM
- * @moduleid START_EXTINITSVC_ERRL_ID
- * @reasoncode INVALID_TASK_TYPE
- * @userdata1 task_type value
- * @userdata2 0
- *
- * @devdesc Extended Initialization Service found an invalid
- * Task Type in the task list.
- * The module id will identify the task.
- * task_type value will be the invalid type.
- */
- errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
- START_EXTINITSVC_ERRL_ID, // moduleid
- INVALID_TASK_TYPE, // reason Code
- 0, // user1 = tidrc
- 0 );
+ // process errorlogs returned from the task that was launched
+ if ( l_errl )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR: dispatching task, errlog=0x%p",
+ l_errl );
+ // break out of loop with error.
break;
- } // endswitch
+ }
- // report an error
- InitService::getTheInstance().reportError( errl );
+ // make local copies of the values in TaskArgs that are returned from
+ // the child.
+ // this also clears the errorlog from the TaskArgs struct, so
+ // use it or lose it ( see taskargs.H for details ).
+ l_childrc = l_args.getReturnCode();
+ l_errl = l_args.getErrorLog();
- if ( args.getReturnCode() != TASKARGS_UNDEFINED64 )
+ if ( l_errl )
{
TRACFCOMP( g_trac_initsvc,
- ERR_MRK "ExtInitSvc TaskArgs returned 0x%llx, errlog=%p",
- args.getReturnCode(),
- args.getErrorLog()
- );
+ " Child task returned 0x%llx, errlog=0x%p",
+ l_childrc,
+ l_errl );
+ // break out of loop with error
+ break;
}
-
+ else
+ {
+ // Check child results for a valid nonzero return code.
+ // If we have one, and no errorlog, then we create and
+ // post our own errorlog here.
+ if ( ( l_childrc != TASKARGS_UNDEFINED64 )
+ && ( l_childrc != 0 )
+ )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "Child task returned 0x%llx, no errlog",
+ l_childrc );
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid see task list
+ * @reasoncode EXTINITSVC_FAILED_NO_ERRLOG
+ * @userdata1 returncode from task
+ * @userdata2 0
+ *
+ * @devdesc The task returned with an error,
+ * but there was no errorlog returned.
+ *
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ l_ptask->taskflags.module_id,
+ INITSERVICE::EXTINITSVC_FAILED_NO_ERRLOG,
+ l_childrc,
+ 0 );
+
+ // break out of loop with error
+ break;
+ } // end if
+ } // end else
} // endfor
+ // die if we drop out with an error
+ if ( l_errl )
+ {
+ // dropped out of loop with error.
+ // Commit the log first, then stop right here.
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR: extra errorlog found: %p",
+ l_errl );
+ errlCommit( l_errl );
+ assert( 0 );
+ }
TRACFCOMP( g_trac_initsvc,
EXIT_MRK "ExtInitSvc finished.");
+
+
// =====================================================================
// ----- Unit Tests -------------------------------------------------
// =====================================================================
/**
- * @note run all the unit tests after we finish the rest
- * there are 2 images generated in the build:
+ * @note run all of the unit tests after we finish the rest
+ * There are 2 images generated in the build:
* hbicore.bin (HostBoot shippable image)
* hbicore_test.bin (runs all unit tests)
* Only hbicore_test.bin has the libcxxtest.so module, so when
* we execute startTask() below on hbicore.bin, it will return -1,
* no module present. This is OK.
*
+ * @todo can we call call module_load() to see if libcxxtest.so exists?
+ * ask Doug or Patrick
+ *
*/
- // Pass it a set of args so we can wait on the barrier
- // This is a bit wasteful since it is always allocated; we need a
- // system call to check if a module exists.
- TaskArgs::TaskArgs cxxtestargs; // create a new one for cxxtest
- cxxtestargs.clear(); // clear it
-
- TRACFCOMP( g_trac_initsvc,
- ENTER_MRK " "); // leave whitespace in trace
- TRACDBIN( g_trac_initsvc,
- ENTER_MRK "Run Unit Tests (if libcxxtests.so is present): ",
- CXXTEST_TASK.taskname,
- strlen(CXXTEST_TASK.taskname) );
-
- errl = InitService::getTheInstance().startTask( &CXXTEST_TASK,
- &cxxtestargs );
-
- // check the returncode and errorlog in the returned args
- if ( ( cxxtestargs.getReturnCode() != TASKARGS_UNDEFINED64 )
- || ( cxxtestargs.getErrorLog() != NULL )
- )
+ // add a do-while loop so there is only one return at the bottom....
+ do
{
- TRACFCOMP( g_trac_initsvc,
- ERR_MRK "CxxTests returned an error 0x%lx and an errorlog %p",
- cxxtestargs.getReturnCode(),
- cxxtestargs.getErrorLog()
- );
- // report an error
- errlHndl_t childerrl = cxxtestargs.getErrorLog();
- InitService::getTheInstance().reportError( childerrl );
- }
+ // Pass it a set of args so we can wait on the barrier
+ errlHndl_t l_cxxerrl = NULL;
+ TaskArgs::TaskArgs l_cxxtestargs;
+ const TaskInfo *l_pcxxtask = &CXXTEST_TASK;
+ uint64_t l_cxxchildrc = 0;
+ errlHndl_t l_cxxchilderrl = NULL;
+
+ l_cxxtestargs.clear();
+
+ TRACDCOMP( g_trac_initsvc,
+ ENTER_MRK "Run Unit Tests (if libcxxtests.so is present): %s",
+ l_pcxxtask->taskname );
+
+ l_cxxerrl = InitService::getTheInstance().startTask( l_pcxxtask,
+ &l_cxxtestargs );
+
+ // process errorlogs returned from the task that was launched
+ // @TODO if we are running the non-test version of HostBoot, this
+ // will always post an extra errorlog. We need a way to know
+ // if we are running the _test version or not.
+ if ( l_cxxerrl )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "Committing error from cxxtask launch" );
+ errlCommit( l_cxxerrl );
+ break; // ERROR, break out of do-while.
+ }
- TRACDCOMP( g_trac_initsvc,
- EXIT_MRK "Unit Tests finished.");
- TRACFCOMP( g_trac_initsvc,
- EXIT_MRK " "); // leave whitespace in trace
+ // make local copies of the values in TaskArgs that are returned from
+ // the child.
+ // this also clears the errorlog from the TaskArgs struct, so
+ // use it or lose it ( see taskargs.H for details ).
+ l_cxxchildrc = l_cxxtestargs.getReturnCode();
+ l_cxxchilderrl = l_cxxtestargs.getErrorLog();
+
+ if ( l_cxxchilderrl )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ " Child task returned 0x%llx, errlog=0x%p",
+ l_cxxchildrc,
+ l_cxxchilderrl );
+ errlCommit( l_cxxchilderrl );
+ }
+ else
+ {
+ // Check child results for a valid nonzero return code.
+ // If we have one, and no errorlog, then we create and
+ // post our own errorlog here.
+ if ( ( l_cxxchildrc != TASKARGS_UNDEFINED64 )
+ && ( l_cxxchildrc != 0 )
+ )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "Child task returned 0x%llx, no errlog",
+ l_cxxchildrc );
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid see task list
+ * @reasoncode CXXTEST_FAILED_NO_ERRLOG
+ * @userdata1 returncode from istep
+ * @userdata2 0
+ *
+ * @devdesc The unit test dispatcher returned with an
+ * error, but there was no errorlog returned.
+ */
+ l_cxxerrl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ l_pcxxtask->taskflags.module_id,
+ INITSERVICE::CXXTEST_FAILED_NO_ERRLOG,
+ l_cxxchildrc,
+ 0 );
+ errlCommit( l_cxxerrl );
+ } // end if
+ } // end else
+
+ } while(0); // end do-while
- // Shutdown all CPUs
+ // =====================================================================
+ // ----- Shutdown all CPUs -----------------------------------------
+ // =====================================================================
uint64_t l_shutdownStatus = SHUTDOWN_STATUS_GOOD;
if (CxxTest::g_FailedTests)
@@ -286,4 +287,18 @@ void ExtInitSvc::init( void *i_ptr )
}
+ExtInitSvc& ExtInitSvc::getTheInstance()
+{
+ return Singleton<ExtInitSvc>::instance();
+}
+
+
+ExtInitSvc::ExtInitSvc()
+{ }
+
+
+ExtInitSvc::~ExtInitSvc()
+{ }
+
+
} // namespace
diff --git a/src/usr/initservice/extinitsvc/extinitsvc.H b/src/usr/initservice/extinitsvc/extinitsvc.H
index 49733c025..5664a0359 100644
--- a/src/usr/initservice/extinitsvc/extinitsvc.H
+++ b/src/usr/initservice/extinitsvc/extinitsvc.H
@@ -36,15 +36,15 @@
/******************************************************************************/
// Includes
/******************************************************************************/
-#include <stdint.h>
-#include <util/singleton.H>
-#include <sys/vfs.h> // VFS_MODULE_NAME_MAX
+#include <stdint.h>
+#include <util/singleton.H>
+#include <sys/vfs.h> // VFS_MODULE_NAME_MAX
-#include <errl/errlentry.H>
-#include <initservice/taskargs.H>
-#include <initservice/initsvcreasoncodes.H>
+#include <errl/errlentry.H>
+#include <initservice/taskargs.H>
+#include <initservice/initsvcreasoncodes.H>
-#include "../baseinitsvc/initservice.H"
+#include "../baseinitsvc/initservice.H"
namespace INITSERVICE
{
@@ -73,8 +73,9 @@ enum ShutdownStatus
/******************************************************************************/
/**
- * @class ExtInitSvc Singleton Class
+ * @class ExtInitSvc
*
+ * Singleton Class
* This extended image module is launched by InitService
*
*/
@@ -98,7 +99,6 @@ public:
* @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);
diff --git a/src/usr/initservice/initsvctasktest2/makefile b/src/usr/initservice/initsvctasktest2/makefile
new file mode 100644
index 000000000..40d0d6c38
--- /dev/null
+++ b/src/usr/initservice/initsvctasktest2/makefile
@@ -0,0 +1,28 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/initservice/initsvctasktest2/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../../..
+MODULE = initsvctasktest2
+
+OBJS = tasktest2.o
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/initservice/initsvcunittesttask2/tasktest2.C b/src/usr/initservice/initsvctasktest2/tasktest2.C
index fdf830518..fdf830518 100644
--- a/src/usr/initservice/initsvcunittesttask2/tasktest2.C
+++ b/src/usr/initservice/initsvctasktest2/tasktest2.C
diff --git a/src/usr/initservice/initsvcunittesttask2/tasktest2.H b/src/usr/initservice/initsvctasktest2/tasktest2.H
index 9dc1434d0..227013990 100644
--- a/src/usr/initservice/initsvcunittesttask2/tasktest2.H
+++ b/src/usr/initservice/initsvctasktest2/tasktest2.H
@@ -25,7 +25,9 @@
#define __INITSVC_TASK_TEST_2_H
/**
- * @file initsvctasktest2.H
+ * @file tasktest2.H
+ *
+ * dummy file for use in initservice unit tests
*
*/
@@ -51,7 +53,7 @@ namespace INITSERVICE
/******************************************************************************/
/**
- * @class InitSvcTestTask2 Class
+ * @class InitSvcTestTask2
*
* test module launched
*/
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C
index 5dfb5a53e..002cc59d4 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.C
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C
@@ -24,7 +24,9 @@
/**
* @file istepdispatcher.C
*
- * IStep Dispatcher interface. Launched from Extended Initialization Service
+ * IStep Dispatcher code. Launched from Extended Initialization Service
+ *
+ * PNOR Driver and Trace should be available by the time this is launched.
*
*/
@@ -36,12 +38,18 @@
#include <stdio.h>
#include <string.h>
-#include <sys/task.h> // tid_t, task_create, etc
-#include <trace/interface.H> // trace support
-#include <errl/errlentry.H> // errlHndl_t
+#include <sys/task.h> // tid_t, task_create, etc
+#include <sys/time.h> // nanosleep
+#include <trace/interface.H> // trace support
+#include <errl/errlentry.H> // errlHndl_t
+#include <devicefw/userif.H> // targeting
+#include <sys/mmio.h> // mmio_scratch_read()
#include "istepdispatcher.H"
-#include "isteplist.H"
+
+#include "splesscommon.H"
+
+#include <isteps/isteplist.H>
namespace INITSERVICE
@@ -53,102 +61,502 @@ namespace INITSERVICE
extern trace_desc_t *g_trac_initsvc;
/**
- * @brief set up _start() task entry procedure using the macro
+ * @enum
+ * SPLess Task return codes
+ *
+ * task return codes for SPless single step
+ * @note future errors will be passed from task_create() and task_exec()
+ * and should be documented in errno.h
+ *
+ */
+enum {
+ SPLESS_TASKRC_INVALID_ISTEP = -3, // invalid istep or substep
+ SPLESS_TASKRC_LAUNCH_FAIL = -4, // failed to launch the task
+ SPLESS_TASKRC_RETURNED_ERRLOG = -5, // istep returned an errorlog
+ SPLESS_TASKRC_TERMINATED = -6, // terminated the polling loop
+};
+
+/**
+ * @note SPLess PAUSE - These two constants are used in a nanosleep() call
+ * below to sleep between polls of the StatusReg. Typically this will
+ * be about 100 ms - the actual value will be determined empirically.
+ *
+ * @debug simics "feature" - set polling time to 1 sec for demo
+ *
+ */
+
+const uint64_t SINGLESTEP_PAUSE_S = 1;
+const uint64_t SINGLESTEP_PAUSE_NS = 100000000;
+
+
+/**
+ * @brief set up _start() task entry procedure using the macro in taskargs.H
*/
TASK_ENTRY_MACRO( IStepDispatcher::getTheInstance().init );
-IStepDispatcher::IStepDispatcher()
-: iv_istepmodeflag(false),
- iv_nextistep( 0 ),
- iv_cancontinueflag(false)
+const TaskInfo *IStepDispatcher::findTaskInfo( const uint16_t i_IStep,
+ const uint16_t i_SubStep ) const
{
+ const TaskInfo *l_pistep = NULL;
+
+ TRACDCOMP( g_trac_initsvc,
+ "g_isteps[%d].numitems = 0x%x",
+ i_IStep,
+ g_isteps[i_IStep].numitems );
+
+ // apply filters
+ do
+ {
+
+ // check input range - IStep
+ if ( i_IStep >= MAX_ISTEPS )
+ {
+ TRACDCOMP( g_trac_initsvc,
+ "IStep 0x%x out of range.",
+ i_IStep );
+ break; // break out with l_pistep set to NULL
+ }
+
+ // check input range - ISubStep
+ if ( i_SubStep >= g_isteps[i_IStep].numitems )
+ {
+ TRACDCOMP( g_trac_initsvc,
+ "IStep 0x%x Substep 0x%x out of range.",
+ i_IStep,
+ i_SubStep );
+ break; // break out with l_pistep set to NULL
+ }
+
+ // check for end of list.
+ if ( g_isteps[i_IStep].pti[i_SubStep].taskflags.task_type
+ == END_TASK_LIST )
+ {
+ TRACDCOMP( g_trac_initsvc,
+ "IStep 0x%x SubSStep 0x%x task_type==END_TASK_LIST.",
+ i_IStep,
+ i_SubStep );
+ break;
+ }
+
+ // looks good, send it back to the caller
+ TRACDCOMP( g_trac_initsvc,
+ "Found TaskInfo 0x%x 0x%x",
+ i_IStep,
+ i_SubStep );
+ l_pistep = &( g_isteps[i_IStep].pti[i_SubStep] );
+ } while ( 0 );
+
+ return l_pistep;
}
-IStepDispatcher::~IStepDispatcher()
+void IStepDispatcher::init( void * io_ptr )
{
+ TRACFCOMP( g_trac_initsvc,
+ ENTER_MRK "starting IStepDispatcher, io_ptr=%p ",
+ io_ptr );
+
+ if ( getIStepMode() )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "IStep single-step" );
+ // IStep single-step
+ singleStepISteps( io_ptr );
+ }
+ else
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "IStep run all" );
+ // Run all the ISteps sequentially
+ runAllISteps( io_ptr );
+ } // endelse
+
+
+ TRACFCOMP( g_trac_initsvc,
+ EXIT_MRK "IStepDispatcher finished.");
}
-IStepDispatcher& IStepDispatcher::getTheInstance()
+bool IStepDispatcher::getIStepMode( ) const
{
- return Singleton<IStepDispatcher>::instance();
+
+ return iv_istepmodeflag;
+}
+
+
+/**
+ * @todo revisit this when PNOR Driver is implemented
+ *
+ */
+void IStepDispatcher::initIStepMode( )
+{
+ uint64_t l_readData = 0;
+
+ l_readData = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_CONFIG );
+
+ TRACDCOMP( g_trac_initsvc,
+ "SCOM ScratchPad read, Offset 0x%x, Data 0x%llx",
+ MMIO_SCRATCH_IPLSTEP_CONFIG,
+ l_readData );
+
+ // check for IStep Mode signature
+ if ( l_readData == ISTEP_MODE_SIGNATURE )
+ {
+ iv_istepmodeflag = true;
+ }
+ else
+ {
+ iv_istepmodeflag = false;
+ }
+
}
-void IStepDispatcher::init( void * ptr )
+void IStepDispatcher::singleStepISteps( void * io_ptr ) const
{
- errlHndl_t errl = NULL;
- uint64_t nextIStep = 0;
- const TaskInfo *pistep = NULL;
- TaskArgs::TaskArgs args;
+ errlHndl_t l_errl = NULL;
+ TaskArgs::TaskArgs l_args;
+ const TaskInfo *l_pistep = NULL;
+ bool l_gobit = false;
+ uint16_t l_nextIStep = 0;
+ uint16_t l_nextSubstep = 0;
+ uint16_t l_taskStatus = 0;
+ uint16_t l_istepStatus = 0;
+ uint32_t l_progresscode = 0;
+ uint64_t l_isteprc = 0;
+
+ TRACFCOMP( g_trac_initsvc, "Start IStep single-step.\n" );
+
+ // initialize command reg
+ SPLESSCMD::write( false, // go bit is false
+ 0, // istep = 0
+ 0 ); // substep = 0
+
+ SPLESSSTS::write( false, // running bit
+ true, // ready bit
+ 0, // istep running
+ 0, // substep running
+ 0, // task status
+ 0 ); // istep status
+
+ //
+ // @note Start the polling loop.
+ // Currently this has no exit, user should reset the machine and/or
+ // load the payload, which will wipe HostBoot from memory.
+ // Loop forever, unless something Very Bad happens.
+ //
+ while( 1 )
+ {
+ // read command reg, updates l_gobit, l_nextIStep, l_nextSubstep
+ SPLESSCMD::read( l_gobit,
+ l_nextIStep,
+ l_nextSubstep );
- TRACFCOMP( g_trac_initsvc,
- ENTER_MRK "starting IStepDispatcher, ptr=%p. &args=%p",
- ptr, &args );
+ // process any commands
+ if ( l_gobit )
+ {
+ TRACDCOMP( g_trac_initsvc,
+ "gobit turned on, istep=0x%x, substep=0x%x",
+ l_nextIStep,
+ l_nextSubstep );
+
+ // look up istep+substep
+ l_pistep = findTaskInfo( l_nextIStep,
+ l_nextSubstep );
+ if ( l_pistep == NULL )
+ {
+ // no istep TaskInfo returned, update status & drop to end.
+ TRACFCOMP( g_trac_initsvc,
+ "Invalid IStep 0x%x / substep 0x%x, try again.",
+ l_nextIStep,
+ l_nextSubstep );
+ SPLESSSTS::write( false,
+ true,
+ l_nextIStep,
+ l_nextSubstep,
+ SPLESS_TASKRC_INVALID_ISTEP,
+ 0 );
+ }
+ else
+ {
+ // set running bit, fill in istep and substep
+ SPLESSSTS::write( true, // set running bit
+ true, // ready bit
+ l_nextIStep, // running istep
+ l_nextSubstep, // running substep
+ 0, // task status (=0)
+ 0 ); // istep status(=0)
+
+ /**
+ * @todo placeholder - set progress code before starting
+ * This will not be finalized until the progress code driver
+ * is designed and implemented.
+ */
+ l_progresscode = ( (l_nextIStep<<16) | l_nextSubstep );
+ InitService::getTheInstance().setProgressCode( l_progresscode );
+
+ // launch the istep
+ TRACDCOMP( g_trac_initsvc,
+ "execute Istep=0x%x / Substep=0x%x",
+ l_nextIStep,
+ l_nextSubStep );
+
+ // clear status, etc for the next istep
+ l_taskStatus = 0;
+ l_istepStatus = 0;
+ l_args.clear();
+
+ // launch the istep
+ l_errl = InitService::getTheInstance().executeFn( l_pistep,
+ &l_args );
+ // filter errors returning from executeFn
+ if ( l_errl )
+ {
+ // handle an errorlog from the parent. This means the
+ // launch failed, set the task Status to Bad.
+ // no need to process child info, thus the else.
+ // set the taskStatus to LAUNCH_FAIL; this will fall
+ // out the bottom and be written to SPLESS Status
+ l_taskStatus = SPLESS_TASKRC_LAUNCH_FAIL;
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR 0x%x: function launch FAIL",
+ l_taskStatus );
+ errlCommit( l_errl );
+ }
+ else
+ {
+ // process information returned from the IStep.
+ // make local copies of the info; this has a secondary
+ // effect of clearing the errorlog pointer inside
+ // the TaskArgs struct.
+ l_isteprc = l_args.getReturnCode(); // local copy
+ l_errl = l_args.getErrorLog(); // local copy
+
+ TRACDCOMP( g_trac_initsvc,
+ "IStep TaskArgs return 0x%llx, errlog=%p",
+ l_isteprc,
+ l_errl );
+
+ // check for child errorlog
+ if ( l_errl )
+ {
+ // tell the user that the IStep returned an errorlog
+ l_taskStatus = SPLESS_TASKRC_RETURNED_ERRLOG;
+ // go ahead and commit the child errorlog
+ errlCommit( l_errl);
+ }
+
+ // massage the return code from the IStep -
+ // If the istep did not set an errorcode,
+ // then we report 0
+ if ( l_isteprc == TASKARGS_UNDEFINED64 )
+ {
+ l_istepStatus = 0;
+ }
+ else
+ {
+ // truncate IStep return status to 16 bits.
+ l_isteprc &= 0x000000000000ffff;
+ l_istepStatus = static_cast<uint16_t>(l_isteprc);
+ }
+
+ } // end else parent errlog
+
+ // l_taskStatus and l_istepStatus should be set correctly now,
+ // send it to the user.
+ // clear runningbit, report status
+ TRACDCOMP( g_trac_initsvc,
+ "Write IStep Status: istep=0x%x, substep=0x%x, taskstatus=0x%x, istepstatus=0x%x",
+ l_nextIStep,
+ l_nextSubstep,
+ l_taskStatus,
+ l_istepStatus );
+ SPLESSSTS::write( false, // clear running bit
+ true, // ready bit
+ l_nextIStep, // running istep
+ l_nextSubstep, // running substep
+ l_taskStatus, // task status
+ l_istepStatus // istepStatus
+ );
+
+ SPLESSCMD::setgobit( false ); // clear gobit
+ } // end else l_pistep
+ } // endif gobit
+
+ // sleep, and wait for user to give us something else to do.
+ nanosleep( SINGLESTEP_PAUSE_S, SINGLESTEP_PAUSE_NS );
+ } // endwhile
+
+
+ // @note
+ // Fell out of loop, clear sts reg and turn off readybit
+ // Currently this will never be reached. Later there may be
+ // a reason to break out of the loop, if this happens we want to
+ // disable the ready bit so the user knows.
+ SPLESSSTS::write( false,
+ false,
+ 0,
+ 0,
+ SPLESS_TASKRC_TERMINATED,
+ 0
+ );
+
+ // all errorlogs should have been committed in the loop, we should
+ // not have any errorlogs still set.
+ if ( l_errl )
+ {
+ // if we do then commit it and stop here.
+ errlCommit( l_errl );
+ assert(0);
+ }
+
+}
- for ( nextIStep=0;
- nextIStep<INITSERVICE::MAX_ISTEPS;
- nextIStep++ )
+
+void IStepDispatcher::runAllISteps( void * io_ptr ) const
+{
+ errlHndl_t l_errl = NULL;
+ uint16_t l_IStep = 0;
+ uint16_t l_SubStep = 0;
+ const TaskInfo *l_pistep = NULL;
+ TaskArgs::TaskArgs l_args;
+ uint64_t l_progresscode = 0;
+ uint64_t l_isteprc = 0;
+
+ for ( l_IStep=0;
+ l_IStep<INITSERVICE::MAX_ISTEPS;
+ l_IStep++ )
{
- pistep = &(g_isteps[nextIStep]);
- if ( pistep->taskflags.task_type == END_TASK_LIST )
+ for ( l_SubStep=0;
+ l_SubStep < INITSERVICE::MAX_SUBSTEPS;
+ l_SubStep++)
{
TRACDCOMP( g_trac_initsvc,
- "End of IStep list.\n" );
- break;
- }
+ "Find IStep=%d, SubStep=%d",
+ l_IStep,
+ l_SubStep );
+ l_pistep = findTaskInfo( l_IStep,
+ l_SubStep );
+ if ( l_pistep == NULL )
+ {
- args.clear(); // clear the args struct for the next istep
- errl = InitService::getTheInstance().executeFn( pistep,
- &args );
+ TRACDCOMP( g_trac_initsvc,
+ "End of ISubStep list." );
+ break; // break out of inner for loop
+ }
- // handle an errorlog from the parent, if it exists
- InitService::getTheInstance().reportError( errl );
+ // @todo placeholder until progress codes are defined and
+ // progress code driver is implemented.
+ l_progresscode = ( (l_IStep<<16) | l_SubStep );
+ InitService::getTheInstance().setProgressCode( l_progresscode );
- /**
- * @todo call getCanContinueProcedure when we have some ISteps that
- * require them.
- */
+ l_args.clear();
- if ( args.getReturnCode() != TASKARGS_UNDEFINED64 )
- {
TRACFCOMP( g_trac_initsvc,
- ERR_MRK "IStep TaskArgs returned 0x%llx, errlog=%p",
- args.getReturnCode(),
- args.getErrorLog()
- );
+ "Run IStep 0x%x / Substep 0x%x",
+ l_IStep,
+ l_SubStep );
+
+ l_errl = InitService::getTheInstance().executeFn( l_pistep,
+ &l_args );
+ if ( l_errl )
+ {
+ // Handle an errorlog from the parent, if it exists
+ // an error here is probably fatal, it means we can't
+ // launch the task or it doesn't exist. In either
+ // case we should exit the loop.
+ // Can't commit the errorlog here because we are using it
+ // as a flag to exit the loop.
+ break;
+ }
+
+ // make local copies of the status returned from the istep.
+ // note that this also removes the errorlog from the TaskArgs
+ // struct - it is read-once. See taskargs.H for details
+ l_isteprc = l_args.getReturnCode();
+ l_errl = l_args.getErrorLog();
+
+ TRACDCOMP( g_trac_initsvc,
+ "IStep TaskArgs returned 0x%llx, errlog=%p",
+ l_isteprc,
+ l_errl );
+ if ( l_errl )
+ {
+ // if we have an errorlog, break out of the inner loop
+ // and handle it.
+ break;
+ }
+ else
+ {
+ // Check child results for a valid nonzero return code.
+ // If we have one, and no errorlog, then we create an
+ // errorlog here.
+ if ( ( l_isteprc != TASKARGS_UNDEFINED64 )
+ && ( l_isteprc != 0 )
+ )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "istep returned 0x%llx, no errlog",
+ l_isteprc );
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid see task list
+ * @reasoncode ISTEP_FAILED_NO_ERRLOG
+ * @userdata1 returncode from istep
+ * @userdata2 0
+ *
+ * @devdesc The Istep returned with an error,
+ * but there was no errorlog posted
+ * from the IStep.
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ l_pistep->taskflags.module_id,
+ INITSERVICE::ISTEP_FAILED_NO_ERRLOG,
+ l_isteprc,
+ 0 );
+ // drop out of inner loop with errlog set.
+ break;
+ } // end if ( )
+ }
+ } // endfor l_SubStep
+
+ if ( l_errl )
+ {
+ // something left an error log in the inner loop, breakout
+ break;
}
+ } // endfor l_IStep
- // report an error from the child, if it exists.
- reportIStepErrorLog( pistep, args.getErrorLog() );
- } // endfor
+ /**
+ * @todo detect Can-Continue condition here and reset/rerun ISteps.
+ * For now this is pushed to a later sprint.
+ */
- TRACFCOMP( g_trac_initsvc,
- EXIT_MRK "IStepDispatcher finished.");
+ // Post any errorlogs. If one exists, stop here. Otherwise, return
+ // to caller.
+ if ( l_errl )
+ {
+ TRACFCOMP( g_trac_initsvc,
+ "ERROR: istep=0x%x, substep=0x%x, committing errorlog %p",
+ l_IStep,
+ l_SubStep,
+ l_errl );
+ errlCommit( l_errl );
+ assert( 0 );
+ }
}
-/**
- * @note IStep Mode is hardwired to false for now
- *
- * @todo revisit this when PNOR Driver is implemented
- */
-bool IStepDispatcher::getIStepMode( ) const
-{
-
- return false;
-}
-
-
bool IStepDispatcher::getCanContinueProcedure( const TaskInfo &i_failingIStep,
errlHndl_t &i_failingError,
@@ -159,11 +567,21 @@ bool IStepDispatcher::getCanContinueProcedure( const TaskInfo &i_failingIStep,
return false;
}
-void IStepDispatcher::reportIStepErrorLog( const TaskInfo *i_failingIStep,
- errlHndl_t io_errl )
+
+IStepDispatcher& IStepDispatcher::getTheInstance()
+{
+ return Singleton<IStepDispatcher>::instance();
+}
+
+
+IStepDispatcher::IStepDispatcher()
{
+ initIStepMode(); // set up internal flag
- InitService::getTheInstance().reportError( io_errl );
}
+
+IStepDispatcher::~IStepDispatcher()
+{ }
+
} // namespace
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H
index 46f4f87e3..352b0f450 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.H
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H
@@ -21,8 +21,8 @@
//
// IBM_PROLOG_END
-#ifndef __ISTEP_DISPATCHER_H
-#define __ISTEP_DISPATCHER_H
+#ifndef __ISTEPDISPATCHER_ISTEPDISPATCHER_H
+#define __ISTEPDISPATCHER_ISTEPDISPATCHER_H
/**
* @file istepdispatcher.H
*
@@ -34,21 +34,22 @@
/******************************************************************************/
// Includes
/******************************************************************************/
-#include <stdint.h>
-#include <sys/vfs.h> // VFS_MODULE_NAME_MAX
+#include <stdint.h>
+#include <util/singleton.H>
-#include <errl/errlentry.H>
-#include <initservice/taskargs.H>
-#include <initservice/initsvcreasoncodes.H>
+#include <errl/errlentry.H>
+#include <initservice/taskargs.H>
+#include <initservice/initsvcreasoncodes.H>
+#include <initservice/initsvcstructs.H>
-#include "../baseinitsvc/initservice.H"
-#include "../common/initsvcstructs.H"
+#include "../baseinitsvc/initservice.H"
+
+#include "splesscommon.H"
namespace INITSERVICE
{
-
/******************************************************************************/
// Globals/Constants
/******************************************************************************/
@@ -58,7 +59,7 @@ namespace INITSERVICE
/******************************************************************************/
/******************************************************************************/
-// Class
+// Class IStepDispatcher
/******************************************************************************/
/**
@@ -85,6 +86,8 @@ public:
*
* @param[in] i_pargs pointer to any arguments passed in from
* _start().
+ *
+ * @return nothing
*/
void init( void *i_pargs);
@@ -109,51 +112,115 @@ private:
IStepDispatcher(const IStepDispatcher& i_right);
IStepDispatcher& operator=(const IStepDispatcher& i_right);
+
/**
- * @brief getIStepMode
- * call into PNOR and fetch the "IStepMode flag" .
- * This will tell us if we are locked to the SP (IStepMode=ON) or
- * can run all the ISteps available (IStepMode=OFF).
+ * @brief init iv_istepmode flag, called in constructor
+ *
+ * Call into PNOR and fetch the "IStepMode flag" .
+ *
+ * @todo currently this calls into the kernel to get the value of
+ * an SCOM Scratch Reg - this will change when PNOR is finished
+ *
+ * @return nothing
*
- * @return false if IStep Mode is "OFF"
+ */
+ void initIStepMode( );
+
+
+ /**
+ * @brief getIStepMode - return value of IStep Mode
+ *
+ * @return bool - value of iv_istepmodeflag
+ * @retval false if IStep Mode is "OFF"
* true if IStep Mode is "ON"
*/
- bool getIStepMode( ) const;
+ bool getIStepMode( ) const;
+
+
+ /**
+ * @brief Find a TaskInfo struct in the global istep list(s),
+ * addressed by { IStep, SubStep }
+ *
+ *
+ * @param[in] i_IStep - IStepNumber
+ * @param[in] i_SubStep - SubStepNumber
+ *
+ * @return pointer to a TaskInfo struct
+ * @retval pointer to a TaskInfo struct, or NULL
+ *
+ */
+ const TaskInfo *findTaskInfo( uint16_t i_IStep,
+ uint16_t i_SubStep ) const;
+
+
+ /**
+ * @brief singleStepISteps
+ *
+ * Stop and wait for SP to send the next IStep to run. Run that, then
+ * wait for the next one.
+ * This is not expected to return - errors etc are sent to the user to
+ * handle.
+ *
+ * @param[in,out] io_ptr - pointer to any args passed in from
+ * ExtInitSvc. This may be a pointer to an
+ * TaskArgs struct (or something else) which
+ * can be filled out on return
+ *
+ * @return none
+ */
+ void singleStepISteps( void * io_ptr ) const;
+
+
+ /**
+ * @brief runAllISteps
+ *
+ * Run all available ISteps sequentially.
+ * If an IStep gets an error, report it and stop.
+ * Otherwise, return.
+ *
+ * @param[in,out] io_ptr - pointer to a TaskArgs struct on input
+ * command, returncode and errorlog will be
+ * clear on input
+ * one or more may be filled in on return
+ *
+ * @return none
+ */
+ void runAllISteps( void * io_ptr ) const;
/**
* @brief getCanContinueProcedure
* If an IStep fails, this routine will fetch the recovery procedure
+ * This is only used in "normal" mode, it will not be used when IStep Mode
+ * is ON (i.e. it will not be used when single-stepping).
*
- * @param[in] reference to IStepInfo struct for failing Istep
- * @param[in] reference to errorlog for the failure
- * @param[in,out] reference to IStepInfo struct for next IStep to run
+ * @param[in] i_failingIStep - ref to IStepInfo struct for failing
+ * Istep
+ * @param[in] i_failingError - ref to errorlog for the failure
+ * @param[in,out] io_nextIStep - ref to TaskInfo struct for next
+ * IStep to run. struct will be filled
+ * out with info on the next IStep to
+ * run.
*
- * @return false if there is no Can-Continue procedure
+ * @return bool
+ * @retval false if there is no Can-Continue procedure,
* true otherwise
*
+ * @todo 2011-08-22 currently the defs for this procedure are pretty
+ * vague - requirements for Can-Continue behaviour have not been
+ * defined yet.
*/
bool getCanContinueProcedure( const TaskInfo &i_failingIStep,
errlHndl_t &i_failingError,
- TaskInfo &io_nextIstep ) const;
-
- /**
- * @brief reportIStepErrorLog
- * If an IStep returns an error log, commit it.
- *
- * @todo Later there may be some decision about whether to report it
- * based on the IStep.
- */
- void reportIStepErrorLog( const TaskInfo *i_failingIStep,
- errlHndl_t io_errl );
+ TaskInfo &io_nextIStep ) const;
+ // ----- internal vars -----------------------------
bool iv_istepmodeflag;
- uint64_t iv_nextistep;
- bool iv_cancontinueflag;
}; // class IStepDispatcher
+
} // namespace
#endif
diff --git a/src/usr/initservice/istepdispatcher/isteplist.H b/src/usr/initservice/istepdispatcher/isteplist.H
deleted file mode 100644
index 612fde725..000000000
--- a/src/usr/initservice/istepdispatcher/isteplist.H
+++ /dev/null
@@ -1,81 +0,0 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/initservice/istepdispatcher/isteplist.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
-
-#ifndef __ISTEPS_H
-#define __ISTEPS_H
-
-/**
- * @file isteplist.H
- *
- * TaskInfo structs for each task that will run in the extended image.
- */
-
-#include <initservice/initsvcreasoncodes.H>
-#include "istepdispatcher.H"
-#include "../../isteps/isteps.H"
-
-namespace INITSERVICE
-{
-
-const uint64_t MAX_ISTEPS = 25;
-
-const TaskInfo g_isteps[] = {
-
- // ----- ISteps Image ------------------------------------------
-
- /**
- * @brief targeting task, initializes extended module area
- */
- {
- "istep1" , // istep name
- ISTEPS::IStep1, // pointer to fn
- {
- NONE, // task type
- EXT_IMAGE, // Extended Module
- ISTEP_1_ERRL_ID, // module id
- }
- },
-
- // ---------------------------------------------------------------
- // ----- 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
-
-#endif
diff --git a/src/usr/initservice/istepdispatcher/makefile b/src/usr/initservice/istepdispatcher/makefile
index 013c6a8f9..d18adfc4f 100644
--- a/src/usr/initservice/istepdispatcher/makefile
+++ b/src/usr/initservice/istepdispatcher/makefile
@@ -20,10 +20,11 @@
# Origin: 30
#
# IBM_PROLOG_END
+
ROOTPATH = ../../../..
MODULE = istepdisp
-OBJS = istepdispatcher.o
+OBJS = istepdispatcher.o splesscommand.o splessstatus.o
## SUBDIRS = test.d
diff --git a/src/usr/initservice/istepdispatcher/splesscommand.C b/src/usr/initservice/istepdispatcher/splesscommand.C
new file mode 100644
index 000000000..563a4be3a
--- /dev/null
+++ b/src/usr/initservice/istepdispatcher/splesscommand.C
@@ -0,0 +1,113 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/initservice/istepdispatcher/splesscommand.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+
+/**
+ * @file splesscommand.C
+ *
+ * Collection of routines to read/write the spless command reg
+ *
+ */
+
+
+/******************************************************************************/
+// Includes
+/******************************************************************************/
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <errl/errlentry.H> // errlHndl_t
+#include <sys/mmio.h> // mmio_scratch_read/write
+
+#include "splesscommon.H"
+
+
+/******************************************************************************/
+// Globals/Constants
+/******************************************************************************/
+
+/******************************************************************************/
+// Typedef/Enumerations
+/******************************************************************************/
+
+namespace SPLESSCMD
+{
+
+
+void read( bool &io_rgobit,
+ uint16_t &io_ristep,
+ uint16_t &io_rsubstep )
+{
+ InternalCommand l_cmd;
+
+ l_cmd.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_COMMAND);
+
+ io_rgobit = l_cmd.f.gobit;
+ io_ristep = l_cmd.f.istep;
+ io_rsubstep = l_cmd.f.substep;
+
+}
+
+
+void write( const bool i_gobit,
+ const uint16_t i_istep,
+ const uint16_t i_substep )
+{
+ InternalCommand l_cmd;
+
+ // copy into union
+ l_cmd.f.gobit = i_gobit;
+ l_cmd.f.istep = i_istep;
+ l_cmd.f.substep = i_substep;
+
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, l_cmd.val64 );
+
+}
+
+
+void getgobit( bool &o_rgobit )
+{
+ uint16_t l_istep = 0;
+ uint16_t l_substep = 0;
+
+ // re-use above call...
+ read( o_rgobit,
+ l_istep,
+ l_substep );
+
+}
+
+
+void setgobit( const bool i_gobit )
+{
+ InternalCommand l_cmd;
+
+ l_cmd.val64 = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_COMMAND);
+
+ l_cmd.f.gobit = i_gobit;
+
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, l_cmd.val64 );
+
+}
+
+} // namespace
diff --git a/src/usr/initservice/istepdispatcher/splesscommon.H b/src/usr/initservice/istepdispatcher/splesscommon.H
new file mode 100644
index 000000000..113d712fd
--- /dev/null
+++ b/src/usr/initservice/istepdispatcher/splesscommon.H
@@ -0,0 +1,269 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/initservice/istepdispatcher/splesscommon.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+
+#ifndef __ISTEPDISP_SPLESS_COMMON_H
+#define __ISTEPDISP_SPLESS_COMMON_H
+/**
+ * @file splesscommon.H
+ *
+ * Prototypes for routines to access SPLESS Command and
+ * and SPLESS Status interfaces
+ *
+ */
+
+/******************************************************************************/
+// Includes
+/******************************************************************************/
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+/******************************************************************************/
+// Globals/Constants
+/******************************************************************************/
+const uint64_t ISTEP_MODE_SIGNATURE = 0x4057b0074057b007;
+
+/******************************************************************************/
+// SPLESS Command Prototypes
+/******************************************************************************/
+
+/**
+ * @namespace SPLESSCMD
+ *
+ * Contains functions to manipulate the SPLESS Command Register
+ * @todo overload these later to get command and seq fields
+ *
+ */
+namespace SPLESSCMD
+{
+
+/**
+ * @union InternalCommand
+ *
+ * define the fields within the 64-bit Command Register
+ *
+
+ * Bit numbers are in ppc notation, where bit 0 is the most significant bit.
+ * Go Bit : bit 0 (ppc notation, msbit)
+ * - set to 1 by the user to start the IStep
+ * - cleared to 0 by HostBoot
+ * Reserved: bit 1: always 0
+ * Sequence #: bits 2-7
+ * Command Number: bits 8:15 - always 0 (for now)
+ * Reserved: bits 16:31
+ * Reserved: bits 32:39 - always 0
+ * IStep Number: bits 40:47
+ * Substep Number: bits 48:63gobit:
+ *
+ */
+union InternalCommand
+{
+ uint64_t val64;
+ struct
+ {
+ bool gobit:1;
+ uint8_t reserved0:1;
+ uint8_t seqnum:6;
+ uint8_t cmdnum;
+
+ uint16_t reserved2;
+
+ uint16_t reserved3:2;
+ uint16_t istep:14;
+
+ uint16_t substep;
+ } f PACKED;
+
+ // init struct to 0
+ InternalCommand() : val64(0) {};
+} ;
+
+
+/**
+ * @brief Read the command register and return the necessary fields.
+ *
+ * @param[in,out] io_rgobit - ref to a gobit var that will be filled in
+ * on return
+ * @param[in,out] io_ristep - ref to a istep var that will be filled in
+ * on return
+ * @param[in,out] io_rsubstep - ref to a substep var that will be filled
+ * in on return
+ *
+ * @return pointer to errorlog
+ * @retval NULL if success, filled-in errorlog if failure
+ *
+ */
+void read( bool &io_rgobit,
+ uint16_t &io_ristep,
+ uint16_t &io_rsubstep );
+
+
+/**
+ * @brief Write all the necessary fields to the command reg.
+ *
+ * Normally the user writes the command reg; this is only used to
+ * init the command reg at the beginning
+ *
+ * @param[in] i_gobit - gobit value to write
+ * @param[in] i_istep - istep value to write
+ * @param[in] i_substep - substep value to write
+ *
+ * @return errorlog pointer
+ * @retval NULL if success, filled-in errorlog if failure
+ *
+ */
+void write( const bool i_gobit,
+ const uint16_t i_istep,
+ const uint16_t i_substep );
+
+
+/**
+ * @brief Read the gobit from the command register
+ *
+ * @param o_rgobit - ref to a gobit var that will be filled in
+ * on return.
+ *
+ * @return errorlog pointer
+ * @retval NULL if success, filled-in errorlog on failure
+ */
+void getgobit( bool &o_rgobit );
+
+
+/**
+ * @brief Write the gobit to the command register
+ *
+ * @param i_gobit - gobit value to be written
+ *
+ * @return pointer to errlog
+ * @retval NULL if success, filled-in errorlog on failure
+ */
+void setgobit( const bool i_gobit ) ;
+
+} // namespace
+
+
+/******************************************************************************/
+// SPLESS Status Prototypes
+/******************************************************************************/
+
+/**
+ * @namespace SPLESSSTS
+ *
+ * Contains functions to manipulate the SPLESS Status Register
+ * @todo overload these to get seq # later
+ *
+ */
+namespace SPLESSSTS
+{
+
+/**
+ * @union InternalStatus
+ *
+ * define the fields within the 64-bit status register
+ * Running bit, bit 0 (ppc notation, msbit):
+ * = 1 when IStep is running
+ * = 0 when IStep is finished
+ * Ready bit, bit 1:
+ * = 1 when IStep Dispatcher is ready to run individual ISteps
+ * = 0 if IStep Dispatcher is not ready:
+ * - System has not loaded the IStep Dispatcher yet
+ * - IStep Mode Flag = 0
+ * Sequence # : bits 2-7 - echoes the sequence number in the associated
+ * command frame.
+ * IStep Running, bits 8:15 - the IStep number that is currently running.
+ * Sub-step Running, bits 16:31 - the substep that is currently running.
+ * Task Status, bits 32:47 - the status that IStep Dispatcher returns when
+ * trying to run the task. For example:
+ * -3 IStep number is invalid
+ * -1, -2 (return code from kernel) IStep could not be launched as a
+ * task or as a function within a task
+ * IStep Status, bits 48:63 - status returned from the IStep.
+ *
+ */
+union InternalStatus {
+ uint64_t val64;
+ struct {
+ bool runningbit:1; // |
+ bool readybit:1; // |
+ uint8_t seqnum:6; // |
+ uint8_t istep; // | 16 bits
+ uint16_t substep; // 16 bits
+ uint16_t taskStatus; // 16 bits
+ uint16_t istepStatus; // 16 bits
+ } f PACKED;
+
+ // init struct to 0
+ InternalStatus() : val64(0) {};
+} ;
+
+
+
+/**
+ * @brief Read the SPLess Status SCOM Reg and return all its fields
+ *
+ * @param[in,out] io_rrunningbit - ref to runningbit var, to be
+ * filled in on return
+ * @param[in,out] io_rreadybit - ref to readybit var, to be filled in
+ * on return
+ * @param[in,out] io_ristep - ref to istep var, to be filled in on
+ * return
+ * @param[in,out] io_rsubstep - ref to substep var, to be filled in
+ * on return
+ * @param[in,out] io_rtaskStatus - ref to taskStatus var, to be filled
+ * in on return
+ * @param[in,out] io_ristepStatus - ref to istepStatus var, to be filled
+ * in on return
+ *
+ * @return none.
+ */
+void read( bool &io_rrunningbit,
+ bool &io_rreadybit,
+ uint16_t &io_ristep,
+ uint16_t &io_rsubstep,
+ uint16_t &io_rtaskStatus,
+ uint16_t &io_ristepStatus );
+
+/**
+ * @brief write
+ *
+ * Read the SPLess Status SCOM Reg and return all its fields
+ *
+ * @param[in] i_runningbit - runningbit val to write
+ * @param[in] i_readybit - readybit val to write
+ * @param[in] i_istep - istep val to write
+ * @param[in] i_substep - substep val to write
+ * @param[in] i_taskStatus - taskStatus val to write
+ * @param[in] i_istepStatus - istepStatus val to write
+ *
+ * @return none
+ */
+void write( const bool i_runningbit,
+ const bool i_readybit,
+ const uint16_t i_istep,
+ const uint16_t i_substep,
+ const uint16_t i_taskStatus,
+ const uint16_t i_istepStatus );
+
+} // namespace
+
+#endif
diff --git a/src/usr/initservice/istepdispatcher/splessstatus.C b/src/usr/initservice/istepdispatcher/splessstatus.C
new file mode 100644
index 000000000..30818778c
--- /dev/null
+++ b/src/usr/initservice/istepdispatcher/splessstatus.C
@@ -0,0 +1,93 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/initservice/istepdispatcher/splessstatus.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/**
+ * @file splessstatus.C
+ *
+ * Routines to read and write spless status reg
+ *
+ */
+
+/******************************************************************************/
+// Includes
+/******************************************************************************/
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <errl/errlentry.H> // errlHndl_t
+#include <sys/mmio.h> // mmio_scratch_read/write
+
+#include "splesscommon.H"
+
+/******************************************************************************/
+// Globals/Constants
+/******************************************************************************/
+
+/******************************************************************************/
+// Typedef/Enumerations
+/******************************************************************************/
+
+
+void SPLESSSTS::read( bool &io_rrunningbit,
+ bool &io_rreadybit,
+ uint16_t &io_ristep,
+ uint16_t &io_rsubstep,
+ uint16_t &io_rtaskStatus,
+ uint16_t &io_ristepStatus )
+{
+ InternalStatus l_sts;
+
+ l_sts.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_STATUS);
+
+ // read was good
+ io_rrunningbit = l_sts.f.runningbit;
+ io_rreadybit = l_sts.f.readybit;
+ io_ristep = l_sts.f.istep;
+ io_rsubstep = l_sts.f.substep;
+ io_rtaskStatus = l_sts.f.taskStatus;
+ io_ristepStatus = l_sts.f.istepStatus;
+
+}
+
+
+void SPLESSSTS::write( const bool i_runningbit,
+ const bool i_readybit,
+ const uint16_t i_istep,
+ const uint16_t i_substep,
+ const uint16_t i_taskStatus,
+ const uint16_t i_istepStatus )
+{
+ InternalStatus l_sts;
+
+ // copy in all the values
+ l_sts.f.runningbit = i_runningbit;
+ l_sts.f.readybit = i_readybit;
+ l_sts.f.istep = i_istep;
+ l_sts.f.substep = i_substep;
+ l_sts.f.taskStatus = i_taskStatus;
+ l_sts.f.istepStatus = i_istepStatus;
+
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_STATUS, l_sts.val64 );
+
+}
+
diff --git a/src/usr/initservice/makefile b/src/usr/initservice/makefile
index 5c5b2a415..28240f386 100644
--- a/src/usr/initservice/makefile
+++ b/src/usr/initservice/makefile
@@ -20,14 +20,15 @@
# Origin: 30
#
# IBM_PROLOG_END
+
ROOTPATH = ../../..
# MODULE =
# OBJS =
-# NOTE: initsvcunittesttask2 is a dummy module that is executed by
+# NOTE: initsvctasktest2 is a dummy module that is executed by
# unit test 2 in the test directory. Please do not rename.
SUBDIRS = baseinitsvc.d extinitsvc.d taskargs.d istepdispatcher.d \
- test.d initsvcunittesttask2.d
+ test.d initsvctasktest2.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/initservice/taskargs/taskargs.C b/src/usr/initservice/taskargs/taskargs.C
index 6d95c9031..ecb4cd88c 100644
--- a/src/usr/initservice/taskargs/taskargs.C
+++ b/src/usr/initservice/taskargs/taskargs.C
@@ -125,8 +125,12 @@ void TaskArgs::postErrorLog( errlHndl_t i_errl )
errlHndl_t TaskArgs::getErrorLog( )
{
+ errlHndl_t l_errl = iv_errl;
- return iv_errl;
+ // null out iv_errl after returning it to someone.
+ iv_errl = NULL;
+
+ return l_errl;
}
@@ -164,6 +168,7 @@ TaskArgs::~TaskArgs()
{
clear();
barrier_destroy( &iv_sync_barrier );
+ // add an assert here to check if there is still an errorlog pending?
}
}; // namespace
diff --git a/src/usr/initservice/test/initservicetest.H b/src/usr/initservice/test/initservicetest.H
index 4c62f3e6d..6a32d73fd 100644
--- a/src/usr/initservice/test/initservicetest.H
+++ b/src/usr/initservice/test/initservicetest.H
@@ -24,17 +24,14 @@
/**
* @file initservicetest.H
*
- * Private functions for VFS2 phase.
+ * Unit tests for initservice module
+ *
*/
#ifndef __TEST_INIT_SERVICETEST_H
#define __TEST_INIT_SERVICETEST_H
-/**
- * @file initservicetest.H
- *
- * @brief Unit tests for initservice module
- */
+
#include <cxxtest/TestSuite.H>
@@ -62,7 +59,7 @@ const INITSERVICE::TaskInfo TASK_TEST1 = {
*
*/
const INITSERVICE::TaskInfo TASK_TEST2 = {
- "libtasktest2.so" , // taskname
+ "libinitsvctasktest2.so" , // taskname
NULL, // ptr to fn
{
INITSERVICE::START_TASK, // startflag=true, try to start
@@ -107,25 +104,27 @@ public:
void testInitServiceStartTask1(void)
{
- errlHndl_t errl = NULL;
+ errlHndl_t l_errl = NULL;
/**
* @todo use a separate instance here, not the singleton
*/
- INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance();
+ INITSERVICE::InitService &l_is
+ = INITSERVICE::InitService::getTheInstance();
- TS_TRACE( "=====>Attempt to run a nonexistent task, expect an ERROR.");
- errl = l_is.startTask( &TASK_TEST1, // task struct
- NULL ); // args
- if ( errl )
+ TS_TRACE( "=====>Run a nonexistent task, expect an ERROR.");
+ l_errl = l_is.startTask( &TASK_TEST1,
+ NULL );
+ if ( l_errl )
{
TS_TRACE( "SUCCESS: startTask returned an errorlog.\n");
+ // clean up
+ errlCommit( l_errl );
}
else
{
TS_FAIL( "ERROR: no error log was returned.\n");
}
-
return;
}
@@ -136,25 +135,26 @@ public:
*/
void testInitServiceStartTask2(void)
{
- errlHndl_t errl = NULL;
+ errlHndl_t l_errl = NULL;
/**
* @todo use a separate instance here, not the singleton
*/
- INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance();
+ INITSERVICE::InitService &l_is
+ = INITSERVICE::InitService::getTheInstance();
- TS_TRACE( "=====>Attempt to run a task with a _start() function, expect SUCCESS.");
- errl = l_is.startTask( &TASK_TEST2, // task struct
- NULL ); // args
- if ( errl )
+ TS_TRACE( "=====>Run a task with _start() function, expect SUCCESS.");
+ l_errl = l_is.startTask( &TASK_TEST2,
+ NULL );
+ if ( l_errl )
{
TS_FAIL( "ERROR: StartTask returned an error log.\n");
+ errlCommit( l_errl );
}
else
{
TS_TRACE( "SUCCESS: startTask returned OK.\n");
}
-
return;
}
@@ -166,18 +166,20 @@ public:
*/
void testInitServiceStartTask3(void)
{
- errlHndl_t errl = NULL;
+ errlHndl_t l_errl = NULL;
/**
* @todo use a separate instance here, not the singleton
*/
- INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance();
+ INITSERVICE::InitService &l_is
+ = INITSERVICE::InitService::getTheInstance();
- TS_TRACE( "====>Attempt to run a task with NO _start() function, expect an ERROR.");
- errl = l_is.startTask( &TASK_TEST3, // task struct
- NULL ); // args
- if ( errl )
+ TS_TRACE( "====>Run a task with NO _start() function, expect an ERROR.");
+ l_errl = l_is.startTask( &TASK_TEST3,
+ NULL );
+ if ( l_errl )
{
TS_TRACE( "SUCCESS: startTask returned an error log.\n");
+ errlCommit( l_errl );
}
else
{
@@ -187,73 +189,6 @@ public:
return;
}
- /**
- * @brief testInitServicereportError1
- * This will call reportError with a NULL errlHndl_t . It should handle it
- * OK (reportError() will print an error message to trace)
- */
- void testInitServicereportError1(void)
- {
- errlHndl_t errl = NULL;
- /**
- * @todo use a separate instance here, not the singleton
- */
- INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance();
-
- TS_TRACE( "====> call reportError with NULL handle, should handle it OK\n ");
- l_is.reportError( errl );
-
- // reportError() might crash, if it returns, just make sure it didn't modify
- // the input pointer
- if ( errl != NULL)
- {
- TS_FAIL( "ERROR: expected the NULL errlHndl_t to stay NULL\n");
- }
- else
- {
- TS_TRACE( "SUCCESS: reportError returned OK.");
- }
-
- return;
- }
-
- /**
- * @brief testInitServicereportError1
- * This will call reportError with a good errorlog.
- * on return, it should be NULLED out
- * @todo can we check with the errorlogging facility to see if it got
- * posted??
- */
- void testInitServicereportError2(void)
- {
- errlHndl_t errl = NULL;
- /**
- * @todo use a separate instance here, not the singleton
- */
- INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance();
-
- errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_INFORMATIONAL,
- INITSERVICE::INIT_SVC_TEST5_ERRL_ID,
- INITSERVICE::START_TASK_FAILED,
- 0,
- 0
- );
-
- TS_TRACE( "====> call reportError with good error handle, should commit and then delete ");
- l_is.reportError( errl );
- if ( errl !=NULL )
- {
- TS_FAIL( "ERROR: reportError did not delete the errlHndl_t handle!\n" );
- }
- else
- {
- TS_TRACE( "SUCCESS: reportError returned OK.");
- }
-
- return;
- }
-
}; // class InitServiceTest
diff --git a/src/usr/initservice/test/splesstest.H b/src/usr/initservice/test/splesstest.H
new file mode 100644
index 000000000..f89d2d4a8
--- /dev/null
+++ b/src/usr/initservice/test/splesstest.H
@@ -0,0 +1,396 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/initservice/test/splesstest.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+
+#ifndef __TEST_SPLESS_H
+#define __TEST_SPLESS_H
+
+/**
+ * @file splesstest.H
+ *
+ * Test SP-less interface to
+ */
+
+#include <sys/time.h> // nanosleep
+#include <sys/mmio.h> // mmio_scratch_write/read
+
+#include <cxxtest/TestSuite.H>
+#include <devicefw/userif.H>
+
+#include "../istepdispatcher/istepdispatcher.H"
+
+#include "../istepdispatcher/splesscommon.H"
+
+using namespace INITSERVICE; // SPLessCommand and SPLessStatus
+using namespace TARGETING; // getIStepMode()
+
+/**
+ * @class SPLessTest
+ *
+ * attempts to run ISteps using the SP-Less interface
+ *
+ */
+class SPLessTest: public CxxTest::TestSuite
+{
+
+public:
+ /**
+ * @brief testSPLessTest1
+ *
+ * - test that IStep Mode is enabled
+ * - read SPLess status:
+ * - ready bit should be on
+ * - running bit shold be off
+ * - status should be 0
+ *
+ */
+ void testSPLessTest1( )
+ {
+ bool l_runningbit = false;
+ bool l_readybit = false;
+ uint16_t l_IStep = 0;
+ uint16_t l_Substep = 0;
+ uint16_t l_taskStatus = 0;
+ uint16_t l_istepStatus = 0;
+
+ if ( ! checkIStepMode() )
+ {
+ // IStepMode is off, don't bother running this
+ TS_TRACE("IStepMode disabled, can't run unit test" );
+ return;
+ }
+
+ SPLESSSTS::read( l_runningbit,
+ l_readybit,
+ l_IStep,
+ l_Substep,
+ l_taskStatus,
+ l_istepStatus );
+ if ( l_readybit == false )
+ {
+ TS_FAIL( "Ready bit should be on");
+ }
+
+ if ( l_runningbit == true )
+ {
+ TS_FAIL( "Running bit should be off");
+ }
+
+ if ( ( l_IStep != 0 ) ||
+ ( l_Substep != 0 )
+
+ )
+ {
+ TS_FAIL( "IStep and SubStep fields should be 0");
+ }
+
+
+ if ( ( l_taskStatus != 0 ) ||
+ ( l_istepStatus != 0 )
+
+ )
+ {
+ TS_FAIL( "Status fields should be 0");
+ }
+
+ }
+
+ /**
+ * @brief testSPLessTest2
+ *
+ * - Execute IStep 0, substep 0
+ *
+ * - this should succeed.
+ *
+ */
+ void testSPLessTest2( )
+ {
+ uint16_t l_taskStatus = 0;
+ uint16_t l_istepStatus = 0;
+ bool l_pass = false;
+
+ if ( ! checkIStepMode() )
+ {
+ // IStepMode is off, don't bother running this
+ TS_TRACE("IStepMode disabled, can't run unit test" );
+ return;
+ }
+
+ if ( ! checkReadyBit() )
+ {
+ TS_FAIL( "readybit is not enabled");
+ return;
+ }
+
+ //
+ l_pass = runIStep( 0, // IStep = 0
+ 0, // Substep=0
+ l_taskStatus, // task status
+ l_istepStatus // istep status
+ );
+
+ if ( !l_pass )
+ {
+ TS_FAIL( "FAILED to run IStep");
+ // dump errorlog?
+ }
+
+ if ( l_taskStatus != 0 )
+ {
+ TS_FAIL( "bad status: taskStatus expected 0, got %d",
+ l_taskStatus);
+ }
+
+
+ if ( l_istepStatus != 0 )
+ {
+ TS_FAIL( "bad status: istepStatus expected 0, got %d",
+ l_istepStatus);
+ }
+
+
+ }
+
+
+ /**
+ * @brief testSPLessTest3
+ *
+ * - Execute Invalid IStep
+ *
+ */
+ void testSPLessTest3( )
+ {
+ uint16_t l_taskStatus = 0;
+ uint16_t l_istepStatus = 0;
+ bool l_pass = false;
+
+ if ( ! checkIStepMode() )
+ {
+ // IStepMode is off, don't bother running this
+ TS_TRACE("IStepMode disabled, can't run unit test" );
+ return;
+ }
+
+
+ if ( ! checkReadyBit() )
+ {
+ TS_FAIL( "readybit is not enabled");
+ return;
+ }
+
+ // run invalid istep/substep
+ l_pass = runIStep( 55, // IStep = 55
+ 55, // Substep=55
+ l_taskStatus, // return task status
+ l_istepStatus // return istep status
+ );
+
+ if ( !l_pass )
+ {
+ TS_FAIL( "FAILED to run IStep");
+ // dump errorlog?
+ }
+
+ if ( (l_taskStatus != 0 ) ||
+ (l_istepStatus != 0 )
+ )
+ {
+ TS_FAIL( "bad status: taskStatus expected 0, got %d",
+ l_taskStatus);
+ }
+
+
+ if (
+ (l_istepStatus != 0 )
+ )
+ {
+ TS_FAIL( "bad status: istepStatus expected 0, got %d",
+ l_istepStatus);
+ }
+
+ }
+
+
+ /**
+ * @brief testSPLessTest4
+ *
+ * - Execute Several ISteps
+ *
+ *
+ *
+ */
+ void testSPLessTest4( )
+ {
+
+ }
+
+
+private:
+
+ /**
+ * @brief checkIStepMode
+ *
+ * check that IStepMode is enabled, by reading the IStepModeSCOM for
+ * a signature value.
+ *
+ * @return bool
+ * @retval true if IStepMode is on, false otherwise
+ */
+ bool checkIStepMode()
+ {
+ uint64_t l_readData = 0;
+ bool l_flag = false;
+
+ l_readData = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_CONFIG );
+
+ // check for IStep Mode signature, this is temporary
+ if ( l_readData == ISTEP_MODE_SIGNATURE )
+ {
+ l_flag = true;
+ }
+ else
+ {
+ l_flag = false;
+ }
+
+
+ return l_flag;
+ }
+
+ /**
+ * @brief checkReadyBit
+ *
+ * check if the ready bit is on before starting any ISteps.
+ *
+ * This calls TS_FAIL and returns false if it cannot read the SCOM.
+ *
+ * @return bool
+ * @retval true if readybit is on, false otherwise
+ */
+ bool checkReadyBit( )
+ {
+ bool l_runningbit = false;
+ bool l_readybit = false;
+ uint16_t l_IStep = 0;
+ uint16_t l_Substep = 0;
+ uint16_t l_taskStatus = 0;
+ uint16_t l_istepStatus = 0;
+
+ SPLESSSTS::read( l_runningbit,
+ l_readybit,
+ l_IStep,
+ l_Substep,
+ l_taskStatus,
+ l_istepStatus );
+
+ return l_readybit;
+ }
+
+
+ /**
+ * @brief runIStep
+ *
+ * run one IStep /substep and return results.
+ *
+ * Assumes that readybit is on (i.e. you should have checked it
+ * before calling this)
+ *
+ * calls TS_FAIL and returns false if cannot read the SCOM regs
+ * calls TS_FAIL and returns false if times out waiting for runningbit
+ * calls TS_FAIL and returns false if ready bit goes off
+ *
+ * @param[in] i_IStep - IStep to run
+ * @param[in] i_Substep - Substep to run
+ * @param[out] o_taskStatus - taskStatus returned from IStep/substep
+ * @param[out] o_istepStatus - istepStatus retured from IStep/substep
+ *
+ * @return bool
+ * @retval true if IStep runs OK, false otherwise
+ */
+ bool runIStep( uint16_t i_IStep,
+ uint16_t i_Substep,
+ uint16_t &o_taskStatus,
+ uint16_t &o_istepStatus
+ )
+ {
+ bool l_runningbit = false;
+ bool l_readybit = false;
+ uint16_t l_IStep = 0;
+ uint16_t l_Substep = 0;
+ bool l_pass = false;
+
+ // init outputs
+
+ l_IStep = 0;
+ l_Substep = 0;
+ o_taskStatus = 0;
+ o_istepStatus = 0;
+
+ l_pass = true; // assume things will be OK
+
+
+ // Write gobit, istep, substep
+ //
+ SPLESSCMD::write( true, // gobit
+ i_IStep, // istep
+ i_Substep // substep
+ );
+ // loop up waiting for test to finish
+ int timeoutctr = 10;
+ do {
+ // give it 500 millseconds to finish
+ nanosleep( 0, 500000000 );
+
+ SPLESSSTS::read( l_runningbit,
+ l_readybit,
+ l_IStep,
+ l_Substep,
+ o_taskStatus,
+ o_istepStatus
+ );
+
+ // timeout probably means the singlestep loop died.
+ // do a TS_FAIL
+ if ( --timeoutctr <= 0 )
+ {
+ TS_FAIL( "TIMEOUT waiting for runningbit to turn off");
+ l_pass = false;
+ }
+
+ } while (l_runningbit);
+
+ // check readybit - if it's off it means the singlestep loop died.
+ // do a TS_FAIL
+ if ( ! l_readybit )
+ {
+ TS_FAIL( "FAIL: readybit is off");
+ l_pass = false;
+ }
+
+ return l_pass;
+ }
+
+}; // class
+
+
+#endif
+
diff --git a/src/usr/isteps/istep1.C b/src/usr/isteps/istep1.C
index 9d1e311b1..97bf3ab73 100644
--- a/src/usr/isteps/istep1.C
+++ b/src/usr/isteps/istep1.C
@@ -20,10 +20,13 @@
// Origin: 30
//
// IBM_PROLOG_END
+
/**
- * @file isteps.C
+ * @file istep1.C
+ *
+ * test ISTep file
*
- * Collection of IStep modules
+ * @note, you must update isteps.h if you change this one
*
*/
@@ -43,7 +46,8 @@
#include <initservice/taskargs.H> // task args
// pull in stuff to run HW procedure - from Andrew's hwpf testcase 2
-// NOTE: there are extra include paths in isteps/makefile to find the fapi includes:
+// NOTE: there are extra include paths in isteps/makefile to find the fapi
+// includes:
// EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer
// EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi
// EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat
@@ -66,7 +70,7 @@ trace_desc_t *g_trac_istep1 = NULL;
TRAC_INIT(&g_trac_istep1, "ISTEP1", 4096);
extern "C"
-void IStep1( void * io_pArgs )
+void IStep0sub0( void * io_pArgs )
{
INITSERVICE::TaskArgs::TaskArgs *pTaskArgs =
reinterpret_cast<INITSERVICE::TaskArgs::TaskArgs *>(io_pArgs);
@@ -77,7 +81,7 @@ void IStep1( void * io_pArgs )
// print out stuff from taskargs
TRACFCOMP( g_trac_istep1,
- "starting IStep 1, command=0x%llx, returncode=0x%llx",
+ ENTER_MRK "starting IStep0sub0, command=0x%llx, returncode=0x%llx",
command, returncode );
// ----- start ISTEP --------------------------------------------------
@@ -89,7 +93,7 @@ void IStep1( void * io_pArgs )
if (l_err)
{
TRACFCOMP( g_trac_istep1,
- "IStep1 failed, posting error code 1");
+ "Failed, posting error code 1");
// Commit/delete error
errlCommit(l_err);
@@ -99,7 +103,7 @@ void IStep1( void * io_pArgs )
else
{
TRACFCOMP( g_trac_istep1,
- "ISTep1 finished successfully.");
+ "Finished successfully.");
pTaskArgs->postReturnCode( 0 );
}
@@ -107,8 +111,9 @@ void IStep1( void * io_pArgs )
// ----- end ISTEP ------------------------------------------------------
TRACFCOMP( g_trac_istep1,
- EXIT_MRK "ending IStep 1");
+ EXIT_MRK "ending IStep0sub0");
+ // if non-null, wait for the barrier, otherwise just return
if ( pTaskArgs )
{
pTaskArgs->waitChildSync();
@@ -117,5 +122,64 @@ void IStep1( void * io_pArgs )
task_end();
}
+extern "C"
+void IStep0sub1( void * io_pArgs )
+{
+ INITSERVICE::TaskArgs::TaskArgs *pTaskArgs =
+ reinterpret_cast<INITSERVICE::TaskArgs::TaskArgs *>(io_pArgs);
+ uint64_t command = pTaskArgs->getCommand();
+ uint64_t returncode = pTaskArgs->getReturnCode();
+
+
+ // print out stuff from taskargs
+ TRACFCOMP( g_trac_istep1,
+ ENTER_MRK "starting IStep0sub1, command=0x%llx, returncode=0x%llx",
+ command, returncode );
+ // ----- start ISTEP --------------------------------------------------
+
+ pTaskArgs->postReturnCode( 0 );
+
+ // ----- end ISTEP ------------------------------------------------------
+ TRACFCOMP( g_trac_istep1,
+ EXIT_MRK "ending IStep0sub1");
+
+ // if non-null, wait for the barrier, otherwise just return
+ if ( pTaskArgs )
+ {
+ pTaskArgs->waitChildSync();
+ }
+
+ task_end();
+}
+
+extern "C"
+void IStep1sub0( void * io_pArgs )
+{
+ INITSERVICE::TaskArgs::TaskArgs *pTaskArgs =
+ reinterpret_cast<INITSERVICE::TaskArgs::TaskArgs *>(io_pArgs);
+ uint64_t command = pTaskArgs->getCommand();
+ uint64_t returncode = pTaskArgs->getReturnCode();
+
+
+ // print out stuff from taskargs
+ TRACFCOMP( g_trac_istep1,
+ ENTER_MRK "starting IStep1sub0, command=0x%llx, returncode=0x%llx",
+ command, returncode );
+ // ----- start ISTEP --------------------------------------------------
+
+ pTaskArgs->postReturnCode( 0 );
+
+ // ----- end ISTEP --------------------------------------------------
+ TRACFCOMP( g_trac_istep1,
+ EXIT_MRK "ending IStep1sub0");
+
+ // if non-null, wait for the barrier, otherwise just return
+ if ( pTaskArgs )
+ {
+ pTaskArgs->waitChildSync();
+ }
+
+ task_end();
+}
} // namespace
OpenPOWER on IntegriCloud