summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd/ipvpd.C
diff options
context:
space:
mode:
authorCorey Swenson <cswenson@us.ibm.com>2014-06-18 16:09:55 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-07-01 13:34:57 -0500
commit2cc1c594ad2b05919d1742625de0da83ffd7f01d (patch)
tree57bbbe923325245e809ea51a96c60ffe79b18600 /src/usr/vpd/ipvpd.C
parent3bcf5b7982bb8a2d9227dbff7be4ff2ce5fec05c (diff)
downloadtalos-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/ipvpd.C')
-rw-r--r--src/usr/vpd/ipvpd.C377
1 files changed, 333 insertions, 44 deletions
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,
OpenPOWER on IntegriCloud