diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2014-06-18 16:09:55 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-07-01 13:34:57 -0500 |
commit | 2cc1c594ad2b05919d1742625de0da83ffd7f01d (patch) | |
tree | 57bbbe923325245e809ea51a96c60ffe79b18600 /src/usr/vpd | |
parent | 3bcf5b7982bb8a2d9227dbff7be4ff2ce5fec05c (diff) | |
download | talos-hostboot-2cc1c594ad2b05919d1742625de0da83ffd7f01d.tar.gz talos-hostboot-2cc1c594ad2b05919d1742625de0da83ffd7f01d.zip |
Merge VPD commits from Stradale
Change-Id: I95aa2bb30299c9d22563068741ffbeda48d2d84b
RTC: 97488
Origin: Google Shared Technology
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/11661
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/vpd')
-rw-r--r-- | src/usr/vpd/HBconfig | 77 | ||||
-rw-r--r-- | src/usr/vpd/cvpd.C | 26 | ||||
-rwxr-xr-x | src/usr/vpd/dimmPres.C | 24 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.C | 377 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.H | 146 | ||||
-rw-r--r-- | src/usr/vpd/mvpd.C | 27 | ||||
-rwxr-xr-x | src/usr/vpd/spd.C | 20 |
7 files changed, 636 insertions, 61 deletions
diff --git a/src/usr/vpd/HBconfig b/src/usr/vpd/HBconfig new file mode 100644 index 000000000..83223a37d --- /dev/null +++ b/src/usr/vpd/HBconfig @@ -0,0 +1,77 @@ +config CVPD_READ_FROM_PNOR + default y + depends on !CVPD_READ_FROM_HW + help + Read Centaur VPD data from PNOR cache + +config CVPD_READ_FROM_HW + default y if !CVPD_READ_FROM_PNOR + depends on !CVPD_READ_FROM_PNOR + help + Read Centaur VPD data from HW resources + +config CVPD_WRITE_TO_PNOR + default y + help + Write Centaur VPD data to PNOR cache + +config CVPD_WRITE_TO_HW + default n + depends on !PALMETTO_PASS1 + help + Write Centaur VPD data to HW resources + +config MVPD_READ_FROM_PNOR + default y + depends on !MVPD_READ_FROM_HW + help + Read Module VPD data from PNOR cache + +config MVPD_READ_FROM_HW + default y if !MVPD_READ_FROM_PNOR + depends on !MVPD_READ_FROM_PNOR + help + Read Module VPD data from HW resources + +config MVPD_WRITE_TO_PNOR + default y + help + Write Module VPD data to PNOR cache + +config MVPD_WRITE_TO_HW + default n + help + Write Module VPD data to HW resources + +config DJVPD_READ_FROM_PNOR + default y + depends on !DJVPD_READ_FROM_HW + help + Read Dimm JEDEC VPD/SPD data from PNOR cache + +config DJVPD_READ_FROM_HW + default y if !DJVPD_READ_FROM_PNOR + depends on !DJVPD_READ_FROM_PNOR + help + Read Dimm JEDEC VPD/SPD data from HW resources + +config DJVPD_WRITE_TO_PNOR + default y + help + Write Dimm JEDEC VPD/SPD data to PNOR cache + +config DJVPD_WRITE_TO_HW + default n + help + Write Dimm JEDEC VPD/SPD data to HW resources + +config HAVE_MBVPD + default y if CVPD_READ_FROM_PNOR || CVPD_READ_FROM_HW + depends on CVPD_READ_FROM_PNOR || CVPD_READ_FROM_HW + help + Have MemBuff/Centaur VPD, PNOR or HW + +config PALMETTO_PASS1 + default n + help + Palmetto pass1 specific changes diff --git a/src/usr/vpd/cvpd.C b/src/usr/vpd/cvpd.C index 8490ff66e..a21eaaa62 100644 --- a/src/usr/vpd/cvpd.C +++ b/src/usr/vpd/cvpd.C @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -33,6 +36,7 @@ #include <vfs/vfs.H> #include <vpd/vpdreasoncodes.H> #include <vpd/cvpdenums.H> +#include <config.h> #include "cvpd.H" #include "vpd.H" @@ -196,4 +200,24 @@ IpVpdFacade(CVPD::SECTION_SIZE, { TRACUCOMP(g_trac_vpd, "CvpdFacade::CvpdFacade> " ); +#ifdef CONFIG_CVPD_READ_FROM_PNOR + iv_configInfo.vpdReadPNOR = true; +#else + iv_configInfo.vpdReadPNOR = false; +#endif +#ifdef CONFIG_CVPD_READ_FROM_HW + iv_configInfo.vpdReadHW = true; +#else + iv_configInfo.vpdReadHW = false; +#endif +#ifdef CONFIG_CVPD_WRITE_TO_PNOR + iv_configInfo.vpdWritePNOR = true; +#else + iv_configInfo.vpdWritePNOR = false; +#endif +#ifdef CONFIG_CVPD_WRITE_TO_HW + iv_configInfo.vpdWriteHW = true; +#else + iv_configInfo.vpdWriteHW = false; +#endif } diff --git a/src/usr/vpd/dimmPres.C b/src/usr/vpd/dimmPres.C index fa7fdc63f..32042fe6b 100755 --- a/src/usr/vpd/dimmPres.C +++ b/src/usr/vpd/dimmPres.C @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -37,6 +40,7 @@ #include <devicefw/driverif.H> #include <vpd/vpdreasoncodes.H> #include <vpd/spdenums.H> +#include <config.h> #include "spd.H" @@ -118,6 +122,24 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType, } // Is the target present +#ifdef CONFIG_DJVPD_READ_FROM_HW + // Check if the parent MBA is functional. + // If it is non-functional then no reason to check the DIMM which + // would otherwise generate tons of FSI errors. + TARGETING::TargetHandleList membuf_parent; + TARGETING::PredicateIsFunctional isFunctional; + TARGETING::targetService().getAssociated( + membuf_parent, + i_target, + TARGETING::TargetService::PARENT_BY_AFFINITY, + TARGETING::TargetService::IMMEDIATE, + &isFunctional); + if ( membuf_parent.size() != 1 ) + { + present = false; + break; + } +#endif present = spdPresent( i_target ); if( present == false ) diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C index 6b6c90cff..22504f672 100644 --- a/src/usr/vpd/ipvpd.C +++ b/src/usr/vpd/ipvpd.C @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -31,8 +34,11 @@ #include <errl/errludtarget.H> #include <targeting/common/targetservice.H> #include <devicefw/driverif.H> +#include <devicefw/userif.H> +#include <i2c/eepromif.H> #include <vfs/vfs.H> #include <vpd/vpdreasoncodes.H> +#include <config.h> #include "vpd.H" #include "ipvpd.H" @@ -80,6 +86,10 @@ IpVpdFacade::IpVpdFacade(uint64_t i_vpdSectionSize, ,iv_cachePnorAddr(0x0) ,iv_vpdMsgType(i_vpdMsgType) { + iv_configInfo.vpdReadPNOR = false; + iv_configInfo.vpdReadHW = false; + iv_configInfo.vpdWritePNOR = false; + iv_configInfo.vpdWriteHW = false; TRACUCOMP(g_trac_vpd, "IpVpdFacade::IpVpdFacade> " ); } @@ -137,6 +147,7 @@ errlHndl_t IpVpdFacade::read ( TARGETING::Target * i_target, err = retrieveKeyword( keywordName, recordName, recordOffset, + 0, i_target, io_buffer, io_buflen, @@ -383,6 +394,50 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record, input_args_t i_args ) { errlHndl_t err = NULL; + + if ( iv_configInfo.vpdReadPNOR ) + { + return findRecordOffsetPnor(i_record, o_offset, i_target, i_args); + } + else if ( iv_configInfo.vpdReadHW ) + { + return findRecordOffsetSeeprom(i_record, o_offset, i_target, i_args); + } + else + { + TRACFCOMP( g_trac_vpd, + ERR_MRK"IpVpdFacade::findRecordOffset:vpdReadPNOR and vpdReadHW false!"); + + /*@ + * @errortype + * @reasoncode VPD::VPD_READ_CONFIG_NOT_SET + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_IPVPD_FIND_RECORD_OFFSET + * @userdata1 Target HUID + * @userdata2 <UNUSED> + * @devdesc Both VPD read PNOR and VPD read HW + * configs are set to false + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_FIND_RECORD_OFFSET, + VPD::VPD_READ_CONFIG_NOT_SET, + TARGETING::get_huid(i_target), + 0x0, + true /*Add HB SW Callout*/ ); + err->collectTrace( "VPD", 256 ); + } + return NULL; +} + +// ------------------------------------------------------------------ +// IpVpdFacade::findRecordOffsetPnor +// ------------------------------------------------------------------ +errlHndl_t IpVpdFacade::findRecordOffsetPnor ( const char * i_record, + uint16_t & o_offset, + TARGETING::Target * i_target, + input_args_t i_args ) +{ + errlHndl_t err = NULL; uint64_t tmpOffset = 0x0; char record[RECORD_BYTE_SIZE] = { '\0' }; uint16_t offset = 0x0; @@ -495,6 +550,145 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record, return err; } +// ------------------------------------------------------------------ +// IpVpdFacade::findRecordOffsetSeeprom +// ------------------------------------------------------------------ +errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record, + uint16_t & o_offset, + TARGETING::Target * i_target, + input_args_t i_args ) +{ + errlHndl_t err = NULL; + char l_buffer[256] = { 0 }; + uint16_t offset = 0x0; + + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"IpVpdFacade::findRecordOffsetSeeprom()" ); + + // Skip the ECC data + large resource ID in the VHDR + offset = VHDR_ECC_DATA_SIZE + VHDR_RESOURCE_ID_SIZE; + + // Read PT keyword from VHDR to find the VTOC. + size_t pt_len = sizeof(l_buffer); + err = retrieveKeyword( "PT", "VHDR", offset, 0, i_target, l_buffer, + pt_len, i_args ); + if (err) { + return err; + } + + TocPtRecord *toc_rec = reinterpret_cast<TocPtRecord*>(l_buffer); + if (pt_len < sizeof(TocPtRecord) || + (memcmp(toc_rec->record_name, "VTOC", + sizeof(toc_rec->record_name)) != 0)) + { + TRACFCOMP( g_trac_vpd, + ERR_MRK"IpVpdFacade::findRecordOffset: VHDR is invalid!"); + + /*@ + * @errortype + * @reasoncode VPD::VPD_RECORD_INVALID_VHDR + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM + * @userdata1 VHDR length + * @userdata2 Target HUID + * @devdesc The VHDR was invalid + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM, + VPD::VPD_RECORD_INVALID_VHDR, + pt_len, + TARGETING::get_huid(i_target) ); + + // Could be the VPD of the target wasn't set up properly + // -- DECONFIG so that we can possibly keep booting + err->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_NULL ); + + // Or HB code didn't look for the record properly + err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_LOW); + + err->collectTrace( "VPD" ); + return err; + } + + offset = le16toh( toc_rec->record_offset ) + 1; // skip 'large resource' + + // Read the PT keyword(s) (there may be more than 1) from the VTOC to + // find the requested record. + bool found = false; + for (uint16_t index = 0; !found; ++index) + { + pt_len = sizeof(l_buffer); + err = retrieveKeyword( "PT", "VTOC", offset, index, i_target, l_buffer, + pt_len, i_args ); + if ( err ) { + break; + } + + // Scan through the VTOC PT keyword records looking for a record + // name match. + for (size_t vtoc_pt_offset = 0; vtoc_pt_offset < pt_len; + vtoc_pt_offset += sizeof(TocPtRecord)) + { + toc_rec = reinterpret_cast<TocPtRecord*>(l_buffer + vtoc_pt_offset); + TRACUCOMP( g_trac_vpd, "Scanning record %s", toc_rec->record_name); + + if (memcmp(toc_rec->record_name, i_record, + sizeof(toc_rec->record_name)) == 0) + { + // Byte swap field on output, skip 'large resource' byte + o_offset = le16toh( toc_rec->record_offset ) + 1; + found = true; + break; + } + } + } + + if ( !found && err == NULL ) { + TRACFCOMP( g_trac_vpd, + ERR_MRK"IpVpdFacade::findRecordOffsetSeeprom: " + "No matching Record (%s) found in VTOC!", i_record ); + + /*@ + * @errortype + * @reasoncode VPD::VPD_RECORD_NOT_FOUND + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM + * @userdata1[0:31] Requested Record + * @userdata1[32:63] Requested Keyword + * @userdata2 Target HUID + * @devdesc The requested record was not found in the VPD VTOC. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM, + VPD::VPD_RECORD_NOT_FOUND, + TWO_UINT32_TO_UINT64(i_args.record, + i_args.keyword), + TARGETING::get_huid(i_target) ); + + // Could be the VPD of the target wasn't set up properly + // -- DECONFIG so that we can possibly keep booting + err->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_NULL ); + + // Or HB code didn't look for the record properly + err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_LOW); + + err->collectTrace( "VPD" ); + } + + TRACSSCOMP( g_trac_vpd, + EXIT_MRK"IpVpdFacade::findRecordOffsetSeeprom()" ); + + return err; +} + // ------------------------------------------------------------------ // IpVpdFacade::retrieveKeyword @@ -502,6 +696,7 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record, errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName, const char * i_recordName, uint16_t i_offset, + uint16_t i_index, TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, @@ -520,6 +715,7 @@ errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName, err = findKeywordAddr( i_keywordName, i_recordName, i_offset, + i_index, i_target, keywordSize, byteAddr, @@ -566,7 +762,6 @@ errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName, return err; } - // ------------------------------------------------------------------ // IpVpdFacade::fetchData // ------------------------------------------------------------------ @@ -577,8 +772,52 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, { errlHndl_t err = NULL; + if ( iv_configInfo.vpdReadPNOR ) + { + return fetchDataFromPnor( i_byteAddr, i_numBytes, o_data, i_target ); + } + else if ( iv_configInfo.vpdReadHW ) + { + return fetchDataFromEeprom( i_byteAddr, i_numBytes, o_data, i_target ); + } + else + { + TRACFCOMP( g_trac_vpd, + ERR_MRK"IpVpdFacade::fetchData:vpdReadPNOR and vpdReadHW false!"); + + /*@ + * @errortype + * @reasoncode VPD::VPD_READ_CONFIG_NOT_SET + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_IPVPD_FETCH_DATA + * @userdata1 Target HUID + * @userdata2 <UNUSED> + * @devdesc Both VPD read PNOR and VPD read HW + * configs are set to false + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_FETCH_DATA, + VPD::VPD_READ_CONFIG_NOT_SET, + TARGETING::get_huid(i_target), + 0x0, + true /*Add HB SW Callout*/ ); + err->collectTrace( "VPD", 256 ); + } + return NULL; +} + +// ------------------------------------------------------------------ +// IpVpdFacade::fetchDataFromPnor +// ------------------------------------------------------------------ +errlHndl_t IpVpdFacade::fetchDataFromPnor ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target ) +{ + errlHndl_t err = NULL; + TRACSSCOMP( g_trac_vpd, - ENTER_MRK"IpVpdFacade::fetchData()" ); + ENTER_MRK"IpVpdFacade::fetchDataFromPnor()" ); do { @@ -599,11 +838,45 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, { break; } + } while( 0 ); + TRACSSCOMP( g_trac_vpd, + EXIT_MRK"IpVpdFacade::fetchDataFromPnor()" ); + + return err; +} + +// ------------------------------------------------------------------ +// IpVpdFacade::fetchDataFromEeprom +// ------------------------------------------------------------------ +errlHndl_t IpVpdFacade::fetchDataFromEeprom ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"IpVpdFacade::fetchDataFromEeprom()" ); + + do + { + // Need to read directly from target's EEPROM. + err = DeviceFW::deviceOp( DeviceFW::READ, + i_target, + o_data, + i_numBytes, + DEVICE_EEPROM_ADDRESS( + EEPROM::VPD_PRIMARY, + i_byteAddr ) ); + if( err ) + { + break; + } } while( 0 ); TRACSSCOMP( g_trac_vpd, - EXIT_MRK"IpVpdFacade::fetchData()" ); + EXIT_MRK"IpVpdFacade::fetchDataFromEeprom()" ); return err; } @@ -614,6 +887,7 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, const char * i_recordName, uint16_t i_offset, + uint16_t i_index, TARGETING::Target * i_target, size_t& o_keywordSize, uint64_t& o_byteAddr, @@ -625,7 +899,7 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, uint16_t keywordSize = 0x0; char record[RECORD_BYTE_SIZE] = { '\0' }; char keyword[KEYWORD_BYTE_SIZE] = { '\0' }; - bool matchFound = false; + int matchesFound = 0; TRACSSCOMP( g_trac_vpd, ENTER_MRK"IpVpdFacade::findKeywordAddr()" ); @@ -776,8 +1050,10 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, o_byteAddr = offset - i_offset; //make address relative // found our match, break out - matchFound = true; - break; + matchesFound++; + if ( matchesFound == i_index + 1 ) { + break; + } } else { @@ -787,14 +1063,14 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, } if( err || - matchFound ) + matchesFound == i_index + 1 ) { break; } } while( 0 ); // If keyword not found in expected Record, flag error. - if( !matchFound && + if( matchesFound != i_index + 1 && NULL == err ) { TRACFCOMP( g_trac_vpd, @@ -807,7 +1083,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, * @reasoncode VPD::VPD_KEYWORD_NOT_FOUND * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid VPD::VPD_IPVPD_FIND_KEYWORD_ADDR - * @userdata1 Start of Record Offset + * @userdata1[0:31] Start of Record Offset + * @userdata1[32:63] Keyword Index * @userdata2[0:31] Requested Record * @userdata2[32:63] Requested Keyword * @devdesc Keyword was not found in Record starting at given @@ -816,7 +1093,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, VPD::VPD_IPVPD_FIND_KEYWORD_ADDR, VPD::VPD_KEYWORD_NOT_FOUND, - i_offset, + TWO_UINT32_TO_UINT64( i_offset, + i_index ), TWO_UINT32_TO_UINT64( i_args.record, i_args.keyword ) ); @@ -873,6 +1151,7 @@ errlHndl_t IpVpdFacade::writeKeyword ( const char * i_keywordName, err = findKeywordAddr( i_keywordName, i_recordName, i_offset, + 0, i_target, keywordSize, byteAddr, @@ -890,48 +1169,58 @@ errlHndl_t IpVpdFacade::writeKeyword ( const char * i_keywordName, { break; } - - // Setup info needed to write from PNOR - VPD::pnorInformation info; - info.segmentSize = iv_vpdSectionSize; - info.maxSegments = iv_vpdMaxSections; - info.pnorSection = iv_pnorSection; - err = VPD::writePNOR( i_offset+byteAddr, - keywordSize, - i_buffer, - i_target, - info, - iv_cachePnorAddr, - &iv_mutex ); - if( err ) + if ( iv_configInfo.vpdWriteHW ) { - break; + // @todo RTC 106884 - Need to handle vpd write to HW } + if ( iv_configInfo.vpdWritePNOR ) + { + // Setup info needed to write from PNOR + VPD::pnorInformation info; + info.segmentSize = iv_vpdSectionSize; + info.maxSegments = iv_vpdMaxSections; + info.pnorSection = iv_pnorSection; + err = VPD::writePNOR( i_offset+byteAddr, + keywordSize, + i_buffer, + i_target, + info, + iv_cachePnorAddr, + &iv_mutex ); + if( err ) + { + break; + } + VPD::VpdWriteMsg_t msgdata; - VPD::VpdWriteMsg_t msgdata; - - // Quick double-check that our constants agree with the values in the - // VPD message structure - assert( sizeof(msgdata.record) == RECORD_BYTE_SIZE ); - assert( sizeof(msgdata.keyword) == KEYWORD_BYTE_SIZE ); + // Quick double-check that our constants agree with the values + // in the VPD message structure + assert( sizeof(msgdata.record) == RECORD_BYTE_SIZE ); + assert( sizeof(msgdata.keyword) == KEYWORD_BYTE_SIZE ); - // Finally, send it down to the FSP - msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); - memcpy( msgdata.record, i_recordName, RECORD_BYTE_SIZE ); - memcpy( msgdata.keyword, i_keywordName, KEYWORD_BYTE_SIZE ); - err = VPD::sendMboxWriteMsg( keywordSize, - i_buffer, - i_target, - iv_vpdMsgType, - msgdata ); + // Finally, send it down to the FSP + msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); + memcpy( msgdata.record, i_recordName, RECORD_BYTE_SIZE ); + memcpy( msgdata.keyword, i_keywordName, KEYWORD_BYTE_SIZE ); + err = VPD::sendMboxWriteMsg( keywordSize, + i_buffer, + i_target, + iv_vpdMsgType, + msgdata ); - if( err ) + if( err ) + { + break; + } + } + else { + // No PNOR, just eat the write attempt. + TRACFCOMP(g_trac_vpd, "VPD record %s:%s - write ignored", + i_keywordName, i_recordName); break; } - - } while(0); TRACSSCOMP( g_trac_vpd, diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H index 46d6584b2..95f110ef0 100644 --- a/src/usr/vpd/ipvpd.H +++ b/src/usr/vpd/ipvpd.H @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -50,9 +53,25 @@ class IpVpdFacade KEYWORD_SIZE_BYTE_SIZE = 1, RECORD_TOC_UNUSED = 2, RT_SKIP_BYTES = 3, + VHDR_ECC_DATA_SIZE = 11, + VHDR_RESOURCE_ID_SIZE = 1, }; /** + * @brief Structure representing the format of each record + * in the PT keyword of the VTOC or VHDR. + */ + struct TocPtRecord { + char record_name[4]; + // All uint16 fields are stored in little endian. + uint16_t record_type; + uint16_t record_offset; + uint16_t record_length; + uint16_t ecc_offset; + uint16_t ecc_length; + } PACKED; + + /** * @brief typdef for ipVpdRecord values */ typedef uint32_t ipVpdRecord; @@ -88,6 +107,16 @@ class IpVpdFacade char keywordName[KEYWORD_BYTE_SIZE+1]; } keywordInfo; + /** + * @brief Structure defining where to read/write VPD data + */ + typedef struct + { + bool vpdReadPNOR; + bool vpdReadHW; + bool vpdWritePNOR; + bool vpdWriteHW; + } configInfo; /** * @brief Constructor @@ -213,8 +242,8 @@ class IpVpdFacade const char *& o_keyword ); /** - * @brief This function will read the VPD TOC to find the offset where the - * given record is located within the chunk of data. + * @brief This function calls the PNOR or EEPROM version of + * the findRecordOffset fuction based on the configInfo. * * @param[in] i_record - String value for the record to look for. * @@ -233,6 +262,46 @@ class IpVpdFacade input_args_t i_args ); /** + * @brief This function will read the VPD TOC to find the offset where the + * given record is located within the chunk of data. + * + * @param[in] i_record - String value for the record to look for. + * + * @param[out] o_offset - The offset where the record is located. + * + * @param[in] i_target - The target to retrieve the data for. + * + * @param[in] i_args - The input arguments. + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t findRecordOffsetPnor ( const char * i_record, + uint16_t & o_offset, + TARGETING::Target * i_target, + input_args_t i_args ); + + /** + * @brief This function will read the VPD VTOC to find the offset where the + * given record is located within the chunk of data. + * + * @param[in] i_record - String value for the record to look for. + * + * @param[out] o_offset - The offset where the record is located. + * + * @param[in] i_target - The target to retrieve the data for. + * + * @param[in] i_args - The input arguments. + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t findRecordOffsetSeeprom ( const char * i_record, + uint16_t & o_offset, + TARGETING::Target * i_target, + input_args_t i_args ); + + /** * @brief This function will read the required keyword from the VPD data. * * @param[in] i_keywordName - String representation of the keyword. @@ -241,6 +310,9 @@ class IpVpdFacade * * @param[in] i_offset - The offset to start reading. * + * @param[in] i_index - The index of the keyword to return if there are + * multiple instances of the same keyword. + * * @param[in] i_target - The target to retrieve data for. * * @param[out] io_buffer - The buffer to place the data in. @@ -259,6 +331,7 @@ class IpVpdFacade errlHndl_t retrieveKeyword ( const char * i_keywordName, const char * i_recordName, uint16_t i_offset, + uint16_t i_index, TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, @@ -302,7 +375,10 @@ class IpVpdFacade * * @param[in] i_recordName - String representation of the record. * - * @param[in] i_offset - The offset to start writing. + * @param[in] i_offset - The offset to start searching. + * + * @param[in] i_index - The index of the keyword to return if there are + * multiple instances of the same keyword. * * @param[in] i_target - The target to write data for. * @@ -319,13 +395,15 @@ class IpVpdFacade errlHndl_t findKeywordAddr ( const char * i_keywordName, const char * i_recordName, uint16_t i_offset, + uint16_t i_index, TARGETING::Target * i_target, size_t& o_keywordSize, uint64_t& o_byteAddr, input_args_t i_args ); + /** - * @brief This function actually reads the data from the source of the VPD - * data. + * @brief This function calls the PNOR or EEPROM version of + * the fetchData function based on the configInfo * * @param[in] i_byteAddr - The offset to be read. * @@ -343,6 +421,44 @@ class IpVpdFacade void * o_data, TARGETING::Target * i_target ); + /** + * @brief This function actually reads the data from PNOR + * + * @param[in] i_byteAddr - The offset to be read. + * + * @param[in] i_numBytes - The number of bytes to read. + * + * @param[out] o_data - The data buffer where the data will be placed. + * + * @param[in] i_target - Target device. + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t fetchDataFromPnor ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target ); + + /** + * @brief This function actually reads the data from EEPROM + * + * @param[in] i_byteAddr - The offset to be read. + * + * @param[in] i_numBytes - The number of bytes to read. + * + * @param[out] o_data - The data buffer where the data will be placed. + * + * @param[in] i_target - Target device. + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t fetchDataFromEeprom ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target ); + /** * @brief This function compares 2 ipvpd record values. Used for binary @@ -443,13 +559,19 @@ class IpVpdFacade * @brief cached PNOR offset for VPD * */ - uint64_t iv_cachePnorAddr; + uint64_t iv_cachePnorAddr; - /** - * @brief cached PNOR offset for VPD - * - */ - VPD::VPD_MSG_TYPE iv_vpdMsgType; + /** + * @brief cached PNOR offset for VPD + * + */ + VPD::VPD_MSG_TYPE iv_vpdMsgType; + + /** + * @brief Config defining where to read/write + * VPD data + */ + configInfo iv_configInfo; }; diff --git a/src/usr/vpd/mvpd.C b/src/usr/vpd/mvpd.C index 169feefdf..b9d411298 100644 --- a/src/usr/vpd/mvpd.C +++ b/src/usr/vpd/mvpd.C @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -33,6 +36,7 @@ #include <vfs/vfs.H> #include <vpd/vpdreasoncodes.H> #include <vpd/mvpdenums.H> +#include <config.h> #include "mvpd.H" #include "ipvpd.H" @@ -193,4 +197,25 @@ IpVpdFacade(MVPD::SECTION_SIZE, VPD::VPD_WRITE_PROC) { TRACUCOMP(g_trac_vpd, "MvpdFacade::MvpdFacade> " ); + +#ifdef CONFIG_MVPD_READ_FROM_PNOR + iv_configInfo.vpdReadPNOR = true; +#else + iv_configInfo.vpdReadPNOR = false; +#endif +#ifdef CONFIG_MVPD_READ_FROM_HW + iv_configInfo.vpdReadHW = true; +#else + iv_configInfo.vpdReadHW = false; +#endif +#ifdef CONFIG_MVPD_WRITE_TO_PNOR + iv_configInfo.vpdWritePNOR = true; +#else + iv_configInfo.vpdWritePNOR = false; +#endif +#ifdef CONFIG_MVPD_WRITE_TO_HW + iv_configInfo.vpdWriteHW = true; +#else + iv_configInfo.vpdWriteHW = false; +#endif } diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C index 15e53e9fa..4480b507c 100755 --- a/src/usr/vpd/spd.C +++ b/src/usr/vpd/spd.C @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -36,6 +39,8 @@ #include <errl/errludtarget.H> #include <targeting/common/targetservice.H> #include <devicefw/driverif.H> +#include <devicefw/userif.H> +#include <i2c/eepromif.H> #include <vfs/vfs.H> #include <pnor/pnorif.H> #include <vpd/vpdreasoncodes.H> @@ -45,6 +50,7 @@ #include "spdDDR3.H" #include "spdDDR4.H" #include "errlud_vpd.H" +#include <config.h> // ---------------------------------------------- // Trace definitions @@ -389,6 +395,16 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, { if( likely( g_usePNOR ) ) { +#ifdef CONFIG_DJVPD_READ_FROM_HW + // Need to read directly from target's EEPROM. + err = DeviceFW::deviceOp( DeviceFW::READ, + i_target, + o_data, + i_numBytes, + DEVICE_EEPROM_ADDRESS( + EEPROM::VPD_PRIMARY, + i_byteAddr ) ); +#elif CONFIG_DJVPD_READ_FROM_PNOR // Setup info needed to read from PNOR VPD::pnorInformation info; info.segmentSize = DIMM_SPD_SECTION_SIZE; @@ -401,7 +417,7 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, info, g_spdPnorAddr, &g_spdMutex ); - +#endif // CONFIG_DJVPD_READ_FROM_PNOR if( err ) { break; |