Example #1
0
// ------------------------------------------------------------------
// getPnorAddr
// ------------------------------------------------------------------
errlHndl_t getPnorAddr ( pnorInformation & i_pnorInfo,
                         uint64_t &io_cachedAddr,
                         mutex_t * i_mutex )
{
    errlHndl_t err = NULL;
    PNOR::SectionInfo_t info;

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

    do
    {
        // Get SPD PNOR section info from PNOR RP
        err = PNOR::getSectionInfo( i_pnorInfo.pnorSection,
                                    info );

        if( err )
        {
            break;
        }

        // Set the globals appropriately
        mutex_lock( i_mutex );
        io_cachedAddr = info.vaddr;
        mutex_unlock( i_mutex );
    } while( 0 );

    TRACSSCOMP( g_trac_vpd,
                EXIT_MRK"getPnorAddr() - addr: 0x%08x",
                io_cachedAddr );

    return err;
}
Example #2
0
// ------------------------------------------------------------------
// invalidatePnorCache
// ------------------------------------------------------------------
errlHndl_t invalidatePnorCache ( TARGETING::Target * i_target )
{
    errlHndl_t l_err = NULL;

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

    TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();

    if( l_type == TARGETING::TYPE_PROC )
    {
        l_err = Singleton<MvpdFacade>::instance().invalidatePnor( i_target );
    }
    else if( l_type == TARGETING::TYPE_MEMBUF )
    {
        l_err = Singleton<CvpdFacade>::instance().invalidatePnor( i_target );
    }
    else if( l_type == TARGETING::TYPE_DIMM )
    {
        l_err = SPD::invalidatePnor( i_target );
    }

    // Clear target attribute switch that says VPD is loaded into PNOR
    TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
                i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
    vpdSwitches.pnorLoaded = 0;
    i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );

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

    return l_err;
}
Example #3
0
// ------------------------------------------------------------------
// Fake readPNOR - image is in memory
// ------------------------------------------------------------------
errlHndl_t readPNOR ( uint64_t i_byteAddr,
                      size_t i_numBytes,
                      void * o_data,
                      TARGETING::Target * i_target,
                      pnorInformation & i_pnorInfo,
                      uint64_t &io_cachedAddr,
                      mutex_t * i_mutex )
{
    errlHndl_t err = NULL;
    int64_t vpdLocation = 0;
    uint64_t addr = 0x0;
    const char * readAddr = NULL;

    TRACSSCOMP( g_trac_vpd,
                ENTER_MRK"RT fake readPNOR()" );

    do
    {
        // fake getPnorAddr gets memory address of VPD
        err = getPnorAddr(i_pnorInfo,
                          io_cachedAddr,
                          i_mutex );
        if(err)
        {
            break;
        }

        addr = io_cachedAddr;

        err = getVpdLocation( vpdLocation,
                              i_target);

        if(err)
        {
            break;
        }

        // Add Offset for target vpd location
        addr += (vpdLocation * i_pnorInfo.segmentSize);

        // Add keyword offset
        addr += i_byteAddr;

        TRACUCOMP( g_trac_vpd,
                   INFO_MRK"Address to read: 0x%08x",
                   addr );

        readAddr = reinterpret_cast<const char *>( addr );
        memcpy( o_data,
                readAddr,
                i_numBytes );
    } while(0);

    TRACSSCOMP( g_trac_vpd,
                EXIT_MRK"RT fake readPNOR()" );

    return err;
}
Example #4
0
    /**
     * @brief This function will perform the steps required to do a write to
     *      the Hostboot DVPD data.
     *
     * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
     *       driververif.H
     *
     * @param[in] i_target - Processor Target device
     *
     * @param [in/out] io_buffer - Pointer to the data that was read from
     *       the target device.  It will also be used to contain data to
     *       be written to the device.
     *
     * @param [in/out] io_buflen - Length of the buffer to be read or written
     *       to/from the target.  This value should indicate the size of the
     *       io_buffer parameter that has been allocated.  Being returned it
     *       will indicate the number of valid bytes in the buffer being
     *       returned.
     *
     * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
     *       usrif.H
     *
     * @param [in] i_args - This is an argument list for the device driver
     *       framework.
     *
     * @return errlHndl_t - NULL if successful, otherwise a pointer to the
     *       error log.
     */
    errlHndl_t dvpdWrite ( DeviceFW::OperationType i_opType,
                           TARGETING::Target * i_target,
                           void * io_buffer,
                           size_t & io_buflen,
                           int64_t i_accessType,
                           va_list i_args )
    {
        errlHndl_t err = NULL;
        IpVpdFacade::input_args_t args;
        args.record = ((dvpdRecord)va_arg( i_args, uint64_t ));
        args.keyword = ((dvpdKeyword)va_arg( i_args, uint64_t ));
        args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));

        TRACSSCOMP( g_trac_vpd,
                    ENTER_MRK"dvpdWrite(0x%.8X):rec=%d,kw=%d,loc=%d",
                    TARGETING::get_huid(i_target),
                    args.record,
                    args.keyword,
                    args.location);


        err = Singleton<DvpdFacade>::instance().write(i_target,
                                                      io_buffer,
                                                      io_buflen,
                                                      args);

        return err;
    }
Example #5
0
// ------------------------------------------------------------------
// getVpdLocation
// ------------------------------------------------------------------
errlHndl_t getVpdLocation ( int64_t & o_vpdLocation,
                            TARGETING::Target * i_target )
{
    errlHndl_t err = NULL;

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

    o_vpdLocation = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>();
    TRACUCOMP( g_trac_vpd,
               INFO_MRK"Using VPD location: %d",
               o_vpdLocation );

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

    return err;
}
Example #6
0
    /**
     * @brief This function will perform the steps required to do a read from
     *      the Hostboot DVPD data.
     *
     * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
     *       driververif.H
     *
     * @param[in] i_target - Processor Target device
     *
     * @param [in/out] io_buffer - Pointer to the data that was read from
     *       the target device.  This parameter, when set to NULL, will return
     *       the keyword size value in io_buflen.
     *
     * @param [in/out] io_buflen - Length of the buffer to be read or written
     *       to/from the target.  This value should indicate the size of the
     *       io_buffer parameter that has been allocated.  Being returned it
     *       will indicate the number of valid bytes in the buffer being
     *       returned. This parameter will contain the size of a keyword when
     *       the io_buffer parameter is passed in NULL.
     *
     * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
     *       usrif.H
     *
     * @param [in] i_args - This is an argument list for the device driver
     *       framework.
     *
     * @return errlHndl_t - NULL if successful, otherwise a pointer to the
     *       error log.
     */
    errlHndl_t dvpdRead ( DeviceFW::OperationType i_opType,
                          TARGETING::Target * i_target,
                          void * io_buffer,
                          size_t & io_buflen,
                          int64_t i_accessType,
                          va_list i_args )
    {
        errlHndl_t err = NULL;
        IpVpdFacade::input_args_t args;
        args.record = ((dvpdRecord)va_arg( i_args, uint64_t ));
        args.keyword = ((dvpdKeyword)va_arg( i_args, uint64_t ));
        args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));

        TRACSSCOMP( g_trac_vpd,
                    ENTER_MRK"dvpdRead(0x%.8X):rec=%d,kw=%d,loc=%d",
                    TARGETING::get_huid(i_target),
                    args.record,
                    args.keyword,
                    args.location);

#ifdef CONFIG_SECUREBOOT
        // Load the secure section just in case if we're using it
        bool l_didload = false;
        err = Singleton<DvpdFacade>::instance().
          loadUnloadSecureSection( args, i_target, true, l_didload );
#endif

        if( !err )
        {
            err = Singleton<DvpdFacade>::instance().read(i_target,
                                                         io_buffer,
                                                         io_buflen,
                                                         args);
        }

#ifdef CONFIG_SECUREBOOT
        if( l_didload )
        {
            errlHndl_t err2 = Singleton<DvpdFacade>::instance().
              loadUnloadSecureSection( args, i_target, false, l_didload );
            if( err2 && !err )
            {
                err = err2;
                err2 = nullptr;
            }
            else if( err2 )
            {
                err2->plid(err->plid());
                errlCommit( err2, VPD_COMP_ID );
            }
        }
#endif

        return err;
    }
Example #7
0
// --------------------------------------------------------
// Presence Detection
//---------------------------------------------------------
bool VPD::cvpdPresent( TARGETING::Target * i_target )
{
    TRACSSCOMP( g_trac_vpd, ENTER_MRK"cvpdPresent()");
#if(defined( CONFIG_MEMVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) )

    return EEPROM::eepromPresence( i_target );

#else
    return Singleton<CvpdFacade>::instance().hasVpdPresent( i_target,
                                                            CVPD::VEIR,
                                                            CVPD::PF );
#endif
}
Example #8
0
bool DVPD::dvpdPresent( TARGETING::Target * i_target )
{
    TRACSSCOMP( g_trac_vpd, ENTER_MRK"dvpdPresent()");
#if(defined( CONFIG_MEMVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) )

    return EEPROM::eepromPresence( i_target );

#else
    return Singleton<DvpdFacade>::instance().hasVpdPresent( i_target,
//TODO RTC 144519 Update recod/keyword once records/keywords defined
//                to be used as "sniff test" that vpd is readable.
                                                            CVPD::VEIR,
                                                            CVPD::PF );
#endif
}
Example #9
0
    /**
     * @brief This function will perform the steps required to do a read from
     *      the Hostboot MVPD data.
     *
     * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
     *       driververif.H
     *
     * @param[in] i_target - Processor Target device
     *
     * @param [in/out] io_buffer - Pointer to the data that was read from
     *       the target device.  This parameter, when set to NULL, will return
     *       the keyword size value in io_buflen.
     *
     * @param [in/out] io_buflen - Length of the buffer to be read or written
     *       to/from the target.  This value should indicate the size of the
     *       io_buffer parameter that has been allocated.  Being returned it
     *       will indicate the number of valid bytes in the buffer being
     *       returned. This parameter will contain the size of a keyword when
     *       the io_buffer parameter is passed in NULL.
     *
     * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
     *       usrif.H
     *
     * @param [in] i_args - This is an argument list for the device driver
     *       framework.
     *
     * @return errlHndl_t - NULL if successful, otherwise a pointer to the
     *       error log.
     */
    errlHndl_t mvpdRead ( DeviceFW::OperationType i_opType,
                          TARGETING::Target * i_target,
                          void * io_buffer,
                          size_t & io_buflen,
                          int64_t i_accessType,
                          va_list i_args )
    {
        errlHndl_t err = NULL;
        IpVpdFacade::input_args_t args;
        args.record = ((mvpdRecord)va_arg( i_args, uint64_t ));
        args.keyword = ((mvpdKeyword)va_arg( i_args, uint64_t ));

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

        err = Singleton<MvpdFacade>::instance().read(i_target,
                                                  io_buffer,
                                                  io_buflen,
                                                  args);

        return err;
    }
Example #10
0
// ------------------------------------------------------------------
// ensureCacheIsInSync
// ------------------------------------------------------------------
errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
{
    errlHndl_t l_err = NULL;

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

    IpVpdFacade& l_ipvpd = Singleton<MvpdFacade>::instance();

    vpdRecord  l_record    = 0;
    vpdKeyword l_keywordPN = 0;
    vpdKeyword l_keywordSN = 0;

    TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();

    if( l_type == TARGETING::TYPE_PROC )
    {
        l_record    = MVPD::VINI;
        l_keywordPN = MVPD::PN;
        l_keywordSN = MVPD::SN;
    }
    else if( l_type == TARGETING::TYPE_MEMBUF )
    {
        l_ipvpd     = Singleton<CvpdFacade>::instance();
        l_record    = CVPD::VINI;
        l_keywordPN = CVPD::PN;
        l_keywordSN = CVPD::SN;
    }
    else if( l_type == TARGETING::TYPE_DIMM )
    {
        // SPD does not have a singleton instance
        // SPD does not use records
        l_keywordPN = SPD::MODULE_PART_NUMBER;
        l_keywordSN = SPD::MODULE_SERIAL_NUMBER;
    }
    else
    {
        TRACFCOMP(g_trac_vpd,ERR_MRK"ensureCacheIsInSync() Unexpected target type, huid=0x%X",TARGETING::get_huid(i_target));
        /*@
         * @errortype
         * @moduleid     VPD_ENSURE_CACHE_IS_IN_SYNC
         * @reasoncode   VPD_UNEXPECTED_TARGET_TYPE
         * @userdata1    Target HUID
         * @userdata2    <UNUSED>
         * @devdesc      Unexpected target type
         */
        l_err = new ERRORLOG::ErrlEntry(
                                ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                VPD_ENSURE_CACHE_IS_IN_SYNC,
                                VPD_UNEXPECTED_TARGET_TYPE,
                                TO_UINT64(TARGETING::get_huid(i_target)),
                                0x0,
                                true /*Add HB Software Callout*/ );
        return l_err;
    }

    do
    {
        // Compare the Part Numbers in PNOR/SEEPROM
        bool l_matchPN = false;
        if( ( l_type == TARGETING::TYPE_PROC   ) ||
            ( l_type == TARGETING::TYPE_MEMBUF ) )
        {
            l_err = l_ipvpd.cmpPnorToSeeprom( i_target,
                                              l_record,
                                              l_keywordPN,
                                              l_matchPN );
        }
        else if( l_type == TARGETING::TYPE_DIMM )
        {
            l_err = SPD::cmpPnorToSeeprom( i_target,
                                           l_keywordPN,
                                           l_matchPN );
        }
        if (l_err)
        {
            TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureCacheIsInSync: Error checking for PNOR/SEEPROM PN match");
            break;
        }

        // Compare the Serial Numbers in PNOR/SEEPROM
        bool l_matchSN = false;
        if( ( l_type == TARGETING::TYPE_PROC   ) ||
            ( l_type == TARGETING::TYPE_MEMBUF ) )
        {
            l_err = l_ipvpd.cmpPnorToSeeprom( i_target,
                                              l_record,
                                              l_keywordSN,
                                              l_matchSN );
        }
        else if( l_type == TARGETING::TYPE_DIMM )
        {
            l_err = SPD::cmpPnorToSeeprom( i_target,
                                           l_keywordSN,
                                           l_matchSN );
        }
        if( l_err )
        {
            TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureCacheIsInSync: Error checking for PNOR/SEEPROM SN match");
            break;
        }

        // If we did not match, we need to load SEEPROM VPD data into PNOR
        if( l_matchPN && l_matchSN )
        {
            TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN = SEEPROM_PN/SN");
        }
        else
        {
            TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN != SEEPROM_PN/SN, Loading PNOR from SEEPROM");

            // @todo RTC 116553 - Need HCDB update call here
            // Load the PNOR data from the SEEPROM
            if( ( l_type == TARGETING::TYPE_PROC   ) ||
                ( l_type == TARGETING::TYPE_MEMBUF ) )
            {
                l_err = l_ipvpd.loadPnor( i_target );
            }
            else if( l_type == TARGETING::TYPE_DIMM )
            {
                l_err = SPD::loadPnor( i_target );
            }
            if( l_err )
            {
                TRACFCOMP(g_trac_vpd,"Error loading SEEPROM VPD into PNOR");
                break;
            }
        }

        // Set target attribute switch that says VPD is loaded into PNOR
        TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
                    i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
        vpdSwitches.pnorLoaded = 1;
        i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );

    } while(0);

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

    return l_err;
}
Example #11
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;
}
Example #12
0
// ------------------------------------------------------------------
// writePNOR
// ------------------------------------------------------------------
errlHndl_t writePNOR ( uint64_t i_byteAddr,
                       size_t i_numBytes,
                       void * i_data,
                       TARGETING::Target * i_target,
                       pnorInformation & i_pnorInfo,
                       uint64_t &io_cachedAddr,
                       mutex_t * i_mutex )
{
    errlHndl_t err = NULL;
    int64_t vpdLocation = 0;
    uint64_t addr = 0x0;
    const char * writeAddr = NULL;

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

    do
    {
        // Check if we have the PNOR addr cached.
        if( 0x0 == io_cachedAddr )
        {
            err = getPnorAddr( i_pnorInfo,
                               io_cachedAddr,
                               i_mutex );

            if( err )
            {
                break;
            }
        }
        addr = io_cachedAddr;

        // Find vpd location of the target
        err = getVpdLocation( vpdLocation,
                              i_target );

        if( err )
        {
            break;
        }

        // Offset cached address by vpd location multiplier
        addr += (vpdLocation * i_pnorInfo.segmentSize);

        // Now offset into that chunk of data by i_byteAddr
        addr += i_byteAddr;

        //TODO: Validate write is within bounds of appropriate PNOR
        //   partition/section.   RTC: 51807

        TRACUCOMP( g_trac_vpd,
                   INFO_MRK"Address to write: 0x%08x",
                   addr );

        // Write the data
        writeAddr = reinterpret_cast<const char*>( addr );
        memcpy( (void*)(writeAddr),
                i_data,
                i_numBytes );

        // @todo RTC:117042 - enable flush once PNOR writes supported
        // Flush the page to make sure it gets to the PNOR
#if 0
        int rc = mm_remove_pages( FLUSH, (void*)addr, i_numBytes );
        if( rc )
        {
            TRACFCOMP(g_trac_vpd,ERR_MRK"writePNOR() Error from mm_remove_pages, rc=%d",rc);
            /*@
             * @errortype
             * @moduleid     VPD_WRITE_PNOR
             * @reasoncode   VPD_REMOVE_PAGES_FAIL
             * @userdata1    Requested Address
             * @userdata2    rc from mm_remove_pages
             * @devdesc      writePNOR mm_remove_pages FLUSH failed
             */
            err = new ERRORLOG::ErrlEntry(
                            ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                            VPD_WRITE_PNOR,
                            VPD_REMOVE_PAGES_FAIL,
                            addr,
                            TO_UINT64(rc),
                            true /*Add HB Software Callout*/ );
        }
#endif
    } while( 0 );

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

    return err;
}
Example #13
0
// ------------------------------------------------------------------
// readPNOR
// ------------------------------------------------------------------
errlHndl_t readPNOR ( uint64_t i_byteAddr,
                      size_t i_numBytes,
                      void * o_data,
                      TARGETING::Target * i_target,
                      pnorInformation & i_pnorInfo,
                      uint64_t &io_cachedAddr,
                      mutex_t * i_mutex )
{
    errlHndl_t err = NULL;
    int64_t vpdLocation = 0;
    uint64_t addr = 0x0;
    const char * readAddr = NULL;

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

    do
    {
        // Check if we have the PNOR addr cached.
        if( 0x0 == io_cachedAddr )
        {
            err = getPnorAddr( i_pnorInfo,
                               io_cachedAddr,
                               i_mutex );

            if( err )
            {
                break;
            }
        }
        addr = io_cachedAddr;

        // Find vpd location of the target
        err = getVpdLocation( vpdLocation,
                              i_target );

        if( err )
        {
            break;
        }

        // Offset cached address by vpd location multiplier
        addr += (vpdLocation * i_pnorInfo.segmentSize);

        // Now offset into that chunk of data by i_byteAddr
        addr += i_byteAddr;

        TRACUCOMP( g_trac_vpd,
                   INFO_MRK"Address to read: 0x%08x",
                   addr );

        //TODO: Validate write is within bounds of appropriate PNOR
        //   partition/section.   RTC: 51807

        // Pull the data
        readAddr = reinterpret_cast<const char*>( addr );
        memcpy( o_data,
                readAddr,
                i_numBytes );
    } while( 0 );

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

    return err;
}
Example #14
0
/**
 * @brief Performs a presence detect operation on MCSs
 *
 * Although not a physical part, presence detect confirms access
 * to direct access memory vpd.
 *
 * @param[in]   i_opType        Operation type, see DeviceFW::OperationType
 *                              in driverif.H
 * @param[in]   i_target        Presence detect target
 * @param[in/out] io_buffer     Read: Pointer to output data storage
 *                              Write: Pointer to input data storage
 * @param[in/out] io_buflen     Input: size of io_buffer (in bytes, always 1)
 *                              Output: Success = 1, Failure = 0
 * @param[in]   i_accessType    DeviceFW::AccessType enum (userif.H)
 * @param[in]   i_args          This is an argument list for DD framework.
 *                              In this function, there are no arguments.
 * @return  errlHndl_t
 */
errlHndl_t directMemoryPresenceDetect(DeviceFW::OperationType i_opType,
                              TARGETING::Target* i_target,
                              void* io_buffer,
                              size_t& io_buflen,
                              int64_t i_accessType,
                              va_list i_args)
{
    errlHndl_t l_errl = NULL;
    bool dvpd_present = false;

    TRACSSCOMP(g_trac_vpd,
                  ENTER_MRK "directMemoryPresenceDetect");

    if (unlikely(io_buflen < sizeof(bool)))
    {
        TRACFCOMP(g_trac_vpd,
                  ERR_MRK "directMemoryPresenceDetect> Invalid data length: %d",
                  io_buflen);
        /*@
         * @errortype
         * @moduleid     VPD::VPD_DVPD_PRESENCEDETECT
         * @reasoncode   VPD::VPD_INVALID_LENGTH
         * @userdata1    Data Length
         * @devdesc      presenceDetect> Invalid data length (!= 1 bytes)
         */
        l_errl =
                new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                        VPD::VPD_DVPD_PRESENCEDETECT,
                                        VPD::VPD_INVALID_LENGTH,
                                        TO_UINT64(io_buflen),
                                        true /*SW error*/);
        io_buflen = 0;
        return l_errl;
    }

    dvpd_present = DVPD::dvpdPresent( i_target );
#if defined(CONFIG_MEMVPD_READ_FROM_HW) && defined(CONFIG_MEMVPD_READ_FROM_PNOR)
    //skipping cache sync when dvpd is present as it will be taken care by node
    //vpd
    if( !dvpd_present )
    {
        TRACFCOMP(g_trac_vpd,
                  ERR_MRK "directMemoryPresenceDetect> failed presence detect");

        // Defer invalidating DVPD in the PNOR in case another target might be
        // sharing this VPD_REC_NUM. Check all targets sharing this
        // VPD_REC_NUM after target discovery in VPD::validateSharedPnorCache.
        // Ensure the VPD_SWITCHES cache valid bit is invalid at this point.
        TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
        i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
        vpdSwitches.pnorCacheValid = 0;
        i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
    }
#endif

    memcpy(io_buffer, &dvpd_present, sizeof(dvpd_present));
    io_buflen = sizeof(dvpd_present);

    TRACSSCOMP(g_trac_vpd,
                  EXIT_MRK "directMemoryPresenceDetect = %d",dvpd_present);
    return NULL;
}
Example #15
0
// ------------------------------------------------------------------
// dimmPresenceDetect
// ------------------------------------------------------------------
errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
                               TARGETING::Target * i_target,
                               void * io_buffer,
                               size_t & io_buflen,
                               int64_t i_accessType,
                               va_list i_args )
{
    errlHndl_t err = NULL;
    bool present = false;
    size_t presentSz = sizeof(present);

    TRACSSCOMP( g_trac_spd,
                ENTER_MRK"dimmPresenceDetect()" );

    do
    {
        // Check to be sure that the buffer is big enough.
        if( !(io_buflen >= sizeof(bool)) )
        {
            TRACFCOMP( g_trac_spd,
                       ERR_MRK"dimmPresenceDetect() - Invalid Data Length: %d",
                       io_buflen );

            /*@
             * @errortype
             * @reasoncode       VPD::VPD_INSUFFICIENT_BUFFER_SIZE
             * @severity         ERRORLOG::ERRL_SEV_UNRECOVERABLE
             * @moduleid         VPD::VPD_SPD_PRESENCE_DETECT
             * @userdata1        Buffer Length
             * @userdata2        <UNUSED>
             * @devdesc          Buffer for checking Presence Detect
             *                   was not the correct size.
             */
            err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                           VPD::VPD_SPD_PRESENCE_DETECT,
                                           VPD::VPD_INSUFFICIENT_BUFFER_SIZE,
                                           TO_UINT64(io_buflen),
                                           0x0,
                                           true /*Add HB Software Callout*/);

            err->collectTrace( "SPD", 256);

            break;
        }

        // Is the target present
#ifdef CONFIG_DJVPD_READ_FROM_HW
        // Check if the parent MBA/MEMBUF is present.  If it is not then
        // no reason to check the DIMM which would otherwise generate
        // tons of FSI errors.  We can't just check if parent MBA
        // is functional because DIMM presence detect is called before
        // the parent MBA/MEMBUF is set as present/functional.
        TARGETING::TargetHandleList membufList;
        TARGETING::PredicateCTM membufPred( TARGETING::CLASS_CHIP,
                                            TARGETING::TYPE_MEMBUF );
        TARGETING::targetService().getAssociated(
            membufList,
            i_target,
            TARGETING::TargetService::PARENT_BY_AFFINITY,
            TARGETING::TargetService::ALL,
            &membufPred);

        bool parentPresent = false;
        const TARGETING::TargetHandle_t membufTarget = *(membufList.begin());

        err = deviceRead(membufTarget, &parentPresent, presentSz,
                                DEVICE_PRESENT_ADDRESS());
        if (err)
        {
            TRACFCOMP(
                g_trac_spd,
                "Error reading parent MEMBUF present: huid 0x%X DIMM huid 0x%X",
                TARGETING::get_huid(membufTarget),
                TARGETING::get_huid(i_target) );
            break;
        }
        if (!parentPresent)
        {
            present = false;
            // Invalidate the SPD in PNOR
            err = VPD::invalidatePnorCache(i_target);
            if (err)
            {
                TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" );
            }
            break;
        }
#endif

        present = spdPresent( i_target );

        if( present == false )
        {
            TRACUCOMP( g_trac_spd,
                       INFO_MRK"Dimm was found to be NOT present." );
        }
        else
        {
            TRACUCOMP( g_trac_spd,
                       INFO_MRK"Dimm was found to be present." );
        }

#if defined(CONFIG_DJVPD_READ_FROM_HW) && defined(CONFIG_DJVPD_READ_FROM_PNOR)
        if( present )
        {
            // Check if the VPD data in the PNOR matches the SEEPROM
            err = VPD::ensureCacheIsInSync( i_target );
            if( err )
            {
                present = false;

                TRACFCOMP(g_trac_spd,ERR_MRK "dimmPresenceDetectt> Error during ensureCacheIsInSync (SPD)" );
                break;
            }
        }
        else
        {
            // SPD is not present, invalidate the SPD in PNOR
            err = VPD::invalidatePnorCache(i_target);
            if (err)
            {
                TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" );
            }
        }
#endif

        if( present && !err )
        {
            //Fsp sets PN/SN so if there is none, do it here
            if(!INITSERVICE::spBaseServicesEnabled())
            {
                //populate serial and part number attributes
                SPD::setPartAndSerialNumberAttributes( i_target );
            }

            // Read ATTR_CLEAR_DIMM_SPD_ENABLE attribute
            TARGETING::Target* l_sys = NULL;
            TARGETING::targetService().getTopLevelTarget(l_sys);

            TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE_type l_clearSPD =
                l_sys->getAttr<TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE>();

            // If SPD clear is enabled then write 0's into magic word for 
            // DIMM_BAD_DQ_DATA keyword
            // Note: If there's an error from performing the clearing,
            // just log the error and continue.
            if (l_clearSPD)
            {
                size_t l_size = 0;

                // Do a read to get the DIMM_BAD_DQ_DATA keyword size
                err = deviceRead(i_target, NULL, l_size,
                                 DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ));
                if (err)
                {
                    TRACFCOMP(g_trac_spd, "dimmPresenceDetect - "
                        "Error reading DIMM_BAD_DQ_DATA keyword size");
                    errlCommit( err, VPD_COMP_ID );
                }
                else
                {
                    // Clear the data
                    TRACFCOMP( g_trac_spd, "Clearing out BAD_DQ_DATA SPD on "
                               "DIMM HUID 0x%X",
                               TARGETING::get_huid(i_target));

                    uint8_t * l_data = static_cast<uint8_t*>(malloc( l_size ));
                    memset(l_data, 0, l_size);

                    err = deviceWrite(i_target, l_data, l_size,
                                     DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ));
                    if (err)
                    {
                        TRACFCOMP( g_trac_spd, "Error trying to clear SPD on "
                                   "DIMM HUID 0x%X",
                                   TARGETING::get_huid(i_target));
                        errlCommit( err, VPD_COMP_ID );
                    }

                    // Free the memory
                    if (NULL != l_data)
                    {
                        free(l_data);
                    }
                }
            }
        }

        // copy present value into output buffer so caller can read it
        memcpy( io_buffer, &present, presentSz );
        io_buflen = presentSz;

    } while( 0 );

    TRACSSCOMP( g_trac_spd,
                EXIT_MRK"dimmPresenceDetect()" );

    return err;
} // end dimmPresenceDetect
Example #16
0
// ------------------------------------------------------------------
// dimmPresenceDetect
// ------------------------------------------------------------------
errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
                               TARGETING::Target * i_target,
                               void * io_buffer,
                               size_t & io_buflen,
                               int64_t i_accessType,
                               va_list i_args )
{
    errlHndl_t err = NULL;
    bool present = false;
    size_t presentSz = sizeof(present);

    TRACSSCOMP( g_trac_spd, ENTER_MRK"dimmPresenceDetect() "
                "DIMM HUID 0x%X", TARGETING::get_huid(i_target));
    do
    {
        // Check to be sure that the buffer is big enough.
        if( !(io_buflen >= sizeof(bool)) )
        {
            TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                       "Invalid Data Length: %d",
                       io_buflen );

            /*@
             * @errortype
             * @reasoncode       VPD::VPD_INSUFFICIENT_BUFFER_SIZE
             * @severity         ERRORLOG::ERRL_SEV_UNRECOVERABLE
             * @moduleid         VPD::VPD_SPD_PRESENCE_DETECT
             * @userdata1        Buffer Length
             * @userdata2        <UNUSED>
             * @devdesc          Buffer for checking Presence Detect
             *                   was not the correct size.
             */
            err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                           VPD::VPD_SPD_PRESENCE_DETECT,
                                           VPD::VPD_INSUFFICIENT_BUFFER_SIZE,
                                           TO_UINT64(io_buflen),
                                           0x0,
                                           true /*Add HB Software Callout*/);

            err->collectTrace( "SPD", 256);

            break;
        }

        // Is the target present?
#ifdef CONFIG_DJVPD_READ_FROM_HW
        // Check if the i2c master is present.
        // If it is not then no reason to check the DIMM which would
        // otherwise generate tons of FSI errors.
        // We can't just check if parent MCA or MBA
        // is functional because DIMM presence detect is called before
        // the parent MCS/MCA or MBA/MEMBUF is set as present/functional.
        bool l_i2cMasterPresent = false;

        do
        {
            // get eeprom vpd primary info
            TARGETING::EepromVpdPrimaryInfo eepromData;
            if( !(i_target->
                     tryGetAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO>
                         ( eepromData ) ) )
            {
                TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                           "Error: no eeprom vpd primary info" );
                break;
            }

            // find i2c master target
            TARGETING::TargetService& tS = TARGETING::targetService();
            bool exists = false;
            tS.exists( eepromData.i2cMasterPath, exists );
            if( !exists )
            {
                TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                           "i2cMasterPath attribute path doesn't exist");
                break;
            }

            // Since it exists, convert to a target
            TARGETING::Target * l_i2cMasterTarget =
                                   tS.toTarget( eepromData.i2cMasterPath );

            if( NULL == l_i2cMasterTarget )
            {
                TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                           "i2cMasterPath target is NULL");
                break;
            }
            TRACSSCOMP( g_trac_spd, "dimmPresenceDetect() "
                "i2c master HUID 0x%X", TARGETING::get_huid(l_i2cMasterTarget));

            // Check if present
            TARGETING::Target* masterProcTarget = NULL;
            TARGETING::targetService().masterProcChipTargetHandle(
                                                        masterProcTarget );
            // Master proc is taken as always present. Validate other targets.
            if (l_i2cMasterTarget != masterProcTarget)
            {
                l_i2cMasterPresent = FSI::isSlavePresent(l_i2cMasterTarget);
                if( !l_i2cMasterPresent )
                {
                    TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                               "isSlavePresent failed");
                    break;
                }
            }
            l_i2cMasterPresent = true;
        }
        while (0);

        if (!l_i2cMasterPresent)
        {
            present = false;
            // Invalidate the SPD in PNOR
            err = VPD::invalidatePnorCache(i_target);
            if (err)
            {
                TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                           "Error invalidating SPD in PNOR" );
            }
            break;
        }
#endif

        present = spdPresent( i_target );

        if( present == false )
        {
            TRACUCOMP( g_trac_spd, INFO_MRK"dimmPresenceDetect() "
                       "Dimm was found to be NOT present." );
        }
        else
        {
            TRACUCOMP( g_trac_spd, INFO_MRK"dimmPresenceDetect() "
                       "Dimm was found to be present." );
        }

#if defined(CONFIG_DJVPD_READ_FROM_HW) && defined(CONFIG_DJVPD_READ_FROM_PNOR)
        if( present )
        {
            // Check if the VPD data in the PNOR matches the SEEPROM
            err = VPD::ensureCacheIsInSync( i_target );
            if( err )
            {
                present = false;
                TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                           "Error during ensureCacheIsInSync (SPD)" );
                break;
            }
        }
        else
        {
            // SPD is not present, invalidate the SPD in PNOR
            err = VPD::invalidatePnorCache(i_target);
            if (err)
            {
                TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                           "Error invalidating SPD in PNOR" );
            }
        }
#endif

        if( present && !err )
        {
            //Fsp sets PN/SN so if there is none, do it here
            if(!INITSERVICE::spBaseServicesEnabled())
            {
                //populate serial and part number attributes
                SPD::setPartAndSerialNumberAttributes( i_target );
            }

            // Read ATTR_CLEAR_DIMM_SPD_ENABLE attribute
            TARGETING::Target* l_sys = NULL;
            TARGETING::targetService().getTopLevelTarget(l_sys);

            TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE_type l_clearSPD =
                l_sys->getAttr<TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE>();

            // If SPD clear is enabled then write 0's into magic word for
            // DIMM_BAD_DQ_DATA keyword
            // Note: If there's an error from performing the clearing,
            // just log the error and continue.
            if (l_clearSPD)
            {
                size_t l_size = 0;

                // Do a read to get the DIMM_BAD_DQ_DATA keyword size
                err = deviceRead(i_target, NULL, l_size,
                                 DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ));
                if (err)
                {
                    TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                        "Error reading DIMM_BAD_DQ_DATA keyword size");
                    errlCommit( err, VPD_COMP_ID );
                }
                else
                {
                    // Clear the data
                    TRACFCOMP( g_trac_spd, "Clearing out BAD_DQ_DATA SPD on "
                               "DIMM HUID 0x%X",
                               TARGETING::get_huid(i_target));

                    uint8_t * l_data = static_cast<uint8_t*>(malloc( l_size ));
                    memset(l_data, 0, l_size);

                    err = deviceWrite(i_target, l_data, l_size,
                                     DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ));
                    if (err)
                    {
                        TRACFCOMP(g_trac_spd, ERR_MRK"dimmPresenceDetect() "
                                  "Error trying to clear SPD on DIMM HUID 0x%X",
                                  TARGETING::get_huid(i_target));
                        errlCommit( err, VPD_COMP_ID );
                    }

                    // Free the memory
                    if (NULL != l_data)
                    {
                        free(l_data);
                    }
                }
            }
        }

        // copy present value into output buffer so caller can read it
        memcpy( io_buffer, &present, presentSz );
        io_buflen = presentSz;

    } while( 0 );

    TRACSSCOMP( g_trac_spd, EXIT_MRK"dimmPresenceDetect()" );

    return err;
} // end dimmPresenceDetect