summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorMark Wenning <wenning@us.ibm.com>2011-11-29 09:33:26 -0600
committerMark W. Wenning <wenning@us.ibm.com>2011-12-06 18:22:18 -0600
commit16bc626758b6dc65c1178e387501cb045e6dcd1d (patch)
tree19a98575511945ddc0c634a405b8cb776bd27dfd /src/usr
parent6a169ffdcc62a48667bb3c22b7547b019dd7e1bf (diff)
downloadblackbird-hostboot-16bc626758b6dc65c1178e387501cb045e6dcd1d.tar.gz
blackbird-hostboot-16bc626758b6dc65c1178e387501cb045e6dcd1d.zip
RTC3594: Improve SPLess Operation
- branch spless3 - reorganize command and status regs - add seqnum - rewrite spless handler - add scanistepnames.pl code to extract istep names - modify hb-simdebug.py to read istep names - review fixes - add workaround for vbu Change-Id: I0f8f991ccbaa822ef5ab672279c3c206e6b7b2e3 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/523 Tested-by: Jenkins Server Reviewed-by: Mark W. Wenning <wenning@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/initservice/build/makefile52
-rwxr-xr-xsrc/usr/initservice/build/scanistepnames.pl185
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.C378
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.H14
-rw-r--r--src/usr/initservice/istepdispatcher/makefile2
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommon.H275
-rw-r--r--src/usr/initservice/makefile2
-rw-r--r--src/usr/initservice/test/splesstest.H396
8 files changed, 612 insertions, 692 deletions
diff --git a/src/usr/initservice/build/makefile b/src/usr/initservice/build/makefile
new file mode 100644
index 000000000..e2e029af3
--- /dev/null
+++ b/src/usr/initservice/build/makefile
@@ -0,0 +1,52 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/initservice/build/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
+#
+# makefile for initialization service build tasks.
+# 1. create isteplist.csv file for spless
+#
+
+
+ROOTPATH=../../../..
+
+## pull in IMGDIR, etc.
+include ${ROOTPATH}/src/usr/parser.mk
+
+OBJFILES=
+
+all: gen_pass code_pass
+
+gen_pass:
+
+code_pass: ${IMGDIR}/isteplist.csv
+
+${IMGDIR}/isteplist.csv : ${ROOTPATH}/src/include/usr/isteps/*.H
+ ./scanistepnames.pl -b $(ROOTPATH)/src/include/usr/isteps -d -o $@
+
+clean:
+ rm -fr ${IMGDIR}/isteplist.csv
+ rm -fr *.o
+
+debug:
+ ls -l ${GENDIR}
+ ls -l ${OBJDIR}
+ ls -l ${IMGDIR}
diff --git a/src/usr/initservice/build/scanistepnames.pl b/src/usr/initservice/build/scanistepnames.pl
new file mode 100755
index 000000000..02435087c
--- /dev/null
+++ b/src/usr/initservice/build/scanistepnames.pl
@@ -0,0 +1,185 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/initservice/build/scanistepnames.pl $
+#
+# 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
+
+#
+# scan files in the src/include/usr/isteps dir for ISTEPSNAME macro. This
+# calls out ISTeps that are executed by the IStep Dispatcher.
+# This perl script will create an img/istepnames.csv file that contains a
+# list of Comma-Separated-Values of the istep, substep, and istep names
+# that the user console should support. For example:
+# 4,0,init_target_states
+# 4,1,init_fsi
+# 4,2,apply_fsi_info
+# 4,3,apply_dd_presence
+# 4,4,apply_pr_keyword_data
+# 4,5,apply_partial_bad
+# 4,6,apply_gard
+# 4,7,testHWP
+
+use strict;
+use File::Find ();
+use Time::localtime;
+use File::Path;
+
+# Variables
+my $DEBUG = 0;
+my $sandBase = $ENV{HOSTBOOTROOT};
+
+my $arg;
+my $argOutput = "";
+my $output = "";
+
+# Arrays
+my @fileList;
+
+while( $ARGV = shift )
+{
+ if( $ARGV =~ m/-b/ )
+ {
+ # set base input dir
+ $sandBase = shift;
+ }
+ elsif( $ARGV =~ m/-o/i )
+ {
+ # set output filename
+ $argOutput = shift;
+ }
+ elsif( $ARGV =~ m/-h/i )
+ {
+ # help
+ usage();
+ }
+ elsif( $ARGV =~ m/-d/i )
+ {
+ # debug flag
+ $DEBUG = 1;
+ }
+ else
+ {
+ usage();
+ }
+}
+
+# Variables depending on input parameters
+if( $argOutput eq "" )
+{
+ $output = "$sandBase/img/istepnames.csv";
+}
+else
+{
+ $output = $argOutput;
+}
+
+print "base input dir: $sandBase\n";
+print "output file name: $argOutput\n";
+print "debug flag: $DEBUG\n";
+
+#debugMsg( "Source Base Path: $sourcebasePath" );
+#debugMsg( "Sandbox Base Dir: $sandBase" );
+#debugMsg( "Output Dir: $output" );
+
+@fileList = getFiles( $sandBase );
+
+open( OUTFILE, "> $argOutput" ) or die( "Cannot open: $argOutput: $!" );
+
+my $infile;
+my $csv;
+my $junk;
+my $junk2;
+
+foreach $infile ( @fileList )
+{
+ print "Scanning file $sandBase/$infile...\n";
+ open(INFILE, "< $sandBase/$infile") or die("Cannot open: $infile: $!");
+
+ while( <INFILE> )
+ {
+ if ( m/^ *ISTEPNAME/ )
+ {
+ ( $junk, $csv, $junk2 ) = split /[\(\)]/ ;
+ $csv =~ s/[" ]//g;
+ print $csv, "\n";
+ print OUTFILE $csv, "\n";
+ }
+ }
+
+}
+
+close (INFILE);
+close (OUTFILE);
+
+
+## Subroutines ################################################################
+
+##
+## Print the Usage message
+##
+sub usage
+{
+ print "Usage: $0 < -b base > <-d> < -o output file >\"\n";
+ print "\n";
+ print "-b: base directory ( default is pwd )\n";
+ print "-o: Output file path for csv file\n";
+ print "-d Enable Debug messages.\n";
+ print "-h Display usage message.\n";
+ print "\n\n";
+ exit 1;
+}
+
+
+#
+# Print debug messages if $DEBUG is enabled.
+#
+sub debugMsg
+{
+ my ($msg) = @_;
+ if( $DEBUG )
+ {
+ print "DEBUG: $msg\n";
+ }
+}
+
+
+#
+# getFiles - find *.H or *.C files
+# This recursively searches the input directory passed in for all C/H files.
+#
+sub getFiles
+{
+ my ($l_input_dir) = @_;
+ my @dir_entry;
+ my $basefilename;
+ local *DH;
+
+ debugMsg( "Getting Files for dir: $l_input_dir" );
+
+ # Open the directory and read all entry names.
+ opendir(DH, $l_input_dir) or die("Cannot open $l_input_dir: $!");
+ # skip the dots
+ ## @dir_entry = grep { !/^\./ } readdir(DH);
+ @dir_entry = grep { /^*.[CH]/ } readdir(DH);
+ closedir(DH);
+
+ return( @dir_entry );
+}
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C
index d2d889e06..df3178f6f 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.C
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C
@@ -116,6 +116,7 @@ namespace INITSERVICE
{
using namespace ERRORLOG; // IStepNameUserDetails
+using namespace SPLESS;
/******************************************************************************/
// Globals/Constants
@@ -123,6 +124,14 @@ using namespace ERRORLOG; // IStepNameUserDetails
extern trace_desc_t *g_trac_initsvc;
/**
+ * @note Since ISTEP_MODE attribute is nonvolatile (persists across boots),
+ * we must have a way to turn the attribute both ON and OFF - we
+ * cannot depend on the FSP to do it since we may not have a FSP.
+ */
+const uint64_t ISTEP_MODE_ON_SIGNATURE = 0x4057b0074057b007;
+const uint64_t ISTEP_MODE_OFF_SIGNATURE = 0x700b7504700b7504;
+
+/**
* @enum
* SPLess Task return codes
*
@@ -136,6 +145,8 @@ enum {
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
+
+ SPLESS_INVALID_COMMAND = 10, // invalid command from user console
};
/**
@@ -146,7 +157,6 @@ enum {
* @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;
@@ -314,32 +324,167 @@ void IStepDispatcher::initIStepMode( )
}
-void IStepDispatcher::singleStepISteps( void * io_ptr ) const
+
+
+/**
+ * @brief Command 0: Run the requested IStep/SubStep
+ *
+ * param[in] i_rcmd - ref to a filled in SPLessCmd struct
+ * param[out] o_sts - ref to a SPLessSts struct to be filled in
+ *
+ * @return none
+ */
+void IStepDispatcher::processSingleIStepCmd(
+ SPLessCmd &i_rrawcmd,
+ SPLessSts &o_rrawsts ) const
{
- 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;
+ errlHndl_t l_errl = NULL;
+ uint64_t l_isteprc = NULL;
+ TaskArgs::TaskArgs l_taskargs;
+ const TaskInfo *l_pistep = NULL;
+ // init the command 0x00 struct to the incoming command reg values
+ SPLessSingleIStepCmd l_cmd( i_rrawcmd );
+ // create a cleared status 0x00 reg
+ SPLessSingleIStepSts l_sts;
+
+ // look up istep+substep
+ l_pistep = IStepDispatcher::getTheInstance().findTaskInfo(
+ l_cmd.istep,
+ l_cmd.substep );
+
+ do
+ {
+ if ( l_pistep == NULL )
+ {
+ // invalid istep, return error
+ l_sts.hdr.runningbit = false;
+ l_sts.hdr.readybit = true;
+ l_sts.hdr.status = SPLESS_TASKRC_INVALID_ISTEP;
+ l_sts.istep = l_cmd.istep;
+ l_sts.substep = l_cmd.substep;
+ l_sts.istepStatus = 0;
+
+ // return to caller to write back to user console
+ o_rrawsts.val64 = l_sts.val64;
+ break;
+ }
+
+
+ // set running bit, fill in istep and substep
+ l_sts.hdr.runningbit = true;
+ l_sts.hdr.readybit = true;
+ l_sts.hdr.status = 0;
+ l_sts.istep = l_cmd.istep;
+ l_sts.substep = l_cmd.substep;
+ l_sts.istepStatus = 0;
+
+ // write intermediate value back to user console
+ o_rrawsts.val64 = l_sts.val64;
+ writeSts( o_rrawsts );
+
+ /**
+ * @todo placeholder - set progress code before starting
+ * This will not be finalized until the progress code driver
+ * is designed and implemented.
+ */
+ uint64_t l_progresscode = ( (l_cmd.istep<<16) | l_cmd.substep );
+ InitService::getTheInstance().setProgressCode( l_progresscode );
+
+
+ // clear the TaskArgs struct
+ l_taskargs.clear();
+
+ // clear the status struct for the next step
+ l_sts.val64 = 0;
+
+ // launch the istep
+ l_errl = InitService::getTheInstance().executeFn( l_pistep,
+ &l_taskargs );
+ // 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_sts.hdr.status = SPLESS_TASKRC_LAUNCH_FAIL;
+ errlCommit( l_errl, INITSVC_COMP_ID );
+ }
+ 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_taskargs.getReturnCode(); // local copy
+ l_errl = l_taskargs.getErrorLog(); // local copy
+
+ // check for child errorlog
+ if ( l_errl )
+ {
+ // tell the user that the IStep returned an errorlog
+ l_sts.hdr.status = SPLESS_TASKRC_RETURNED_ERRLOG;
+ // go ahead and commit the child errorlog
+ errlCommit( l_errl, INITSVC_COMP_ID );
+ }
- TRACFCOMP( g_trac_initsvc, "Start IStep single-step.\n" );
+ // truncate IStep return status to 32 bits.
+ l_isteprc &= SPLESS_SINGLE_STEP_STS_MASK;
+ l_sts.istepStatus = static_cast<uint32_t>(l_isteprc);
+ } // end else parent errlog
+
+ // task status and istepStatus should be set correctly now,
+ // send it to the user console.
+ // clear runningbit, report status
+ // set running bit, fill in istep and substep
+ l_sts.hdr.runningbit = false;
+ l_sts.hdr.readybit = true;
+ // l_sts.hdr.seqnum = i_seqnum;
+ // task status set above
+ l_sts.istep = l_cmd.istep;
+ l_sts.substep = l_cmd.substep;
+ // istepStatus set above
+
+ // write to status reg, return to caller to write to user console
+ o_rrawsts.val64 = l_sts.val64;
+
+ break;
+
+ } while(0);
+
+}
+
+
+/**
+ * @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 IStepDispatcher::singleStepISteps( void * io_ptr ) const
+{
+ SPLessCmd l_cmd;
+ SPLessSts l_sts;
+ uint8_t l_seqnum = 0;
// initialize command reg
- SPLESSCMD::write( false, // go bit is false
- 0, // istep = 0
- 0 ); // substep = 0
+ l_cmd.val64 = 0;
+ writeCmd( l_cmd );
- SPLESSSTS::write( false, // running bit
- true, // ready bit
- 0, // istep running
- 0, // substep running
- 0, // task status
- 0 ); // istep status
+ // init status reg, enable ready bit
+ l_sts.val64 = 0;
+ l_sts.hdr.readybit = true;
+ writeSts( l_sts );
//
// @note Start the polling loop.
@@ -349,134 +494,59 @@ void IStepDispatcher::singleStepISteps( void * io_ptr ) const
//
while( 1 )
{
- // read command reg, updates l_gobit, l_nextIStep, l_nextSubstep
- SPLESSCMD::read( l_gobit,
- l_nextIStep,
- l_nextSubstep );
- // process any commands
- if ( l_gobit )
- {
- TRACDCOMP( g_trac_initsvc,
- "gobit turned on, istep=0x%x, substep=0x%x",
- l_nextIStep,
- l_nextSubstep );
+ // read command register from user console
+ readCmd( l_cmd );
- // 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
+ // get the sequence number
+ l_seqnum = l_cmd.hdr.seqnum;
+
+ // process any pending commands
+ if ( l_cmd.hdr.gobit )
+ {
+ switch( l_cmd.hdr.cmdnum )
{
- // 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, INITSVC_COMP_ID );
- }
- 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, INITSVC_COMP_ID);
- }
-
- // 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
+ case SPLESS_SINGLE_ISTEP_CMD:
+ // command 0: run istep/substep
+ processSingleIStepCmd( l_cmd, l_sts );
+ break;
+
+ default:
+ l_sts.hdr.status = SPLESS_INVALID_COMMAND;
+ } // endif switch
+
+ l_sts.hdr.seqnum = l_seqnum;
+ // status should be set now, write to Status Reg.
+ writeSts( l_sts );
+
+ // clear command reg, including go bit (i.e. set to false)
+ l_cmd.val64 = 0;
+ writeCmd( l_cmd );
} // endif gobit
+
// sleep, and wait for user to give us something else to do.
- nanosleep( SINGLESTEP_PAUSE_S, SINGLESTEP_PAUSE_NS );
+ /**
+ * @todo Need a common method of doing delays in HostBoot
+ * @VBU workaround
+ */
+ // Don't delay as long in VBU because it will take VERY long to
+ // run the simulator
+ TARGETING::EntityPath syspath(TARGETING::EntityPath::PATH_PHYSICAL);
+ syspath.addLast(TARGETING::TYPE_SYS,0);
+ TARGETING::Target* sys = TARGETING::targetService().toTarget(syspath);
+ uint8_t vpo_mode = 0;
+ if( sys
+ && sys->tryGetAttr<TARGETING::ATTR_VPO_MODE>(vpo_mode)
+ && (vpo_mode == 0) )
+ {
+ nanosleep( SINGLESTEP_PAUSE_S, SINGLESTEP_PAUSE_NS );
+ }
+ else
+ {
+ // VBU delay per Patrick
+ nanosleep(0,TEN_CTX_SWITCHES_NS);
+ }
} // endwhile
@@ -485,22 +555,10 @@ void IStepDispatcher::singleStepISteps( void * io_ptr ) const
// 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, INITSVC_COMP_ID );
- assert(0);
- }
+ l_sts.val64 = 0;
+ l_sts.hdr.status = SPLESS_TASKRC_TERMINATED;
+ l_sts.hdr.seqnum = l_seqnum;
+ writeSts( l_sts );
}
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H
index 70e9f2883..5add1008c 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.H
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H
@@ -56,6 +56,8 @@
namespace INITSERVICE
{
+// using namespace SPLESS;
+
/******************************************************************************/
// Globals/Constants
/******************************************************************************/
@@ -158,6 +160,18 @@ private:
const TaskInfo *findTaskInfo( uint16_t i_IStep,
uint16_t i_SubStep ) const;
+ /**
+ * @brief Command 0: Run the requested IStep/SubStep
+ *
+ * param[in] i_rcmd - ref to a filled in SPLessCmd struct
+ * param[out] o_sts - ref to a SPLessSts struct to be filled in
+ *
+ * @return none
+ */
+ void processSingleIStepCmd(
+ SPLESS::SPLessCmd &i_rcmd,
+ SPLESS::SPLessSts &o_rsts ) const;
+
/**
* @brief singleStepISteps
diff --git a/src/usr/initservice/istepdispatcher/makefile b/src/usr/initservice/istepdispatcher/makefile
index d18adfc4f..43e064f00 100644
--- a/src/usr/initservice/istepdispatcher/makefile
+++ b/src/usr/initservice/istepdispatcher/makefile
@@ -24,7 +24,7 @@
ROOTPATH = ../../../..
MODULE = istepdisp
-OBJS = istepdispatcher.o splesscommand.o splessstatus.o
+OBJS = istepdispatcher.o
## SUBDIRS = test.d
diff --git a/src/usr/initservice/istepdispatcher/splesscommon.H b/src/usr/initservice/istepdispatcher/splesscommon.H
index d75ee1f83..d08b920c2 100644
--- a/src/usr/initservice/istepdispatcher/splesscommon.H
+++ b/src/usr/initservice/istepdispatcher/splesscommon.H
@@ -29,6 +29,9 @@
* Prototypes for routines to access SPLESS Command and
* and SPLESS Status interfaces
*
+ * Currently SPLess only supports the one command 0x00, this rewrite will
+ * allow support of other SPLess commands.
+ *
*/
/******************************************************************************/
@@ -38,11 +41,9 @@
#include <stdio.h>
#include <string.h>
-/******************************************************************************/
-// Globals/Constants
-/******************************************************************************/
+
/**
- * @note Since ISTEP_MODE attribute is nonvolitile (persists across boots),
+ * @note Since ISTEP_MODE attribute is nonvolatile (persists across boots),
* we must have a way to turn the attribute both ON and OFF - we
* cannot depend on the FSP to do it since we may not have a FSP.
*/
@@ -57,115 +58,123 @@ const uint64_t ISTEP_MODE_OFF_SIGNATURE = 0x700b7504700b7504;
* @namespace SPLESSCMD
*
* Contains functions to manipulate the SPLESS Command Register
- * @todo overload these later to get command and seq fields
*
*/
-namespace SPLESSCMD
+namespace SPLESS
{
+const uint8_t SPLESS_SINGLE_ISTEP_CMD = 0x00;
+const uint64_t SPLESS_SINGLE_STEP_STS_MASK = 0x00000000ffffffff;
+
+
/**
- * @union InternalCommand
- *
- * define the fields within the 64-bit Command Register
+ * @struct CommandHdr
*
-
+ * Command Header for all SPless commands. 2 bytes long.
* 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:
+ * Command Number: bits 8:15
+ *
*
*/
-union InternalCommand
+struct CommandHdr
{
- uint64_t val64;
- struct
- {
- bool gobit:1;
- uint8_t reserved0:1;
- uint8_t seqnum:6;
- uint8_t cmdnum;
+ bool gobit:1;
+ uint8_t reserved0:1;
+ uint8_t seqnum:6;
+ uint8_t cmdnum;
- uint16_t reserved2;
+} __attribute__((packed));
- uint16_t reserved3:2;
- uint16_t istep:14;
- uint16_t substep;
- } f PACKED;
+/**
+ * @union SPLessCmd
+ *
+ * 64-bit "template" struct for the SPLess command.
+ * This will be read in and used to extract the header info, then "cast"
+ * to the correct command.
+ */
+union SPLessCmd
+{
+ uint64_t val64;
+ struct
+ {
+ CommandHdr hdr;
+ uint16_t reserved1;
+ uint32_t reserved2;
+ } __attribute__((packed));
// init struct to 0
- InternalCommand() : val64(0) {};
+ SPLessCmd() : val64(0) {};
} ;
/**
- * @brief Read the command register and return the necessary fields.
+ * @union SPLessSingleIStepCmd
*
- * @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
+ * Implement Command 0x00, run Istep/Substep
*
- * @return pointer to errorlog
- * @retval NULL if success, filled-in errorlog if failure
+ * Send IStep and SubStep number(s) to run.
*
*/
-void read( bool &io_rgobit,
- uint16_t &io_ristep,
- uint16_t &io_rsubstep );
+union SPLessSingleIStepCmd
+{
+ uint64_t val64;
+ struct
+ {
+ CommandHdr hdr;
+ uint8_t istep;
+ uint8_t substep;
+ uint32_t reserved;
+ } __attribute__((packed));
+ SPLessSingleIStepCmd() : val64(0) {};
-/**
- * @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 );
+
+ SPLessSingleIStepCmd( const SPLessCmd &i_cmd )
+ : val64(i_cmd.val64) { };
+
+private:
+ // disable assignment constructor
+ SPLessSingleIStepCmd& operator=(const SPLessSingleIStepCmd& i_right);
+
+} ;
/**
- * @brief Read the gobit from the command register
+ * @brief Read the command register and return a filled-in SPLessCmd struct
*
- * @param o_rgobit - ref to a gobit var that will be filled in
- * on return.
+ * @param[in,out] io_rcmd - reference to a SPLessCmd struct
*
- * @return errorlog pointer
- * @retval NULL if success, filled-in errorlog on failure
+ * @return none
*/
-void getgobit( bool &o_rgobit );
+inline void readCmd( SPLessCmd &io_rcmd )
+{
+
+ io_rcmd.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_COMMAND);
+}
/**
- * @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 ) ;
+ * @brief Write a filled-in command struct 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_rcmd - reference to a filled-in SPLessCmd reg
+ *
+ * @return none
+ */
+inline void writeCmd( SPLessCmd &io_rcmd )
+{
+
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, io_rcmd.val64 );
+}
-} // namespace
/******************************************************************************/
@@ -173,20 +182,12 @@ void setgobit( const bool i_gobit ) ;
/******************************************************************************/
/**
- * @namespace SPLESSSTS
+ * @struct StatusHdr
*
- * Contains functions to manipulate the SPLESS Status Register
- * @todo overload these to get seq # later
+ * header for the Status Reg returned by all SPLess Commands.
*
- */
-namespace SPLESSSTS
-{
-
-/**
- * @union InternalStatus
- *
- * define the fields within the 64-bit status register
- * Running bit, bit 0 (ppc notation, msbit):
+ * Bit numbers are in ppc notation, where bit 0 is the most significant bit.
+ * * Running bit, bit 0 (ppc notation, msbit):
* = 1 when IStep is running
* = 0 when IStep is finished
* Ready bit, bit 1:
@@ -196,80 +197,86 @@ namespace SPLESSSTS
* - 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:
+ * Status : returned status for the command, from IStepDisp.
+ * For example:
* -EINVAL IStep number is invalid
* -ENOENT, -ENOEXEC (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.
+ */
+struct StatusHdr
+{
+ bool runningbit:1;
+ bool readybit:1;
+ uint8_t seqnum:6;
+ int8_t status;
+
+} __attribute__((packed));
+
+/**
+ * @union SPLessSts
+ *
+ * Send HostBoot Status to the user console
*
*/
-union InternalStatus {
+union SPLessSts {
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;
+ StatusHdr hdr;
+ uint16_t reserved1;
+ uint32_t reserved2;
+ } __attribute__((packed));
// init struct to 0
- InternalStatus() : val64(0) {};
+ SPLessSts() : val64(0) {};
} ;
+/**
+ * @union SPLessSts0x00
+ *
+ * Return Status from IStep/Substep
+ *
+ */
+union SPLessSingleIStepSts {
+ uint64_t val64;
+ struct {
+ StatusHdr hdr;
+ uint8_t istep;
+ uint8_t substep;
+ uint32_t istepStatus;
+ } __attribute__((packed));
+
+ SPLessSingleIStepSts() : val64(0) {};
+} ;
+
/**
- * @brief Read the SPLess Status SCOM Reg and return all its fields
+ * @brief Read the SPLess Status reg and return a filled in struct.
*
- * @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
+ * @param[in,out] io_rsts - ref SPLessSts struct
*
* @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 );
+inline void readSts( SPLessSts &io_rsts )
+{
+
+ io_rsts.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_STATUS);
+}
/**
- * @brief write
+ * @brief Write a filled in SPLessSts struct to the SPLess Status Reg
*
- * 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
+ * @param[in,out] io_rsts
*
* @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 );
+inline void writeSts( SPLessSts &io_rsts )
+{
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_STATUS, io_rsts.val64 );
+
+}
} // namespace
+
#endif
diff --git a/src/usr/initservice/makefile b/src/usr/initservice/makefile
index 28240f386..5bdac5fde 100644
--- a/src/usr/initservice/makefile
+++ b/src/usr/initservice/makefile
@@ -29,6 +29,6 @@ ROOTPATH = ../../..
# 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 initsvctasktest2.d
+ test.d initsvctasktest2.d build.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/initservice/test/splesstest.H b/src/usr/initservice/test/splesstest.H
deleted file mode 100644
index d1caf006b..000000000
--- a/src/usr/initservice/test/splesstest.H
+++ /dev/null
@@ -1,396 +0,0 @@
-// 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_ON_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
-
OpenPOWER on IntegriCloud