diff options
| author | Mike Jones <mjjones@us.ibm.com> | 2011-10-26 14:59:19 -0500 | 
|---|---|---|
| committer | MIKE J. JONES <mjjones@us.ibm.com> | 2011-11-01 12:14:11 -0500 | 
| commit | 5554e9d53859a91b39b01c8f789fe536e4688ecb (patch) | |
| tree | 8f24ea04634c7aed7e34d7ce6a26326c0e954e8d /src | |
| parent | 14cd4e689a68a7440309090d0a6f82d25f8b6984 (diff) | |
| download | blackbird-hostboot-5554e9d53859a91b39b01c8f789fe536e4688ecb.tar.gz blackbird-hostboot-5554e9d53859a91b39b01c8f789fe536e4688ecb.zip | |
Initial Deconfigure and GARD support
Change-Id: I8448480627ad478e8e16377027137e6df410053f
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/460
Tested-by: Jenkins Server
Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/usr/hwas/deconfigGard.H | 453 | ||||
| -rw-r--r-- | src/include/usr/hwas/hwas_reasoncodes.H | 43 | ||||
| -rw-r--r-- | src/lib/sync.C | 2 | ||||
| -rw-r--r-- | src/usr/hwas/deconfigGard.C | 692 | ||||
| -rw-r--r-- | src/usr/hwas/makefile | 2 | ||||
| -rw-r--r-- | src/usr/hwas/test/hwasGardTest.H | 920 | ||||
| -rw-r--r-- | src/usr/targeting/xmltohb/attribute_types.xml | 13 | ||||
| -rw-r--r-- | src/usr/targeting/xmltohb/target_types.xml | 12 | 
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> | 

