summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd
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
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')
-rw-r--r--src/usr/vpd/HBconfig77
-rw-r--r--src/usr/vpd/cvpd.C26
-rwxr-xr-xsrc/usr/vpd/dimmPres.C24
-rw-r--r--src/usr/vpd/ipvpd.C377
-rw-r--r--src/usr/vpd/ipvpd.H146
-rw-r--r--src/usr/vpd/mvpd.C27
-rwxr-xr-xsrc/usr/vpd/spd.C20
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;
OpenPOWER on IntegriCloud