summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/hwas/deconfigGard.H453
-rw-r--r--src/include/usr/hwas/hwas_reasoncodes.H43
-rw-r--r--src/lib/sync.C2
-rw-r--r--src/usr/hwas/deconfigGard.C692
-rw-r--r--src/usr/hwas/makefile2
-rw-r--r--src/usr/hwas/test/hwasGardTest.H920
-rw-r--r--src/usr/targeting/xmltohb/attribute_types.xml13
-rw-r--r--src/usr/targeting/xmltohb/target_types.xml12
8 files changed, 2135 insertions, 2 deletions
diff --git a/src/include/usr/hwas/deconfigGard.H b/src/include/usr/hwas/deconfigGard.H
new file mode 100644
index 000000000..25de080fc
--- /dev/null
+++ b/src/include/usr/hwas/deconfigGard.H
@@ -0,0 +1,453 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/hwas/deconfigGard.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 deconfigGard.H
+ *
+ * @brief Defines the DeconfigGard class that provides functions to deconfigure
+ * and create GARD records for Targets
+ */
+
+#ifndef DECONFIGGARD_H_
+#define DECONFIGGARD_H_
+
+#include <vector>
+#include <stdint.h>
+#include <sys/sync.h>
+#include <util/singleton.H>
+#include <errl/errlentry.H>
+#include <targeting/target.H>
+#include <targeting/entitypath.H>
+
+namespace HWAS
+{
+
+/**
+ * @brief Returns a reference to the DeconfigGard singleton.
+ */
+class DeconfigGard;
+DeconfigGard & theDeconfigGard();
+
+/**
+ * @class DeconfigGard
+ *
+ * This class defines the singleton that handles Deconfigure and GARD Record
+ * functionality
+ */
+class DeconfigGard
+{
+public:
+
+ /**
+ * @enum GardSeverity
+ *
+ * Defines the possible severities of a GARD Record
+ */
+ enum GardSeverity
+ {
+ GARD_SEVERITY_FATAL = 1,
+ GARD_SEVERITY_PREDICTIVE = 2,
+ GARD_SEVERITY_MANUAL = 3,
+ };
+
+ /**
+ * @enum DeconfigCause
+ *
+ * Defines the possible causes for the creation of a Deconfigure Record
+ */
+ enum DeconfigCause
+ {
+ DECONFIG_CAUSE_GARD_RECORD = 1, // Existence of GARD Record
+ DECONFIG_CAUSE_FIRMWARE_REQ = 2, // Firmware Request
+ DECONFIG_CAUSE_DECONFIG_BY_ASSOC = 3, // Deconfigure by Association
+ };
+
+ /**
+ * @struct GardRecord
+ *
+ * Defines a GARD Record.
+ *
+ * Multiple GARD Records can exist for a specific Target
+ */
+ struct GardRecord
+ {
+ uint32_t iv_recordId;
+ TARGETING::EntityPath iv_targetId;
+ union
+ {
+ char iv_cardMruSn[12]; // TODO is there a SN type?
+ uint32_t iv_chipMruEcid; // TODO is there an ECID type?
+ };
+ uint32_t iv_errlogPlid;
+ uint8_t iv_severity; // Value from GardSeverity
+ uint8_t iv_padding[3];
+ uint32_t iv_gardTime;
+ };
+
+ typedef std::vector<GardRecord> GardRecords_t;
+ typedef std::vector<GardRecord>::iterator GardRecordsItr_t;
+ typedef std::vector<GardRecord>::const_iterator GardRecordsCItr_t;
+
+ /**
+ * @struct DeconfigureRecord
+ *
+ * Defines a Deconfigure Record
+ *
+ * Only one Deconfigure Record can exist for a specific Target
+ */
+ struct DeconfigureRecord
+ {
+ TARGETING::EntityPath iv_targetId;
+ uint32_t iv_errlogPlid;
+ uint8_t iv_cause; // Value from DeconfigCause
+ uint8_t iv_padding[3];
+ uint32_t iv_deconfigureTime;
+ };
+
+ typedef std::vector<DeconfigureRecord> DeconfigureRecords_t;
+ typedef std::vector<DeconfigureRecord>::iterator DeconfigureRecordsItr_t;
+ typedef std::vector<DeconfigureRecord>::const_iterator DeconfigureRecordsCItr_t;
+
+ /**
+ * @brief Destructor.
+ */
+ ~DeconfigGard();
+
+ /**
+ * @brief Clears GARD Records for replaced Targets.
+ *
+ * Called by HWAS as part of initial IPL steps.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t clearGardRecordsForReplacedTargets();
+
+ /**
+ * @brief Deconfigures Targets that have GARD Records in preparation to IPL.
+ *
+ * Called by HWAS as part of initial IPL steps.
+ *
+ * If deconfiguring all such Targets will result in a configuration that is
+ * unable to IPL then it figures out which subset of Targets to deconfigure
+ * to give the best chance of IPL (Resource Recovery).
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t deconfigureTargetsFromGardRecordsForIpl();
+
+ /**
+ * @brief Deconfigures a Target.
+ *
+ * Called by ErrlManager when committing an error log containing a
+ * Deconfigure request.
+ *
+ * This will Deconfigure the Target (set state to non-functional, do any
+ * Deconfigure actions and create a Deconfigure Record) and Deconfigure
+ * Targets by association. Any errors deconfiguring targets are committed
+ * and the function continues. The only errors returned are usage errors.
+ *
+ * @param[in] i_target Reference to Target to deconfigure.
+ * @param[in] i_pErr Pointer to error log that will shortly be committed
+ * by the caller.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t deconfigureTarget(TARGETING::Target & i_target,
+ errlHndl_t i_pErr);
+
+ /**
+ * @brief Creates a GARD Record for a Target.
+ *
+ * Called by ErrlManager when committing an error log containing a
+ * GARD Record request.
+ *
+ * Called by an administrator to manually create a GARD Record.
+ *
+ * Any error creating the GARD Record will be returned to the user.
+ *
+ * @param[in] i_target Reference to Target to create GARD Record for.
+ * @param[in] i_pErr Pointer to error log that will shortly be committed
+ * by the caller.
+ * @param[in] i_severity Severity of the GARD Record.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t createGardRecord(const TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const GardSeverity i_severity);
+
+ /**
+ * @brief Gets the specified Deconfigure Records.
+ *
+ * Called by an administrator to view Deconfigure Records. There can only be
+ * one Deconfiguration Record per Target.
+ *
+ * If the specified record does not exist then no error is returned. The
+ * only errors returned are usage errors and errors accessing the
+ * Deconfigure Records.
+ *
+ * @param[in] i_pTargetId Pointer to the Target ID to get the Deconfigure
+ * Record for. If NULL then all Deconfigure Records
+ * are retrieved.
+ * @param[out] o_records Reference to vector of DeconfigureRecords that is
+ * cleared then filled in with records.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t getDeconfigureRecords(const TARGETING::EntityPath * i_pTargetId,
+ DeconfigureRecords_t & o_records) const;
+
+ /**
+ * @brief Clears the specified GARD Records.
+ *
+ * Called by an administrator to clear GARD records manually.
+ *
+ * If the specified record does not exist then no error is returned. The
+ * only errors returned are usage errors and errors accessing the GARD
+ * Records.
+ *
+ * @param[in] i_recordId RecordId to clear. If zero then all GARD Records
+ * are cleared.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t clearGardRecords(const uint32_t i_recordId);
+
+ /**
+ * @brief Clears all GARD Records for the specified Target.
+ *
+ * Called by an administrator to clear GARD records manually.
+ *
+ * If no GARD Records exist for the Target then no error is returned. The
+ * only errors returned are usage errors and errors accessing the GARD
+ * Records.
+ *
+ * @param[in] i_targetId Reference to Target ID to clear GARD Records for.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t clearGardRecords(const TARGETING::EntityPath & i_targetId);
+
+ /**
+ * @brief Gets the specified GARD Records.
+ *
+ * Called by an administrator to view GARD Records.
+ *
+ * If the specified record does not exist then no error is returned. The
+ * only errors returned are usage errors and errors accessing the GARD
+ * Records.
+ *
+ * @param[in] i_recordId RecordId to get. If zero then all GARD Records are
+ * retrieved.
+ * @param[out] o_records Reference to vector of GardRecords that is cleared
+ * then filled in with records.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t getGardRecords(const uint32_t i_recordId,
+ GardRecords_t & o_records);
+
+ /**
+ * @brief Gets all GARD Records for the specified Target.
+ *
+ * Called by an administrator to view GARD Records.
+ *
+ * If no GARD Records exist for the Target then no error is returned. The
+ * only errors returned are usage errors and errors accessing the GARD
+ * Records.
+ *
+ * @param[in] i_targetId Reference to Target ID to get GARD Records for.
+ * @param[out] o_records Reference to vector of GardRecords that is cleared
+ * then filled in with records.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t getGardRecords(const TARGETING::EntityPath & i_targetId,
+ GardRecords_t & o_records);
+
+protected:
+
+ /**
+ * @brief Default constructor
+ *
+ * Can only be called by Singleton
+ */
+ DeconfigGard();
+
+private:
+
+ // Copy constructor and assignment operator disabled
+ DeconfigGard(const DeconfigGard & i_right);
+ DeconfigGard & operator=(const DeconfigGard & i_right);
+
+ /**
+ * @brief Deconfigures Targets by association.
+ *
+ * @param[in] i_target Reference to base Target.
+ * @param[in] i_pErr Pointer to error log that will shortly be committed
+ * by the caller.
+ */
+ void _deconfigureByAssoc(TARGETING::Target & i_target,
+ errlHndl_t i_pErr);
+
+ /**
+ * @brief Deconfigures a Target.
+ *
+ * This will Deconfigure the Target (set state to non-functional, do any
+ * Deconfigure actions and create a Deconfigure Record).
+ *
+ * @param[in] i_target Reference to Target to deconfigure.
+ * @param[in] i_pErr Pointer to error log that will shortly be committed
+ * by the caller.
+ * @param[in] i_cause Deconfigure cause.
+ */
+ void _deconfigureTarget(TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const DeconfigCause i_cause);
+
+ /**
+ * @brief Performs Deconfigure Actions.
+ *
+ * @param[in] i_target Reference to Target to perform actions on.
+ */
+ void _doDeconfigureActions(TARGETING::Target & i_target);
+
+ /**
+ * @brief Creates a Deconfigure Record
+ *
+ * @param[in] i_target Reference to Target to create record for.
+ * @param[in] i_pErr Pointer to error log that will shortly be committed
+ * by the caller.
+ * @param[in] i_cause Deconfigure cause.
+ */
+ void _createDeconfigureRecord(const TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const DeconfigCause i_cause);
+
+public:
+
+ /**
+ * @brief Clears the specified Deconfigure Records.
+ *
+ * @note Provided for unit test only. Production code should not be
+ * clearing Deconfigure Records.
+ *
+ * @param[in] i_pTargetId Pointer to the Target ID to clear Deconfigure
+ * Records for. If NULL then all Deconfigure Records
+ * are cleared.
+ */
+ void _clearDeconfigureRecords(const TARGETING::EntityPath * i_pTargetId);
+
+private:
+ /**
+ * @brief Gets the specified Deconfigure Records.
+ *
+ * @param[in] i_pTargetId Pointer to the Target ID to get the Deconfigure
+ * Record for. If NULL then all Deconfigure Records
+ * are retrieved.
+ * @param[out] o_records Reference to vector of DeconfigureRecords that is
+ * cleared then filled in with records.
+ */
+ void _getDeconfigureRecords(const TARGETING::EntityPath * i_pTargetId,
+ DeconfigureRecords_t & o_records) const;
+
+ /**
+ * @brief Creates a GARD Record for a Target.
+ *
+ * @param[in] i_target Reference to Target to create GARD Record for.
+ * @param[in] i_pErr Pointer to error log that will shortly be committed
+ * by the caller.
+ * @param[in] i_severity Severity of the GARD Record.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t _createGardRecord(const TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const GardSeverity i_severity);
+
+ /**
+ * @brief Clears the specified GARD Records.
+ *
+ * @param[in] i_recordId RecordId to clear. If zero then all GARD Records
+ * are cleared.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t _clearGardRecords(const uint32_t i_recordId);
+
+ /**
+ * @brief Clears all GARD Records for the specified Target.
+ *
+ * @param[in] i_targetId Reference to Target ID to clear GARD Records for.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t _clearGardRecords(const TARGETING::EntityPath & i_targetId);
+
+ /**
+ * @brief Gets the specified GARD Records.
+ *
+ * @param[in] i_recordId RecordId to get. If zero then all GARD Records are
+ * retrieved.
+ * @param[out] o_records Reference to vector of GardRecords that is cleared
+ * then filled in with records.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t _getGardRecords(const uint32_t i_recordId,
+ GardRecords_t & o_records);
+
+ /**
+ * @brief Gets all GARD Records for the specified Target.
+ *
+ *
+ * @param[in] i_targetId Reference to Target ID to get GARD Records for.
+ * @param[out] o_records Reference to vector of GardRecords that is cleared
+ * then filled in with records.
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t _getGardRecords(const TARGETING::EntityPath & i_targetId,
+ GardRecords_t & o_records);
+
+ /**
+ * @brief Ensures that the GARD Record data is setup
+ *
+ * @return errlHndl_t. Error log handle.
+ */
+ errlHndl_t _ensureGardRecordDataSetup();
+
+ // Mutex for thread safety
+ mutable mutex_t iv_mutex;
+
+ // GARD Record Data
+ uint32_t iv_nextGardRecordId; // Next GARD Record ID to use
+ uint32_t iv_maxGardRecords; // Maximum number of GARD Records
+ GardRecord * iv_pGardRecords; // Pointer to the GARD Records in PNOR
+
+ // The Deconfigure Records
+ DeconfigureRecords_t iv_deconfigureRecords;
+};
+
+}
+
+#endif
diff --git a/src/include/usr/hwas/hwas_reasoncodes.H b/src/include/usr/hwas/hwas_reasoncodes.H
new file mode 100644
index 000000000..6e2b34858
--- /dev/null
+++ b/src/include/usr/hwas/hwas_reasoncodes.H
@@ -0,0 +1,43 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/hwas/hwas_reasoncodes.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 HWAS_REASONCODES_H
+#define HWAS_REASONCODES_H
+
+#include <hbotcompid.H>
+
+namespace HWAS
+{
+ enum HwasModuleID
+ {
+ MOD_DECONFIG_GARD = 0x01,
+ };
+
+ enum HwasReasonCode
+ {
+ RC_TARGET_NOT_DECONFIGURABLE = HWAS_COMP_ID | 0x01,
+ RC_TARGET_NOT_GARDABLE = HWAS_COMP_ID | 0x02,
+ RC_GARD_REPOSITORY_FULL = HWAS_COMP_ID | 0x03,
+ };
+};
+
+#endif
diff --git a/src/lib/sync.C b/src/lib/sync.C
index 95501d2aa..0b57aa0b7 100644
--- a/src/lib/sync.C
+++ b/src/lib/sync.C
@@ -97,7 +97,7 @@ void mutex_init(mutex_t * o_mutex)
//-----------------------------------------------------------------------------
-void mutex_destroy(mutex_t *& i_mutex)
+void mutex_destroy(mutex_t * i_mutex)
{
i_mutex->iv_val = ~0;
return;
diff --git a/src/usr/hwas/deconfigGard.C b/src/usr/hwas/deconfigGard.C
new file mode 100644
index 000000000..e1f42c2c7
--- /dev/null
+++ b/src/usr/hwas/deconfigGard.C
@@ -0,0 +1,692 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/hwas/deconfigGard.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 deconfigGard.C
+ *
+ * @brief Implements the DeconfigGard class
+ */
+
+#include <string.h>
+#include <targeting/targetservice.H>
+#include <errl/errlmanager.H>
+#include <hwas/deconfigGard.H>
+#include <hwas/hwas_reasoncodes.H>
+#include <pnor/pnorif.H>
+
+// Trace definition
+trace_desc_t* g_trac_deconf = NULL;
+#define __COMP_TD__ g_trac_deconf
+
+// The DeconfigGard code needs to trace a target. The current recommended way is
+// to get the Target's PHYS_PATH attribute and do a binary trace. However, the
+// size of a TARGETING::EntityPath is 17 bytes. This code will trace only the
+// first 16 bytes to avoid a multi-line binary trace. This all seems a little
+// convoluted. Is there a better way to trace a Target
+#define DG_TRAC_TARGET(string, pPath) \
+ TRACFBIN(g_trac_deconf, string, pPath, sizeof(TARGETING::EntityPath) - 1)
+
+namespace HWAS
+{
+
+//******************************************************************************
+DeconfigGard & theDeconfigGard()
+{
+ return Singleton<DeconfigGard>::instance();
+}
+
+//******************************************************************************
+DeconfigGard::DeconfigGard()
+: iv_nextGardRecordId(0),
+ iv_maxGardRecords(0),
+ iv_pGardRecords(NULL)
+{
+ TRAC_INIT_BUFFER(&g_trac_deconf, "DECONF", 4096);
+ TRAC_INF("DeconfigGard Constructor");
+ mutex_init(&iv_mutex);
+}
+
+//******************************************************************************
+DeconfigGard::~DeconfigGard()
+{
+ TRAC_INF("DeconfigGard Destructor");
+ mutex_destroy(&iv_mutex);
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::clearGardRecordsForReplacedTargets()
+{
+ TRAC_INF("****TBD****Usr Request: Clear GARD Records for replaced Targets");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = NULL;
+
+ // TODO
+
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::deconfigureTargetsFromGardRecordsForIpl()
+{
+ TRAC_INF("****TBD****Usr Request: Deconfigure Targets from GARD Records for IPL");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = NULL;
+
+ // TODO
+
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::deconfigureTarget(TARGETING::Target & i_target,
+ errlHndl_t i_pErr)
+{
+ TRAC_ERR("Usr Request: Deconfigure Target");
+ mutex_lock(&iv_mutex);
+
+ // Caller must pass a valid errlHndl_t
+ assert(i_pErr != NULL);
+
+ // Deconfigure the Target
+ _deconfigureTarget(i_target, i_pErr, DECONFIG_CAUSE_FIRMWARE_REQ);
+
+ // Deconfigure other Targets by association
+ _deconfigureByAssoc(i_target, i_pErr);
+
+ mutex_unlock(&iv_mutex);
+ return NULL;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::createGardRecord(const TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const GardSeverity i_severity)
+{
+ TRAC_ERR("Usr Request: Create GARD Record");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = _createGardRecord(i_target, i_pErr, i_severity);
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::getDeconfigureRecords(
+ const TARGETING::EntityPath * i_pTargetId,
+ DeconfigureRecords_t & o_records) const
+{
+ TRAC_INF("Usr Request: Get Deconfigure Record(s)");
+ mutex_lock(&iv_mutex);
+ _getDeconfigureRecords(i_pTargetId, o_records);
+ mutex_unlock(&iv_mutex);
+ return NULL;
+}
+
+
+//******************************************************************************
+errlHndl_t DeconfigGard::clearGardRecords(const uint32_t i_recordId)
+{
+ TRAC_INF("Usr Request: Clear GARD Record(s) by Record ID");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = _clearGardRecords(i_recordId);
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::clearGardRecords(
+ const TARGETING::EntityPath & i_targetId)
+{
+ TRAC_INF("Usr Request: Clear GARD Record(s) by Target ID");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = _clearGardRecords(i_targetId);
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::getGardRecords(
+ const uint32_t i_recordId,
+ GardRecords_t & o_records)
+{
+ TRAC_INF("Usr Request: Get GARD Record(s) by Record ID");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = _getGardRecords(i_recordId, o_records);
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::getGardRecords(
+ const TARGETING::EntityPath & i_targetId,
+ GardRecords_t & o_records)
+{
+ TRAC_INF("Usr Request: Get GARD Record(s) by Target ID");
+ mutex_lock(&iv_mutex);
+ errlHndl_t l_pErr = _getGardRecords(i_targetId, o_records);
+ mutex_unlock(&iv_mutex);
+ return l_pErr;
+}
+
+//******************************************************************************
+void DeconfigGard::_deconfigureByAssoc(TARGETING::Target & i_target,
+ errlHndl_t i_pErr)
+{
+ TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>();
+ DG_TRAC_TARGET(ERR_MRK "****TBD****: Deconfiguring by Association for: ",
+ &l_id);
+
+ // TODO
+}
+
+//******************************************************************************
+void DeconfigGard::_deconfigureTarget(TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const DeconfigCause i_cause)
+{
+ TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>();
+ DG_TRAC_TARGET(ERR_MRK "Deconfiguring Target: ", &l_id);
+
+ errlHndl_t l_pErr = NULL;
+
+ if (!i_target.getAttr<TARGETING::ATTR_DECONFIG_GARDABLE>())
+ {
+ // Target is not Deconfigurable. Commit an error
+ TRAC_ERR("Target not Deconfigurable");
+ /*@
+ * @errortype
+ * @moduleid MOD_DECONFIG_GARD
+ * @reasoncode RC_TARGET_NOT_DECONFIGURABLE
+ * @devdesc Attempt to deconfigure a target that is not
+ * deconfigurable
+ */
+ l_pErr = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ MOD_DECONFIG_GARD,
+ RC_TARGET_NOT_DECONFIGURABLE);
+ errlCommit(l_pErr);
+ }
+ else
+ {
+ // Set the Target state to non-functional. The assumption is that it is
+ // not possible for another thread (other than deconfigGard) to be
+ // updating HWAS_STATE concurrently.
+ TARGETING::HwasState l_state =
+ i_target.getAttr<TARGETING::ATTR_HWAS_STATE>();
+
+ if (!l_state.functional)
+ {
+ TRAC_ERR("Target HWAS_STATE already non-functional");
+ }
+ else
+ {
+ TRAC_ERR("Setting Target HWAS_STATE to non-functional");
+ l_state.functional = 0;
+ i_target.setAttr<TARGETING::ATTR_HWAS_STATE>(l_state);
+ }
+
+ // Do any necessary Deconfigure Actions
+ _doDeconfigureActions(i_target);
+
+ // Create a Deconfigure Record
+ _createDeconfigureRecord(i_target, i_pErr, i_cause);
+ }
+}
+
+//******************************************************************************
+void DeconfigGard::_doDeconfigureActions(TARGETING::Target & i_target)
+{
+ // TODO
+}
+
+//******************************************************************************
+void DeconfigGard::_createDeconfigureRecord(
+ const TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const DeconfigCause i_cause)
+{
+ // Get the Target's ID
+ TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Look for an existing Deconfigure Record for the Target
+ DeconfigureRecordsCItr_t l_itr = iv_deconfigureRecords.begin();
+
+ for (; l_itr != iv_deconfigureRecords.end(); ++l_itr)
+ {
+ if ((*l_itr).iv_targetId == l_id)
+ {
+ break;
+ }
+ }
+
+ if (l_itr != iv_deconfigureRecords.end())
+ {
+ TRAC_ERR("Not creating a Deconfigure Record, one already exists");
+ }
+ else
+ {
+ // Create a DeconfigureRecord
+ TRAC_ERR("Creating a Deconfigure Record");
+
+ DeconfigureRecord l_record;
+ l_record.iv_targetId = l_id;
+ l_record.iv_errlogPlid = 0; // TODO Get PLID from ErrorLog
+ l_record.iv_cause = i_cause;
+ l_record.iv_padding[0] = 0;
+ l_record.iv_padding[1] = 0;
+ l_record.iv_padding[2] = 0;
+ l_record.iv_deconfigureTime = 0; // TODO Get epoch time
+
+ iv_deconfigureRecords.push_back(l_record);
+ }
+}
+
+//******************************************************************************
+void DeconfigGard::_clearDeconfigureRecords(
+ const TARGETING::EntityPath * i_pTargetId)
+{
+ if (i_pTargetId == NULL)
+ {
+ TRAC_INF("Clearing all %d Deconfigure Records",
+ iv_deconfigureRecords.size());
+ iv_deconfigureRecords.clear();
+ }
+ else
+ {
+ // Look for a Deconfigure Record for the specified Target (there can
+ // only be one record)
+ bool l_foundRecord = false;
+
+ for (DeconfigureRecordsItr_t l_itr = iv_deconfigureRecords.begin();
+ l_itr != iv_deconfigureRecords.end(); ++l_itr)
+ {
+ if ((*l_itr).iv_targetId == *i_pTargetId)
+ {
+ DG_TRAC_TARGET(INFO_MRK "Clearing Deconfigure Record for: ",
+ i_pTargetId);
+ iv_deconfigureRecords.erase(l_itr);
+ l_foundRecord = true;
+ break;
+ }
+ }
+
+ if (!l_foundRecord)
+ {
+ DG_TRAC_TARGET(INFO_MRK "Did not find a Deconfigure Record to clear for: ",
+ i_pTargetId);
+ }
+ }
+}
+
+//******************************************************************************
+void DeconfigGard::_getDeconfigureRecords(
+ const TARGETING::EntityPath * i_pTargetId,
+ DeconfigureRecords_t & o_records) const
+{
+ DeconfigureRecordsCItr_t l_itr = iv_deconfigureRecords.begin();
+ o_records.clear();
+
+ if (i_pTargetId == NULL)
+ {
+ TRAC_INF("Getting all %d Deconfigure Records",
+ iv_deconfigureRecords.size());
+
+ for (; l_itr != iv_deconfigureRecords.end(); ++l_itr)
+ {
+ o_records.push_back(*l_itr);
+ }
+ }
+ else
+ {
+ // Look for a Deconfigure Record for the specified Target (there can
+ // only be one record)
+ for (; l_itr != iv_deconfigureRecords.end(); ++l_itr)
+ {
+ if ((*l_itr).iv_targetId == *i_pTargetId)
+ {
+ DG_TRAC_TARGET(INFO_MRK "Getting Deconfigure Record for: ",
+ i_pTargetId);
+ o_records.push_back(*l_itr);
+ break;
+ }
+ }
+
+ if (l_itr == iv_deconfigureRecords.end())
+ {
+ DG_TRAC_TARGET(INFO_MRK "Did not find a Deconfigure Record to get for: ",
+ i_pTargetId);
+ }
+ }
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::_createGardRecord(const TARGETING::Target & i_target,
+ errlHndl_t i_pErr,
+ const GardSeverity i_severity)
+{
+ errlHndl_t l_pErr = NULL;
+
+ TARGETING::EntityPath l_id = i_target.getAttr<TARGETING::ATTR_PHYS_PATH>();
+ DG_TRAC_TARGET(ERR_MRK "Creating GARD Record for: ", &l_id);
+
+ if (!i_target.getAttr<TARGETING::ATTR_DECONFIG_GARDABLE>())
+ {
+ // Target is not GARDable. Commit an error
+ TRAC_ERR("Target not GARDable");
+ /*@
+ * @errortype
+ * @moduleid MOD_DECONFIG_GARD
+ * @reasoncode RC_TARGET_NOT_GARDABLE
+ * @devdesc Attempt to create a GARD Record for a target that is
+ * not GARDable
+ */
+ l_pErr = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_DECONFIG_GARD,
+ RC_TARGET_NOT_GARDABLE);
+ errlCommit(l_pErr);
+ }
+ else
+ {
+ l_pErr = _ensureGardRecordDataSetup();
+
+ if (l_pErr)
+ {
+ TRAC_ERR("Error from _ensureGardRecordDataSetup");
+ }
+ else
+ {
+ GardRecord * l_pRecord = NULL;
+
+ // Find an empty GARD Record slot
+ for (uint32_t i = 0; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_recordId == 0)
+ {
+ l_pRecord = &(iv_pGardRecords[i]);
+ break;
+ }
+ }
+
+ if (!l_pRecord)
+ {
+ TRAC_ERR("GARD Record Repository full");
+ /*@
+ * @errortype
+ * @moduleid MOD_DECONFIG_GARD
+ * @reasoncode RC_GARD_REPOSITORY_FULL
+ * @devdesc Attempt to create a GARD Record and the GARD
+ * Repository is full
+ * @userdata1 Number of GARD Records in repository
+ */
+ l_pErr = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_DECONFIG_GARD,
+ RC_GARD_REPOSITORY_FULL,
+ iv_maxGardRecords);
+ }
+ else
+ {
+ l_pRecord->iv_recordId = iv_nextGardRecordId++;
+ l_pRecord->iv_targetId = l_id;
+ // TODO Setup iv_cardMruSn or iv_chipMruEcid
+ l_pRecord->iv_errlogPlid = 0; // TODO Get PLID from ErrorLog
+ l_pRecord->iv_severity = i_severity;
+ l_pRecord->iv_padding[0] = 0;
+ l_pRecord->iv_padding[1] = 0;
+ l_pRecord->iv_padding[2] = 0;
+ l_pRecord->iv_gardTime = 0; // TODO Get epoch time
+ }
+ }
+ }
+
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::_clearGardRecords(const uint32_t i_recordId)
+{
+ errlHndl_t l_pErr = NULL;
+
+ l_pErr = _ensureGardRecordDataSetup();
+
+ if (l_pErr)
+ {
+ TRAC_ERR("Error from _ensureGardRecordDataSetup");
+ }
+ else
+ {
+ if (i_recordId == 0)
+ {
+ TRAC_INF("Clearing all GARD Records");
+
+ // Only clear valid GARD Records to avoid excessive PNOR access
+ for (uint32_t i = 0; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_recordId != 0)
+ {
+ memset(&(iv_pGardRecords[i]), 0, sizeof(GardRecord));
+ }
+ }
+ }
+ else
+ {
+ uint32_t i = 0;
+ for (; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_recordId == i_recordId)
+ {
+ TRAC_INF("Clearing GARD Record ID 0x%x", i_recordId);
+ memset(&(iv_pGardRecords[i]), 0, sizeof(GardRecord));
+ break;
+ }
+ }
+
+ if (i == iv_maxGardRecords)
+ {
+ TRAC_INF("No GARD Record ID 0x%x to clear", i_recordId);
+ }
+ }
+ }
+
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::_clearGardRecords(
+ const TARGETING::EntityPath & i_targetId)
+{
+ errlHndl_t l_pErr = NULL;
+
+ l_pErr = _ensureGardRecordDataSetup();
+
+ if (l_pErr)
+ {
+ TRAC_ERR("Error from _ensureGardRecordDataSetup");
+ }
+ else
+ {
+ bool l_gardRecordsCleared = false;
+
+ for (uint32_t i = 0; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_targetId == i_targetId)
+ {
+ DG_TRAC_TARGET(INFO_MRK "Clearing GARD Record for: ",
+ &i_targetId);
+ memset(&(iv_pGardRecords[i]), 0, sizeof(GardRecord));
+ l_gardRecordsCleared = true;
+ }
+ }
+
+ if (!l_gardRecordsCleared)
+ {
+ DG_TRAC_TARGET(INFO_MRK "No GARD Records to clear for: ",
+ &i_targetId);
+ }
+ }
+
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::_getGardRecords(const uint32_t i_recordId,
+ GardRecords_t & o_records)
+{
+ errlHndl_t l_pErr = NULL;
+ o_records.clear();
+
+ l_pErr = _ensureGardRecordDataSetup();
+
+ if (l_pErr)
+ {
+ TRAC_ERR("Error from _ensureGardRecordDataSetup");
+ }
+ else
+ {
+ if (i_recordId == 0)
+ {
+ TRAC_INF("Getting all GARD Records");
+ for (uint32_t i = 0; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_recordId != 0)
+ {
+ TRAC_INF("Getting GARD Record ID 0x%x",
+ iv_pGardRecords[i].iv_recordId);
+ o_records.push_back(iv_pGardRecords[i]);
+ }
+ }
+ }
+ else
+ {
+ uint32_t i = 0;
+ for (; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_recordId == i_recordId)
+ {
+ TRAC_INF("Getting GARD Record ID 0x%x", i_recordId);
+ o_records.push_back(iv_pGardRecords[i]);
+ break;
+ }
+ }
+
+ if (i == iv_maxGardRecords)
+ {
+ TRAC_INF("No GARD Record ID 0x%x to get", i_recordId);
+ }
+ }
+ }
+
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::_getGardRecords(
+ const TARGETING::EntityPath & i_targetId,
+ GardRecords_t & o_records)
+{
+ errlHndl_t l_pErr = NULL;
+ o_records.clear();
+
+ l_pErr = _ensureGardRecordDataSetup();
+
+ if (l_pErr)
+ {
+ TRAC_ERR("Error from _ensureGardRecordDataSetup");
+ }
+ else
+ {
+ bool l_gardRecordsGot = false;
+
+ for (uint32_t i = 0; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_targetId == i_targetId)
+ {
+ DG_TRAC_TARGET(INFO_MRK "Getting GARD Record for: ",
+ &i_targetId);
+ o_records.push_back(iv_pGardRecords[i]);
+ l_gardRecordsGot = true;
+ }
+ }
+
+ if (!l_gardRecordsGot)
+ {
+ DG_TRAC_TARGET(INFO_MRK "No GARD Records to get for: ",
+ &i_targetId);
+ }
+ }
+
+ return l_pErr;
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::_ensureGardRecordDataSetup()
+{
+ errlHndl_t l_pErr = NULL;
+
+ if (iv_pGardRecords == NULL)
+ {
+ PNOR::SectionInfo_t l_section;
+
+ // TODO Update when PNOR for GARD Records available (change HB_DATA)
+ l_pErr = PNOR::getSectionInfo(PNOR::HB_DATA, PNOR::SIDE_A, l_section);
+
+ if(l_pErr)
+ {
+ TRAC_ERR("Error getting GARD Record PNOR section info");
+ }
+ else
+ {
+ uint32_t l_numGardRecords = 0;
+ iv_pGardRecords = reinterpret_cast<GardRecord *>(l_section.vaddr);
+ iv_maxGardRecords = l_section.size / sizeof(GardRecord);
+
+ // TODO Remove this section when PNOR for GARD Records available
+ // For now, just use a buffer
+ iv_pGardRecords = new GardRecord[20];
+ memset(iv_pGardRecords, 0, sizeof(GardRecord) * 20);
+ iv_maxGardRecords = 20;
+ // TODO Remove this section when PNOR for GARD Records available
+
+ // Figure out the next GARD Record ID to use
+ for (uint32_t i = 0; i < iv_maxGardRecords; i++)
+ {
+ if (iv_pGardRecords[i].iv_recordId > iv_nextGardRecordId)
+ {
+ iv_nextGardRecordId = iv_pGardRecords[i].iv_recordId;
+ }
+
+ if (iv_pGardRecords[i].iv_recordId != 0)
+ {
+ l_numGardRecords++;
+ }
+ }
+
+ iv_nextGardRecordId++;
+
+ TRAC_INF("GARD Record data setup. MaxRecords: %d. NextID: %d. NumRecords: %d",
+ iv_maxGardRecords, iv_nextGardRecordId, l_numGardRecords);
+ }
+ }
+
+ return l_pErr;
+}
+
+}
diff --git a/src/usr/hwas/makefile b/src/usr/hwas/makefile
index 2542f0c39..f752aa88c 100644
--- a/src/usr/hwas/makefile
+++ b/src/usr/hwas/makefile
@@ -29,7 +29,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp
MODULE = hwas
-OBJS = hwas.o testHWP.o
+OBJS = hwas.o deconfigGard.o testHWP.o
SUBDIRS=test.d
diff --git a/src/usr/hwas/test/hwasGardTest.H b/src/usr/hwas/test/hwasGardTest.H
new file mode 100644
index 000000000..dda0de693
--- /dev/null
+++ b/src/usr/hwas/test/hwasGardTest.H
@@ -0,0 +1,920 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/hwas/test/hwasGardTest.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 _HWASGARDTEST_H
+#define _HWASGARDTEST_H
+
+/**
+ * @file hwasGardTest.H
+ *
+ * @brief Unit tests for HWAS Deconfigure and GARD functionality
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// CXXTEST
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <targeting/targetservice.H>
+#include <hwas/deconfigGard.H>
+#include <hwas/hwas_reasoncodes.H>
+
+class HwasGardTest: public CxxTest::TestSuite
+{
+public:
+
+ /**
+ * @brief Test getting all Deconfigure Records
+ */
+ void testDeconfigure1()
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure1: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::DeconfigureRecords_t l_records;
+
+ // Get all Deconfigure Records
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(NULL, l_records);
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ TS_FAIL("testDeconfigure1: Error from getDeconfigureRecords");
+ }
+ else
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure1: Success. %d records",
+ l_records.size());
+ }
+ }
+
+ /**
+ * @brief Test getting a Deconfigure Record for a specific Target
+ */
+ void testDeconfigure2()
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure2: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::DeconfigureRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Get any Deconfigure Record for the chip
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id,
+ l_records);
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ TS_FAIL("testDeconfigure2: Error from getDeconfigureRecords");
+ }
+ else
+ {
+ if (l_records.size() > 1)
+ {
+ TS_FAIL("testDeconfigure2: More than 1 record (%d) for chip",
+ l_records.size());
+ }
+ else
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure2: Success. %d records",
+ l_records.size());
+ }
+ }
+ }
+
+ /**
+ * @brief Test Deconfiguring a Target, getting the Deconfigure Record and
+ * clearing the Deconfigure Record
+ */
+ void testDeconfigure3()
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure3: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::DeconfigureRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Create an error log to pass to the deconfigureTarget function, this
+ // will never be committed.
+ errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_DECONFIG_GARD,
+ HWAS::RC_TARGET_NOT_DECONFIGURABLE);
+
+ do
+ {
+ // Get any existing Deconfigure Record for the chip
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id,
+ l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure3: Error from getDeconfigureRecords");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure3: Chip has existing Deconfigure Record, skipping test");
+ break;
+ }
+
+ // Get the original HWAS_STATE of the chip
+ TARGETING::HwasState l_origState =
+ l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>();
+
+ // Deconfigure the chip
+ l_pErr = HWAS::theDeconfigGard().deconfigureTarget(*l_pTarget,
+ l_pNewErr);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure3: Error from deconfigureTarget");
+ break;
+ }
+
+ // Get the new HWAS_STATE of the chip
+ TARGETING::HwasState l_state =
+ l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>();
+
+ if (l_state.functional)
+ {
+ TS_FAIL("testDeconfigure3: Chip functional after deconfigure");
+ // intentionally continue
+ }
+
+ // Get the Deconfigure Record for the chip
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id,
+ l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure3: Error from getDeconfigureRecords (2)");
+ break;
+ }
+
+ if (l_records.size() != 1)
+ {
+ TS_FAIL("testDeconfigure3: %d records for chip, expected 1",
+ l_records.size());
+ break;
+ }
+
+ // Reset the HWAS_STATE of the chip
+ l_pTarget->setAttr<TARGETING::ATTR_HWAS_STATE>(l_origState);
+
+ // Clear the Deconfigure Record
+ HWAS::theDeconfigGard()._clearDeconfigureRecords(&l_id);
+
+ // Get the Deconfigure Record for the chip
+ l_records.clear();
+
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id,
+ l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure3: Error from getDeconfigureRecords (3)");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_FAIL("testDeconfigure3: %d records for chip, expected 0",
+ l_records.size());
+ break;
+ }
+
+ TS_TRACE(INFO_MRK "testDeconfigure3: Success");
+ }
+ while (0);
+
+ delete l_pNewErr;
+ l_pNewErr = NULL;
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ }
+ }
+
+ /**
+ * @brief Test Deconfiguring a Target multiple times
+ */
+ void testDeconfigure4()
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure4: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::DeconfigureRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Create an error log to pass to the deconfigureTarget function, this
+ // will never be committed.
+ errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_DECONFIG_GARD,
+ HWAS::RC_TARGET_NOT_DECONFIGURABLE);
+
+ do
+ {
+ // Get any existing Deconfigure Record for the chip
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id,
+ l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure4: Error from getDeconfigureRecords");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_TRACE(INFO_MRK "testDeconfigure4: Chip has existing Deconfigure Record, skipping test");
+ break;
+ }
+
+ // Get the current HWAS_STATE of the chip
+ TARGETING::HwasState l_origState =
+ l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>();
+
+ // Deconfigure the chip
+ l_pErr = HWAS::theDeconfigGard().deconfigureTarget(*l_pTarget,
+ l_pNewErr);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure4: Error from deconfigureTarget");
+ break;
+ }
+
+ // Deconfigure the chip again
+ l_pErr = HWAS::theDeconfigGard().deconfigureTarget(*l_pTarget,
+ l_pNewErr);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure4: Error from deconfigureTarget (2)");
+ break;
+ }
+
+ // Get the new HWAS_STATE of the chip
+ TARGETING::HwasState l_state =
+ l_pTarget->getAttr<TARGETING::ATTR_HWAS_STATE>();
+
+ if (l_state.functional)
+ {
+ TS_FAIL("testDeconfigure4: Chip functional after deconfigure");
+ // intentionally continue
+ }
+
+ // Get the Deconfigure Record for the chip
+ l_pErr = HWAS::theDeconfigGard().getDeconfigureRecords(&l_id,
+ l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testDeconfigure4: Error from getDeconfigureRecords (2)");
+ break;
+ }
+
+ // The second Deconfigure should not have created a new record
+ if (l_records.size() != 1)
+ {
+ TS_FAIL("testDeconfigure4: %d records for chip, expected 1",
+ l_records.size());
+ break;
+ }
+
+ // Reset the HWAS_STATE of the chip
+ l_pTarget->setAttr<TARGETING::ATTR_HWAS_STATE>(l_origState);
+
+ // Clear the Deconfigure Record
+ HWAS::theDeconfigGard()._clearDeconfigureRecords(&l_id);
+
+ TS_TRACE(INFO_MRK "testDeconfigure4: Success");
+ }
+ while (0);
+
+ delete l_pNewErr;
+ l_pNewErr = NULL;
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ }
+ }
+
+ /**
+ * @brief Test getting all GARD Records
+ */
+ void testGard1()
+ {
+ TS_TRACE(INFO_MRK "testGard1: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(0, l_records);
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ TS_FAIL("testGard1: Error from getGardRecords");
+ }
+ else
+ {
+ TS_TRACE(INFO_MRK "testGard1: Success. %d records",
+ l_records.size());
+ }
+ }
+
+ /**
+ * @brief Test getting GARD Records with a bad record ID).
+ */
+ void testGard2()
+ {
+ TS_TRACE(INFO_MRK "testGard2: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(0x12345678, l_records);
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ TS_FAIL("testGard2: Error from getGardRecords");
+ }
+ else
+ {
+ if (l_records.size())
+ {
+ TS_FAIL("testGard2: %d records found for bad ID",
+ l_records.size());
+ }
+ else
+ {
+ TS_TRACE(INFO_MRK "testGard2: Success");
+ }
+ }
+ }
+
+ /**
+ * @brief Test getting GARD Records for a specific target
+ */
+ void testGard3()
+ {
+ TS_TRACE(INFO_MRK "testGard3: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+
+ // Get all GARD Records for the Target
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ TS_FAIL("testGard3: Error from getGardRecords");
+ }
+ else
+ {
+ TS_TRACE(INFO_MRK "testGard3: Success. %d records",
+ l_records.size());
+ }
+ }
+
+ /**
+ * @brief Test creating a GARD Record, getting the GARD Record and
+ * clearing the GARD Record
+ */
+ void testGard4()
+ {
+ TS_TRACE(INFO_MRK "testGard4: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Create an error log to pass to the createGardRecord function, this
+ // will never be committed.
+ errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_DECONFIG_GARD,
+ HWAS::RC_TARGET_NOT_DECONFIGURABLE);
+
+ do
+ {
+ // Get any existing GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard4: Error from getGardRecords");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_TRACE(INFO_MRK "testGard4: Chip has %d existing Gard Records, skipping test",
+ l_records.size());
+ break;
+ }
+
+ // Create a GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard4: Error from createGardRecord");
+ break;
+ }
+
+ // Get the GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard4: Error from getGardRecords (2)");
+ break;
+ }
+
+ if (l_records.size() != 1)
+ {
+ TS_FAIL("testGard4: %d records for chip, expected 1",
+ l_records.size());
+ break;
+ }
+
+ if (l_records[0].iv_severity !=
+ HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE)
+ {
+ TS_FAIL("testGard4: Record severity %d, expected predictive",
+ l_records[0].iv_severity);
+ break;
+ }
+
+ // Clear the GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_id);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard4: Error from clearGardRecords");
+ break;
+ }
+
+ // Get the GARD Records for the chip
+ l_records.clear();
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard4: Error from getGardRecords (3)");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_FAIL("testGard4: %d records for chip, expected 0",
+ l_records.size());
+ break;
+ }
+
+ TS_TRACE(INFO_MRK "testGard4: Success");
+ }
+ while (0);
+
+ delete l_pNewErr;
+ l_pNewErr = NULL;
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ }
+ }
+
+ /**
+ * @brief Test creating a GARD Record for a Target multiple times
+ */
+ void testGard5()
+ {
+ TS_TRACE(INFO_MRK "testGard5: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Create an error log to pass to the createGardRecord function, this
+ // will never be committed.
+ errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_DECONFIG_GARD,
+ HWAS::RC_TARGET_NOT_DECONFIGURABLE);
+
+ do
+ {
+ // Get any existing GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard5: Error from getGardRecords");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_TRACE(INFO_MRK "testGard5: Chip has %d existing Gard Records, skipping test",
+ l_records.size());
+ break;
+ }
+
+ // Create a GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard5: Error from createGardRecord");
+ break;
+ }
+
+ // Create another GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_FATAL);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard5: Error from createGardRecord (2)");
+ break;
+ }
+
+ // Get the GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard5: Error from getGardRecords (2)");
+ break;
+ }
+
+ if (l_records.size() != 2)
+ {
+ TS_FAIL("testGard5: %d records for chip, expected 2",
+ l_records.size());
+ break;
+ }
+
+ // Clear the GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_id);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard5: Error from clearGardRecords");
+ break;
+ }
+
+ // Get the GARD Records for the chip
+ l_records.clear();
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard5: Error from getGardRecords (3)");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_FAIL("testGard5: %d records for chip, expected 0",
+ l_records.size());
+ break;
+ }
+
+ TS_TRACE(INFO_MRK "testGard5: Success");
+ }
+ while (0);
+
+ delete l_pNewErr;
+ l_pNewErr = NULL;
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ }
+ }
+
+ /**
+ * @brief Test getting and clearing GARD Records by recordID
+ */
+ void testGard6()
+ {
+ TS_TRACE(INFO_MRK "testGard6: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Create an error log to pass to the createGardRecord function, this
+ // will never be committed.
+ errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_DECONFIG_GARD,
+ HWAS::RC_TARGET_NOT_DECONFIGURABLE);
+
+ do
+ {
+ // Get any existing GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from getGardRecords");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_TRACE(INFO_MRK "testGard6: Chip has %d existing Gard Records, skipping test",
+ l_records.size());
+ break;
+ }
+
+ // Create a GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from createGardRecord");
+ break;
+ }
+
+ // Create another GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_FATAL);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from createGardRecord (2)");
+ break;
+ }
+
+ // Get the GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from getGardRecords (2)");
+ break;
+ }
+
+ if (l_records.size() != 2)
+ {
+ TS_FAIL("testGard6: %d records for chip, expected 2",
+ l_records.size());
+ break;
+ }
+
+ // Get the first GARD Record for the chip by Record ID
+ uint32_t l_recordID = l_records[0].iv_recordId;
+ l_records.clear();
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_recordID,
+ l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from getGardRecords (3)");
+ break;
+ }
+
+ if (l_records.size() != 1)
+ {
+ TS_FAIL("testGard6: %d records for chip, expected 1",
+ l_records.size());
+ break;
+ }
+
+ // Clear the first GARD Record for the chip by Record ID
+ l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_recordID);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from clearGardRecords");
+ break;
+ }
+
+ // Get the GARD Records for the chip
+ l_records.clear();
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(l_id, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from getGardRecords (4)");
+ break;
+ }
+
+ if (l_records.size() != 1)
+ {
+ TS_FAIL("testGard6: %d records for chip, expected 1 (2)",
+ l_records.size());
+ break;
+ }
+
+ // Clear the GARD Records for the chip
+ l_pErr = HWAS::theDeconfigGard().clearGardRecords(l_id);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard6: Error from clearGardRecords");
+ break;
+ }
+
+ TS_TRACE(INFO_MRK "testGard6: Success");
+ }
+ while (0);
+
+ delete l_pNewErr;
+ l_pNewErr = NULL;
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ }
+ }
+
+ /**
+ * @brief Test getting and clearing all GARD Records
+ */
+ void testGard7()
+ {
+ TS_TRACE(INFO_MRK "testGard7: Started");
+
+ errlHndl_t l_pErr = NULL;
+ HWAS::DeconfigGard::GardRecords_t l_records;
+
+ // Get the master processor chip
+ TARGETING::Target* l_pTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(l_pTarget);
+ TARGETING::EntityPath l_id =
+ l_pTarget->getAttr<TARGETING::ATTR_PHYS_PATH>();
+
+ // Create an error log to pass to the createGardRecord function, this
+ // will never be committed.
+ errlHndl_t l_pNewErr = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HWAS::MOD_DECONFIG_GARD,
+ HWAS::RC_TARGET_NOT_DECONFIGURABLE);
+
+ do
+ {
+ // Get all existing GARD Records
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(0, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard7: Error from getGardRecords");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_TRACE(INFO_MRK "testGard7: %d existing Gard Records, skipping test",
+ l_records.size());
+ break;
+ }
+
+ // Create a GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_PREDICTIVE);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard7: Error from createGardRecord");
+ break;
+ }
+
+ // Create another GARD Record for the chip
+ l_pErr = HWAS::theDeconfigGard().
+ createGardRecord(*l_pTarget, l_pNewErr,
+ HWAS::DeconfigGard::GARD_SEVERITY_FATAL);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard7: Error from createGardRecord (2)");
+ break;
+ }
+
+ // Clear all GARD Records
+ l_pErr = HWAS::theDeconfigGard().clearGardRecords(0);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard7: Error from clearGardRecords");
+ break;
+ }
+
+ // Get the GARD Records
+ l_records.clear();
+
+ l_pErr = HWAS::theDeconfigGard().getGardRecords(0, l_records);
+
+ if (l_pErr)
+ {
+ TS_FAIL("testGard7: Error from getGardRecords (2)");
+ break;
+ }
+
+ if (l_records.size() != 0)
+ {
+ TS_FAIL("testGard7: %d records for chip, expected 0",
+ l_records.size());
+ break;
+ }
+
+ TS_TRACE(INFO_MRK "testGard7: Success");
+ }
+ while (0);
+
+ delete l_pNewErr;
+ l_pNewErr = NULL;
+
+ if (l_pErr)
+ {
+ errlCommit(l_pErr);
+ }
+ }
+};
+
+#endif
diff --git a/src/usr/targeting/xmltohb/attribute_types.xml b/src/usr/targeting/xmltohb/attribute_types.xml
index 343d791ce..212c69b30 100644
--- a/src/usr/targeting/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/xmltohb/attribute_types.xml
@@ -844,6 +844,7 @@
</complexType>
<persistency>volatile</persistency>
<readable/>
+ <writeable/>
</attribute>
<attribute>
@@ -935,5 +936,17 @@
<readable/>
</attribute>
+<attribute>
+ <id>DECONFIG_GARDABLE</id>
+ <description>If the Target is Deconfigurable and GARDable</description>
+ <simpleType>
+ <uint8_t>
+ <default>0</default>
+ </uint8_t>
+ </simpleType>
+ <persistency>non-volatile</persistency>
+ <readable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/xmltohb/target_types.xml b/src/usr/targeting/xmltohb/target_types.xml
index 2b0cbfe6c..ea371bd9c 100644
--- a/src/usr/targeting/xmltohb/target_types.xml
+++ b/src/usr/targeting/xmltohb/target_types.xml
@@ -39,6 +39,10 @@
<id>PRIMARY_CAPABILITIES</id>
</attribute>
<attribute><id>HWAS_STATE</id></attribute>
+ <attribute>
+ <id>DECONFIG_GARDABLE</id>
+ <default>0</default>
+ </attribute>
</targetType>
<targetType>
@@ -102,6 +106,10 @@
<attribute>
<id>FSI_OPTION_FLAGS</id>
</attribute>
+ <attribute>
+ <id>DECONFIG_GARDABLE</id>
+ <default>1</default>
+ </attribute>
</targetType>
<targetType>
@@ -155,6 +163,10 @@
<field><id>reserved</id><value>0</value></field>
</default>
</attribute>
+ <attribute>
+ <id>DECONFIG_GARDABLE</id>
+ <default>1</default>
+ </attribute>
</targetType>
<targetType>
OpenPOWER on IntegriCloud