Esempio n. 1
0
void EntityPath::dump() const
{
    #define TARG_FN "dump()"

    char  l_pBuf[200];
    memset(l_pBuf,'\0',200);
    char* l_pCursor = l_pBuf;
    l_pCursor+=sprintf(l_pCursor,"%s:",pathTypeAsString());
    for(uint32_t i=0; i<size(); ++i)
    {
        l_pCursor+=sprintf(l_pCursor,"/%s%d",
            pathElementTypeAsString(operator[](i).type),
            operator[](i).instance);
    }

    TRACFBIN(g_trac_targeting,
             "EntityPath",
             l_pBuf,
             l_pCursor-l_pBuf);

    #undef TARG_FN
}
Esempio n. 2
0
//*****************************************************************************
// resetBackupTopology
//*****************************************************************************
errlHndl_t resetBackupTopology(
                              uint32_t i_oscPos,
                              const TARGETING::TargetHandle_t& i_procOscTgt,
                              const TARGETING::TargetHandleList& i_badChipList,
                              bool i_informPhyp)
{
    TOD_ENTER("resetBackupTopology");
    errlHndl_t l_err = nullptr;

    // Put the handle to the firmware_request request struct
    // out here so it is easier to free later
    hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr;
    hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr;

    do
    {
        if ((nullptr == g_hostInterfaces) ||
            (nullptr == g_hostInterfaces->firmware_request))
        {
            TOD_ERR("resetBackupTopology: "
                    "Hypervisor firmware_request interface not linked");

            /*@
             * @errortype
             * @severity     ERRL_SEV_UNRECOVERABLE
             * @moduleid     TOD_RT_TOPOLOGY_RESET_BACKUP
             * @reasoncode   TOD_RT_NULL_FIRMWARE_REQUEST_PTR
             * @userdata1    None
             * @userdata2    None
             * @devdesc      Host interfaces are not initialized
             * @custdesc     An internal error occurred. This will
             *               force the Time of Day function to run
             *               with complete redundancy.
             */
            l_err = new ErrlEntry( ERRL_SEV_UNRECOVERABLE,
                                   TOD_RT_TOPOLOGY_RESET_BACKUP,
                                   TOD_RT_NULL_FIRMWARE_REQUEST_PTR,
                                   0, 0, true);

            break;
        }

        // The format of the data to be sent, according to the document
        // "Handle PRD Request for resetting backup TOD topology" is as follows
        // All data members below are 4 bytes long (32 bits)
        // Ordinal ID - 0xFFFFFFFF means no OSC to be avoided
        // HUID of the node - This field should be considered only if Ordinal
        //                    ID is NOT set to 0xFFFFFFFF otherwise it is set
        //                    to 0
        // HUID of the first processor
        // HUID of the second processor, etc

        // Check if we get conflicting data, if so send a Trace out
        if ((0xFFFFFFFF == i_oscPos) && (nullptr != i_procOscTgt))
        {
           TOD_ERR("Conflicting input data, input oscillator position "
                   "(i_oscPos) has value 0xFFFFFFFF, meaning no oscillator "
                   "to be avoided but input oscillator target (i_procOscTgt) "
                   "has a valid value" );
        }
        else if ((0xFFFFFFFF != i_oscPos) && (nullptr == i_procOscTgt))
        {
           TOD_ERR("Conflicting input data, input oscillator position "
                   "(i_oscPos) has value 0x%X, meaning avoid oscillator "
                   "but input oscillator target (i_procOscTgt) "
                   "has a NULL value", i_oscPos);
        }
        // Flag to determine if the OSC data will be added to the data
        bool l_addOscData = (0xFFFFFFFF != i_oscPos) &&
                            (nullptr != i_procOscTgt);

        // Default the request data size to the size of the
        // GenericFspMboxMessage_t minus the size of the
        // GenericFspMboxMessage_t's data.  The size of the
        // GenericFspMboxMessage_t's data will be added later
        uint32_t l_req_data_size = sizeof(GenericFspMboxMessage_t) -
                                   sizeof(GenericFspMboxMessage_t::data);

        // Add to the request data size iff there is data needing to be passed
        if (i_badChipList.size() > 0)
        {
            // if the bad chip list has any items then increase size to
            // accommodate for an ordinal ID and a HUID, regardless if
            // they have relevant data or not, because they are expected
            // before the HUID list.
            l_req_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t)) +
                               (i_badChipList.size() * sizeof(uint32_t));
        }
        else if (l_addOscData)
        {
            // if there is a valid OSC then accommodate for an ordinal ID
            // and HUID of node, but don't need space for HUID list because,
            // if we are here, the list is empty
            l_req_data_size += (MSG_OSC_SIZE_OF_DETAILS * sizeof(uint32_t));
        }

        // The request data size must be at a minimum the size of the
        // FSP generic message (sizeof(GenericFspMboxMessage_t))
        if (l_req_data_size < sizeof(GenericFspMboxMessage_t))
        {
            l_req_data_size = sizeof(GenericFspMboxMessage_t);
        }

        // Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg which
        // means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to
        // the previous calculated request data size
        uint64_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE +
                                     l_req_data_size;

        // Create the firmware_request request struct to send data
        l_req_fw_msg =
                   (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size);

        // Initialize the firmware_request request struct
        l_req_fw_msg->generic_msg.initialize();

        // Populate the firmware_request request struct with given data
        l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ;
        l_req_fw_msg->generic_msg.dataSize = l_req_data_size;
        l_req_fw_msg->generic_msg.msgq = MBOX::FSP_TOD_MSGQ;
        l_req_fw_msg->generic_msg.msgType = (false == i_informPhyp ?
                   GenericFspMboxMessage_t::MSG_TOD_BACKUP_RESET:
                   GenericFspMboxMessage_t::MSG_TOD_BACKUP_RESET_INFORM_PHYP);
        l_req_fw_msg->generic_msg.__req = GenericFspMboxMessage_t::REQUEST;

        // A convenient way to populate the data
        uint32_t* l_dataPtr =
                reinterpret_cast<uint32_t*>(&(l_req_fw_msg->generic_msg.data));

        if (i_badChipList.size() > 0)
        {
            // set the ordinal ID
            l_dataPtr[MSG_OSC_ORDINAL_ID_LOC] = i_oscPos;

            // attach the HUIDs from bad chip list to end of struct
            size_t i = MSG_OSC_HUIDS_LOC;
            for (auto l_target : i_badChipList)
            {
                l_dataPtr[i++] = GETHUID(l_target);
            }
        }

        // Set the HUID of the ordinal node if need be
        if (l_addOscData)
        {
            // set the ordinal ID
            l_dataPtr[MSG_OSC_ORDINAL_ID_LOC] = i_oscPos;

            // Get the parent node target
            TARGETING::TargetHandleList l_list;
            TARGETING::targetService().getAssociated(l_list,
                                           i_procOscTgt,
                                           TARGETING::TargetService::PARENT,
                                           TARGETING::TargetService::IMMEDIATE);

            if (l_list.size() == 1)
            {
               l_dataPtr[MSG_OSC_ORDINAL_NODE_HUID_LOC] = GETHUID(l_list[0]);
            }
            else
            {
                /*@
                 * @errortype
                 * @severity     ERRL_SEV_UNRECOVERABLE
                 * @moduleid     TOD_RT_TOPOLOGY_RESET_BACKUP
                 * @reasoncode   TOD_INVALID_TARGET
                 * @userdata1    The number of parents found osc target
                 * @userdata2    None
                 * @devdesc      No/Multiple parent(s) found for
                 *               processor osc target
                 * @custdesc     An internal error occurred. This will
                 *               force the Time of Day function to run
                 *               with complete redundancy.
                 */
                l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
                                      TOD_RT_TOPOLOGY_RESET_BACKUP,
                                      TOD_INVALID_TARGET,
                                      l_list.size(), 0, true);

                break;
            }
        }

        // Create the firmware_request response struct to receive data
        // NOTE: For messages to the FSP the response size must match
        // the request size
        uint64_t l_resp_fw_msg_size = l_req_fw_msg_size;
        l_resp_fw_msg =
                    (hostInterfaces::hbrt_fw_msg *)malloc(l_resp_fw_msg_size);
        memset(l_resp_fw_msg, 0, l_resp_fw_msg_size);

        // Trace out the request structure
        TRACFBIN(ISTEPS_TRACE::g_trac_isteps_trace,
                 INFO_MRK"TOD::Sending firmware_request",
                 l_req_fw_msg,
                 l_req_fw_msg_size);

        // Make the firmware_request call
        l_err = firmware_request_helper(l_req_fw_msg_size,
                                        l_req_fw_msg,
                                        &l_resp_fw_msg_size,
                                        l_resp_fw_msg);

        if (l_err)
        {
            break;
        }
    } while (0);

    // Release the firmware messages
    free(l_req_fw_msg);
    free(l_resp_fw_msg);
    l_req_fw_msg = l_resp_fw_msg = nullptr;

    TOD_EXIT("resetBackupTopology");
    return l_err;
} // end resetBackupTopology
Esempio n. 3
0
//*****************************************************************************
// readTodProcDataFromFile
//*****************************************************************************
errlHndl_t readTodProcDataFromFile(TodChipDataContainer& o_todChipData)
{
    TOD_ENTER("readTodProcDataFromFile");
    errlHndl_t l_err = nullptr;

    // Put the handle to the firmware messages out here
    // so it is easier to free later
    hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr;
    hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr;

    // clear the out data, regardless of the code to follow
    o_todChipData.clear();

    do
    {
        if ((nullptr == g_hostInterfaces) ||
            (nullptr == g_hostInterfaces->firmware_request))
        {
            TOD_ERR("readTodProcDataFromFile: "
                    "Hypervisor firmware_request interface not linked");

            /*@
             * @errortype
             * @severity     ERRL_SEV_UNRECOVERABLE
             * @moduleid     TOD_RT_TOPOLOGY_DATA
             * @reasoncode   TOD_RT_NULL_FIRMWARE_REQUEST_PTR
             * @devdesc      Host interfaces are not initialized
             * @custdesc     An internal error occurred. This will
             *               force the Time of Day function to run
             *               with complete redundancy.
             */
            l_err = new ErrlEntry( ERRL_SEV_UNRECOVERABLE,
                                   TOD_RT_TOPOLOGY_DATA,
                                   TOD_RT_NULL_FIRMWARE_REQUEST_PTR,
                                   0, 0, true);

            break;
        }

        // Default the response data size to the size of the
        // GenericFspMboxMessage_t minus the size of the
        // GenericFspMboxMessage_t's data.  The size of the
        // GenericFspMboxMessage_t's data will be added later
        uint32_t l_resp_data_size = sizeof(GenericFspMboxMessage_t) -
                                    sizeof(GenericFspMboxMessage_t::data);

        // Get the number of TodChipData items that will be returned.
        uint32_t l_nTodChips = TodSvcUtil::getMaxProcsOnSystem();

        // Add to the response data size iff there is data needing to be passed
        l_resp_data_size += (l_nTodChips * sizeof(TodChipData));

        // The response data size must be at a minimum the size of the
        // FSP generic message (sizeof(GenericFspMboxMessage_t))
        if (l_resp_data_size < sizeof(GenericFspMboxMessage_t))
        {
            l_resp_data_size = sizeof(GenericFspMboxMessage_t);
        }

        // Calculate the TOTAL size of hostInterfaces::hbrt_fw_msg which
        // means only adding hostInterfaces::HBRT_FW_MSG_BASE_SIZE to
        // the previous calculated response data size
        uint64_t l_resp_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE +
                                      l_resp_data_size;

        // Create the firmware_request response struct to receive data
        l_resp_fw_msg =
                     (hostInterfaces::hbrt_fw_msg *)malloc(l_resp_fw_msg_size);
        memset(l_resp_fw_msg, 0, l_resp_fw_msg_size);

        // Create the firmware_request request struct to send data
        uint64_t l_req_fw_msg_size = l_resp_fw_msg_size;
        l_req_fw_msg =
                   (hostInterfaces::hbrt_fw_msg *)malloc(l_req_fw_msg_size);

        // Initialize the firmware_request request struct
        l_req_fw_msg->generic_msg.initialize();

        // Populate the firmware_request request struct with given data
        l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ;
        l_req_fw_msg->generic_msg.msgq = MBOX::FSP_TOD_MSGQ;
        l_req_fw_msg->generic_msg.msgType =
                           GenericFspMboxMessage_t::MSG_TOD_TOPOLOGY_DATA;
        l_req_fw_msg->generic_msg.__req = GenericFspMboxMessage_t::REQUEST;

        // Trace out the request structure
        TRACFBIN(ISTEPS_TRACE::g_trac_isteps_trace,
                 INFO_MRK"TOD::Sending firmware_request",
                 l_req_fw_msg,
                 l_req_fw_msg_size);

        // Make the firmware_request call
        l_err = firmware_request_helper(l_req_fw_msg_size,
                                        l_req_fw_msg,
                                        &l_resp_fw_msg_size,
                                        l_resp_fw_msg);

        if (l_err)
        {
            break;
        }

        // If we are here, then this was no error retrieving the data. Now,
        // just get the data from the returned struct and pass back to caller
        // Get a pointer to the data
        TodChipData* l_todChipData =
                   (TodChipData*)(&(l_resp_fw_msg->generic_msg.data));

        // Gather the data into the container provided
        for (size_t i = 0; i < l_nTodChips; ++i)
        {
            o_todChipData.push_back(l_todChipData[i]);
        }
    }
    while (0);

    // Release the firmware messages
    free(l_req_fw_msg);
    free(l_resp_fw_msg);
    l_req_fw_msg = l_resp_fw_msg = nullptr;

    TOD_EXIT("readTodProcDataFromFile");
    return l_err;
} // end readTodProcDataFromFile
Esempio n. 4
0
// ------------------------------------------------------------------
// sendMboxWriteMsg
// ------------------------------------------------------------------
errlHndl_t sendMboxWriteMsg ( size_t i_numBytes,
                              void * i_data,
                              TARGETING::Target * i_target,
                              VPD_MSG_TYPE i_type,
                              VpdWriteMsg_t& i_record )
{
    errlHndl_t l_err = NULL;
    msg_t* msg = NULL;

    TRACSSCOMP( g_trac_vpd,
                ENTER_MRK"sendMboxWriteMsg()" );

    do
    {
        //Create a mailbox message to send to FSP
        msg = msg_allocate();
        msg->type = i_type;
        msg->data[0] = i_record.data0;
        msg->data[1] = i_numBytes;

        //Copy the data into the message
        msg->extra_data = malloc( i_numBytes );
        memcpy( msg->extra_data, i_data, i_numBytes );

        TRACFCOMP( g_trac_vpd,
                   INFO_MRK"sendMboxWriteMsg: Send msg to FSP to write VPD type %.8X, record %d, offset 0x%X",
                   i_type,
                   i_record.rec_num,
                   i_record.offset );

        //We only send VPD update when we have SP Base Services
        if( !INITSERVICE::spBaseServicesEnabled() )
        {
            TRACFCOMP(g_trac_vpd, INFO_MRK "No SP Base Services, skipping VPD write");
            TRACFBIN( g_trac_vpd, "msg=", msg, sizeof(msg_t) );
            TRACFBIN( g_trac_vpd, "extra=", msg->extra_data, i_numBytes );
            free (msg->extra_data);
            msg_free( msg );

            break;
        }

        l_err = MBOX::send( MBOX::FSP_VPD_MSGQ, msg );
        if( l_err )
        {
            TRACFCOMP(g_trac_vpd,
                      ERR_MRK "Failed sending VPD to FSP for %.8X",
                      TARGETING::get_huid(i_target));
            ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_err);

            l_err->collectTrace("VPD",1024);
            if( VPD_WRITE_DIMM == i_type )
            {
                l_err->collectTrace("SPD",1024);
            }

            // just commit the log and move on, nothing else to do
            errlCommit( l_err, VPD_COMP_ID );
            l_err = NULL;

            free( msg->extra_data );
            msg->extra_data = NULL;
            msg_free( msg );
        }
    } while( 0 );

    TRACSSCOMP( g_trac_vpd,
                EXIT_MRK"sendMboxWriteMsg()" );

    return l_err;
}
Esempio n. 5
0
    //**************************************************************************
    // FREQVOLTSVC::setWofFrequencyUpliftSelected
    //**************************************************************************
    void setWofFrequencyUpliftSelected()
    {

        // get mrw data
        TARGETING::Target* l_pTopLevel = NULL;
        (void)TARGETING::targetService().getTopLevelTarget(l_pTopLevel);
        ATTR_WOF_FREQUENCY_UPLIFT_type l_upliftTable = {{{0}}};
        ATTR_WOF_PROC_SORT_type l_procSortTable = {{0}};
        ATTR_NOMINAL_FREQ_MHZ_type l_sysNomFreqMhz =
            l_pTopLevel->getAttr<ATTR_NOMINAL_FREQ_MHZ>();
        ATTR_WOF_ENABLED_type l_wofEnabled = l_pTopLevel->getAttr
                                           < TARGETING::ATTR_WOF_ENABLED > ();

        // tryGetAttr used due to complex data type. Expected to always work.
        if (!l_pTopLevel->tryGetAttr<ATTR_WOF_FREQUENCY_UPLIFT>(l_upliftTable))
        {
            // The zero initialized values will be used for the select array
            TRACFCOMP(g_fapiTd, "Failed to get ATTR_WOF_FREQUENCY_UPLIFT");
        }
        // tryGetAttr used due to complex data type. Expected to always work.
        if ( !l_pTopLevel->tryGetAttr<ATTR_WOF_PROC_SORT>(l_procSortTable))
        {
            // Not finding the sort table will result in not finding the index
            // which will result in a log later
            TRACFCOMP(g_fapiTd, "Failed to get ATTR_WOF_PROC_SORT");
        }

        // get the list of procs
        TargetHandleList l_procTargetList;
        getAllChips(l_procTargetList, TYPE_PROC, true);

        // for each proc, fill in Wof Frequency Uplift Selected attribute
        for (TargetHandleList::const_iterator
                l_proc_iter = l_procTargetList.begin();
                l_proc_iter != l_procTargetList.end();
                ++l_proc_iter)
        {
            TARGETING::Target * l_pProcTarget = *l_proc_iter;

            // find number of active cores
            TARGETING::TargetHandleList l_presCoreList;
            getChildAffinityTargetsByState( l_presCoreList,
                      const_cast<TARGETING::Target*>(l_pProcTarget),
                      TARGETING::CLASS_UNIT,
                      TARGETING::TYPE_CORE,
                      TARGETING::UTIL_FILTER_PRESENT);
            uint8_t l_activeCores = l_presCoreList.size();
            TRACDCOMP(g_fapiTd, "setWofFrequencyUpliftSelected:"
                            " number of active cores  is %d ",
                            l_activeCores);

            // find WOF index. For example:
            // ATTR_WOF_PROC_SORT =
            // Cores/Nom Freq/Index
            //   8    3325     1
            //   10   2926     2
            //   12   2561     3
            //   12   3093     4
            // Use WOF index=3 for active cores=12 && nom freq=2561
            uint8_t l_wofIndex = 0;
            for (uint8_t i=0;i<4;i++)
            {
                if ( (l_activeCores   == l_procSortTable[i][0]) &&
                     (l_sysNomFreqMhz == l_procSortTable[i][1]) )
                {
                   l_wofIndex = l_procSortTable[i][2];
                   break;
                }
            }
            TRACDCOMP(g_fapiTd, "setWofFrequencyUpliftSelected:"
                            " WOF index is %d ",
                            l_wofIndex);
            // validate WOF index
            ATTR_WOF_FREQUENCY_UPLIFT_SELECTED_type l_selectedTable = {{0}};
            if ( (!l_wofIndex) || (l_wofIndex > 4))
            {
                if (l_wofEnabled) // log error if WOF enabled
                {
                    TRACFCOMP(g_fapiTd, "setWofFrequencyUpliftSelected:"
                        " No WOF table index match found HUID:0x%08X"
                        " active cores=%d, nom freq=%d, index=%d",
                        l_pProcTarget->getAttr<TARGETING::ATTR_HUID>(),
                        l_activeCores,
                        l_sysNomFreqMhz,
                        l_wofIndex);

                    errlHndl_t l_err = NULL;
                    /*@
                     * @errortype
                     * @moduleid         fapi::MOD_GET_WOF_FREQ_UPLIFT_SELECTED
                     * @reasoncode       fapi::RC_INVALID_WOF_INDEX
                     * @userdata1[0:31]  Proc HUID
                     * @userdata1[32:63] WOF Freq Uplift Index
                     * @userdata2[0:31]  Number of active cores
                     * @userdata2[32:63] Nomimal Frequency
                     * @devdesc          When WOF is enabled, the WOF Freq
                     *                   Uplift index should be 1,2,3, or 4
                     */
                    l_err =
                        new  ERRORLOG::ErrlEntry(
                             ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                             fapi::MOD_GET_WOF_FREQ_UPLIFT_SELECTED,
                             fapi::RC_INVALID_WOF_INDEX,
                             TWO_UINT32_TO_UINT64(
                                 l_pProcTarget->getAttr<TARGETING::ATTR_HUID>(),
                                 l_wofIndex),
                             TWO_UINT32_TO_UINT64(
                                 l_activeCores,
                                 l_sysNomFreqMhz));

                    // Callout HW as WOF mrw data is incorrect
                    l_err->addHwCallout(l_pProcTarget, HWAS::SRCI_PRIORITY_MED,
                                         HWAS::NO_DECONFIG, HWAS::GARD_NULL);

                    // Include WOF processor sort table
                    TRACFBIN (g_fapiTd,
                              "WOF processor sort table",
                              l_procSortTable,
                              sizeof(l_procSortTable));
                    l_err->collectTrace(FAPI_TRACE_NAME);

                    // log error and keep going
                    errlCommit(l_err,HWPF_COMP_ID);
                }
                // make sure zeros are set in the selected table attribute
                memset(l_selectedTable,
                       0,
                       sizeof(l_selectedTable));
            }
            else
            {
                // use index to set Wof Frequency Uplift selected attribute
                // note: mrw index is 1 based
                memcpy(l_selectedTable,
                       &l_upliftTable[l_wofIndex-1][0][0],
                       sizeof(l_selectedTable));
            }
            if (!l_pProcTarget->trySetAttr<ATTR_WOF_FREQUENCY_UPLIFT_SELECTED>
                                             (l_selectedTable))
            {
                //unlikely, crash
                TRACFCOMP(g_fapiTd,
                            "Failed to set ATTR_WOF_FREQUENCY_UPLIFT_SELECTED");
                assert(0);
            }
        }
        return;
    }
Esempio n. 6
0
/**
 * @brief Check flash image SHA512 hash value of each explorer chip
 *        and update the flash if it does not match the SHA512 hash
 *        of the image in PNOR.
 *
 * @param[out] o_stepError Error handle for logging istep failures
 *
 */
void updateAll(IStepError& o_stepError)
{
    bool l_imageLoaded = false;
    errlHndl_t l_err = nullptr;
    bool l_rebootRequired = false;

    // Get a list of OCMB chips
    TARGETING::TargetHandleList l_ocmbTargetList;
    getAllChips(l_ocmbTargetList, TYPE_OCMB_CHIP);

    TRACFCOMP(g_trac_expupd, ENTER_MRK
              "updateAll: %d ocmb chips found",
              l_ocmbTargetList.size());

    do
    {
        // If no OCMB chips exist, we're done.
        if(l_ocmbTargetList.size() == 0)
        {
            break;
        }

        // Read explorer fw image from pnor
        PNOR::SectionInfo_t l_pnorSectionInfo;
        rawImageInfo_t l_imageInfo;

#ifdef CONFIG_SECUREBOOT
        l_err = PNOR::loadSecureSection(PNOR::OCMBFW);
        if(l_err)
        {
            TRACFCOMP(g_trac_expupd, ERR_MRK
                      "updateAll: Failed to load OCMBFW section"
                      " from PNOR!");

            l_err->collectTrace(EXPUPD_COMP_NAME);

            // Create IStep error log and cross reference to error that occurred
            o_stepError.addErrorDetails( l_err );

            // Commit Error
            errlCommit( l_err, EXPUPD_COMP_ID );

            break;
        }
#endif //CONFIG_SECUREBOOT

        l_imageLoaded = true;

        // get address and size of packaged image
        l_err = PNOR::getSectionInfo(PNOR::OCMBFW, l_pnorSectionInfo);
        if(l_err)
        {
            TRACFCOMP(g_trac_expupd, ERR_MRK
                      "updateAll: Failure in getSectionInfo()");

            l_err->collectTrace(EXPUPD_COMP_NAME);

            // Create IStep error log and cross reference to error that occurred
            o_stepError.addErrorDetails( l_err );

            // Commit Error
            errlCommit( l_err, EXPUPD_COMP_ID );
            break;
        }

        // Verify the header and retrieve address, size and
        // SHA512 hash of unpackaged image
        l_err = ocmbFwValidateImage(
                                  l_pnorSectionInfo.vaddr,
                                  l_pnorSectionInfo.secureProtectedPayloadSize,
                                  l_imageInfo);
        if(l_err)
        {
            TRACFCOMP(g_trac_expupd, ERR_MRK
                      "updateAll: Failure in expupdValidateImage");

            l_err->collectTrace(EXPUPD_COMP_NAME);

            // Create IStep error log and cross reference to error that occurred
            o_stepError.addErrorDetails( l_err );

            // Commit Error
            errlCommit( l_err, EXPUPD_COMP_ID );
            break;
        }

        // For each explorer chip, compare flash hash with PNOR hash and
        // create a list of explorer chips with differing hash values.
        TARGETING::TargetHandleList l_flashUpdateList;
        for(const auto & l_ocmbTarget : l_ocmbTargetList)
        {
            sha512regs_t l_regs;

            //skip all gemini ocmb chips (not updateable)
            if(l_ocmbTarget->getAttr<TARGETING::ATTR_CHIP_ID>() ==
                                                     POWER_CHIPID::GEMINI_16)
            {
                TRACFCOMP(g_trac_expupd,
                      "updateAll: skipping update of gemini OCMB 0x%08x",
                      TARGETING::get_huid(l_ocmbTarget));
                continue;
            }

            //retrieve the SHA512 hash for the currently flashed image.
            l_err = getFlashedHash(l_ocmbTarget, l_regs);
            if(l_err)
            {
                TRACFCOMP(g_trac_expupd, ERR_MRK
                         "updateAll: Failure in getFlashedHash(huid = 0x%08x)",
                         TARGETING::get_huid(l_ocmbTarget));

                l_err->collectTrace(EXPUPD_COMP_NAME);

                // Create IStep error log and cross reference to error
                // that occurred
                o_stepError.addErrorDetails(l_err);

                errlCommit(l_err, EXPUPD_COMP_ID);

                //Don't stop on error, go to next target.
                continue;
            }

            // Trace the hash and image ID values
            TRACFCOMP(g_trac_expupd,
                      "updateAll: OCMB 0x%08x image ID=0x%08x",
                      TARGETING::get_huid(l_ocmbTarget), l_regs.imageId);
            TRACFBIN(g_trac_expupd, "SHA512 HASH FROM EXPLORER",
                     l_regs.sha512Hash, HEADER_SHA512_SIZE);

            //Compare hashes.  If different, add to list for update.
            if(memcmp(l_regs.sha512Hash, l_imageInfo.imageSHA512HashPtr,
                      HEADER_SHA512_SIZE))
            {
                TRACFCOMP(g_trac_expupd,
                        "updateAll: SHA512 hash mismatch on ocmb[0x%08x]",
                        TARGETING::get_huid(l_ocmbTarget));

                //add target to our list of targets needing an update
                l_flashUpdateList.push_back(l_ocmbTarget);
            }
            else
            {
                TRACFCOMP(g_trac_expupd,
                          "updateAll: SHA512 hash for ocmb[0x%08x]"
                          " matches SHA512 hash of PNOR image.",
                          TARGETING::get_huid(l_ocmbTarget));
            }
        }

        TRACFCOMP(g_trac_expupd,
                  "updateAll: updating flash for %d OCMB chips",
                  l_flashUpdateList.size());

        // update each explorer in the list of chips needing updates
        for(const auto & l_ocmb : l_flashUpdateList)
        {
            TRACFCOMP(g_trac_expupd, "updateAll: updating OCMB 0x%08x",
                      TARGETING::get_huid(l_ocmb));
            fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>l_fapi2Target(l_ocmb);

            // reset watchdog for each ocmb as this function can be very slow
            INITSERVICE::sendProgressCode();

            // Invoke procedure
            FAPI_INVOKE_HWP(l_err, exp_fw_update, l_fapi2Target,
                            l_imageInfo.imagePtr, l_imageInfo.imageSize);
            if (l_err)
            {
                TRACFCOMP(g_trac_expupd,
                          "Error from exp_fw_update for OCMB 0x%08x",
                          TARGETING::get_huid(l_ocmb));

                l_err->collectTrace(EXPUPD_COMP_NAME);

                // Create IStep error log and cross reference to error
                // that occurred
                o_stepError.addErrorDetails( l_err );

                errlCommit(l_err, EXPUPD_COMP_ID);

                // Don't stop on error, go to next target.
                continue;
            }
            else
            {
                TRACFCOMP(g_trac_expupd,
                        "updateAll: successfully updated OCMB 0x%08x",
                        TARGETING::get_huid(l_ocmb));

                // Request reboot for new firmware to be used
                l_rebootRequired = true;
            }
        }
    }while(0);

    // unload explorer fw image
    if(l_imageLoaded)
    {
#ifdef CONFIG_SECUREBOOT
        l_err = PNOR::unloadSecureSection(PNOR::OCMBFW);
        if(l_err)
        {
            TRACFCOMP(g_trac_expupd, ERR_MRK
                      "updateAll: Failed to unload OCMBFW");

            l_err->collectTrace(EXPUPD_COMP_NAME);

            // Create IStep error log and cross reference to error that occurred
            o_stepError.addErrorDetails( l_err );

            // Commit Error
            errlCommit( l_err, EXPUPD_COMP_ID );
        }
#endif //CONFIG_SECUREBOOT
    }

    // force reboot if any updates were successful
    if(l_rebootRequired)
    {
        TRACFCOMP(g_trac_expupd,
                  "updateAll: OCMB chip(s) was updated.  Requesting reboot...");
        Target* l_pTopLevel = nullptr;
        targetService().getTopLevelTarget( l_pTopLevel );
        assert(l_pTopLevel, "expupd::updateAll: no TopLevelTarget");
        auto l_reconfigAttr =
            l_pTopLevel->getAttr<TARGETING::ATTR_RECONFIGURE_LOOP>();
        l_reconfigAttr |= RECONFIGURE_LOOP_OCMB_FW_UPDATE;
        l_pTopLevel->setAttr<TARGETING::ATTR_RECONFIGURE_LOOP>(l_reconfigAttr);
    }
    else
    {
        TRACFCOMP(g_trac_expupd, "updateAll: No OCMB chips were updated");
    }


    TRACFCOMP(g_trac_expupd, EXIT_MRK"updateAll()");
}
Esempio n. 7
0
/*
 * @brief Send esel data to bmc
 */
void send_esel(eselInitData * i_data,
            errlHndl_t &o_err, IPMI::completion_code &o_cc)
{
    IPMI_TRAC(ENTER_MRK "send_esel");
    uint8_t* data = NULL;

    size_t len = 0;
    uint8_t esel_recordID[2] = {0,0};
    uint8_t sel_recordID[2] = {0,0};

    do{
        const size_t l_eSELlen = i_data->dataSize;

        if (l_eSELlen == 0)
        {
            IPMI_TRAC(INFO_MRK "no eSEL data present, skipping to SEL");
            // sending sensor SELs only, not the eSEL
            break;
        }

        uint8_t reserveID[2] = {0,0};
        // we need to send down the extended sel data (eSEL), which is
        // longer than the protocol buffer, so we need to do a reservation and
        // call the AMI partial_add_esel command multiple times

        // put a reservation on the SEL Device since we're doing a partial_add
        len = 0;
        delete [] data;
        data = NULL;
        o_cc = IPMI::CC_UNKBAD;
        o_err = IPMI::sendrecv(IPMI::reserve_sel(),o_cc,len,data);
        if(o_err)
        {
            IPMI_TRAC(ERR_MRK "error from reserve_sel");
            break;
        }
        if(o_cc != IPMI::CC_OK)
        {
            IPMI_TRAC(ERR_MRK "Failed to reserve_sel, o_cc %02x",o_cc);
            break;
        }
        storeReserveRecord(reserveID,data);

        // first send down the SEL Event Record data
        size_t eSELindex = 0;
        uint8_t l_lastEntry = 0;
        len = PARTIAL_ADD_ESEL_REQ + sizeof(selRecord);
        delete [] data;
        data = new uint8_t[len];

        // fill in the partial_add_esel request (command) data
        createPartialAddHeader(reserveID,esel_recordID,eSELindex,l_lastEntry,data);

        // copy in the SEL event record data
        memcpy(&data[PARTIAL_ADD_ESEL_REQ], i_data->eSel,
                sizeof(selRecord));
        // update to make this what AMI eSEL wants
        data[PARTIAL_ADD_ESEL_REQ + offsetof(selRecord,record_type)] = record_type_ami_esel;
        data[PARTIAL_ADD_ESEL_REQ + offsetof(selRecord,event_data1)] = event_data1_ami;

        o_cc = IPMI::CC_UNKBAD;
        TRACFBIN( g_trac_ipmi, INFO_MRK"1st partial_add_esel:", data, len);
        o_err = IPMI::sendrecv(IPMI::partial_add_esel(),o_cc,len,data);
        if(o_err)
        {
            IPMI_TRAC(ERR_MRK "error from first partial_add_esel");
            break;
        }
        // as long as we continue to get CC_OK, the reserve sel is good.
        // if the reservation is lost (ie, because something else tried to
        // create a SEL) then the BMC just discards all this data. the
        // errorlog will still be in PNOR and won't get ACKed, so it'll get
        // resent on the next IPL.
        if (o_cc != IPMI::CC_OK)
        {
            IPMI_TRAC(ERR_MRK "failed first partial_add_esel, o_cc %02x, eSELindex %02x",
                    o_cc, eSELindex);
            break;
        }
        // BMC returns the recordID, it's always the same (unless
        // there's a major BMC bug...)
        storeReserveRecord(esel_recordID,data);

        // now send down the eSEL data in chunks.
        const size_t l_maxBuffer = IPMI::max_buffer();
        while(eSELindex<l_eSELlen)
        {
            //if the index + the maximum buffer is less than what we still
            //have left in the eSEL, this is not the last entry (data[6] = 0)
            //otherwise, it is and data[6] = 1
            if(eSELindex + (l_maxBuffer - PARTIAL_ADD_ESEL_REQ)
                    < l_eSELlen)
            {
                len = l_maxBuffer;
                l_lastEntry = 0x00;
            }
            else
            {
                len = l_eSELlen - eSELindex + PARTIAL_ADD_ESEL_REQ;
                l_lastEntry = 0x01;
            }
            delete [] data;
            data = new uint8_t[len];

            // fill in the partial_add_esel request (command) data
            createPartialAddHeader(reserveID, esel_recordID,
                    eSELindex + sizeof(selRecord),
                    l_lastEntry, data);

            uint8_t dataCpyLen = len - PARTIAL_ADD_ESEL_REQ;
            memcpy(&data[PARTIAL_ADD_ESEL_REQ],
                    &i_data->eSelExtra[eSELindex],
                    dataCpyLen);

            // update the offset into the data
            eSELindex = eSELindex + dataCpyLen;

            o_cc = IPMI::CC_UNKBAD;
            TRACFBIN( g_trac_ipmi, INFO_MRK"partial_add_esel:", data, len);
            o_err = IPMI::sendrecv(IPMI::partial_add_esel(),o_cc,len,data);
            if(o_err)
            {
                IPMI_TRAC(ERR_MRK "error from partial_add_esel");
                break;
            }
            // as long as we continue to get CC_OK, the reserve sel is good.
            // if the reservation is lost (ie, because something else tried to
            // create a SEL) then the BMC just discards all this data. the
            // errorlog will still be in PNOR and won't get ACKed, so it'll get
            // resent on the next IPL.
            if (o_cc != IPMI::CC_OK)
            {
                IPMI_TRAC(ERR_MRK "failed partial_add_esel, o_cc %02x, eSELindex %02x",
                        o_cc, eSELindex);
                break;
            }
            // BMC returns the recordID, it's always the same (unless
            // there's a major BMC bug...)
            storeReserveRecord(esel_recordID,data);
        } // while eSELindex
    }while(0);

    // if eSEL wasn't created due to an error, we don't want to continue
    if (o_err == NULL)
    {
        // caller wants us to NOT create sensor SEL
        if ((i_data->eSel[offsetof(selRecord,sensor_type)] == SENSOR::INVALID_TYPE) &&
            (i_data->eSel[offsetof(selRecord,sensor_number)] == TARGETING::UTIL::INVALID_IPMI_SENSOR)
           )
        {
            IPMI_TRAC(INFO_MRK "Invalid sensor type/number - NOT sending sensor SELs");
        }
        else
        {
            // if the eSEL wasn't created due to a bad completion code, we will
            // still try to send down a SEL that we create, which will contain
            // the eSEL recordID (if it was successful)
            if (data)
            {
                delete [] data;
            }
            len = sizeof(IPMISEL::selRecord);
            data = new uint8_t[len];

            // copy in the SEL event record data
            memcpy(data, i_data->eSel, sizeof(IPMISEL::selRecord));
            // copy the eSEL recordID (if it was created) into the extra data area
            // and mark the event_data1 to indicate this is OEM data
            data[offsetof(selRecord,event_data1)] |= 0xA0;
            data[offsetof(selRecord,event_data2)] = esel_recordID[1];
            data[offsetof(selRecord,event_data3)] = esel_recordID[0];

            // use local cc so that we don't corrupt the esel from above
            IPMI::completion_code l_cc = IPMI::CC_UNKBAD;
            TRACFBIN( g_trac_ipmi, INFO_MRK"add_sel:", data, len);
            o_err = IPMI::sendrecv(IPMI::add_sel(),l_cc,len,data);
            if(o_err)
            {
                IPMI_TRAC(ERR_MRK "error from add_sel");
            }
            else if (l_cc != IPMI::CC_OK)
            {
                IPMI_TRAC(ERR_MRK "failed add_sel, l_cc %02x", l_cc);
            }
            else
            {
                // if CC_OK, then len=2 and data contains the recordID of the new SEL
                storeReserveRecord(sel_recordID,data);
            }
        }
    }

    if (data)
    {
        delete [] data;
    }

    IPMI_TRAC(EXIT_MRK
        "send_esel o_err=%.8X, o_cc=x%.2x, sel recID=x%x%x, esel recID=x%x%x",
        o_err ? o_err->plid() : NULL, o_cc, sel_recordID[1], sel_recordID[0],
        esel_recordID[1], esel_recordID[0]);

    return;
} // send_esel