summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd/runtime/rt_vpd.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/vpd/runtime/rt_vpd.C')
-rw-r--r--src/usr/vpd/runtime/rt_vpd.C167
1 files changed, 144 insertions, 23 deletions
diff --git a/src/usr/vpd/runtime/rt_vpd.C b/src/usr/vpd/runtime/rt_vpd.C
index d907aee2e..d73b0dc1a 100644
--- a/src/usr/vpd/runtime/rt_vpd.C
+++ b/src/usr/vpd/runtime/rt_vpd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -28,9 +28,14 @@
#include <errl/errludtarget.H>
#include <vpd/vpdreasoncodes.H>
#include <initservice/initserviceif.H>
-#include "../vpd.H"
+#include <devicefw/driverif.H>
+#include <i2c/eepromif.H>
#include <runtime/interface.h>
#include <targeting/common/util.H>
+#include "vpd.H"
+#include "mvpd.H"
+#include "cvpd.H"
+#include "spd.H"
// ----------------------------------------------
// Trace definitions
@@ -261,29 +266,145 @@ errlHndl_t writePNOR ( uint64_t i_byteAddr,
mutex_t * i_mutex )
{
errlHndl_t err = NULL;
- // Does VPD write ever need to be supported at runtime?
- TRACFCOMP(g_trac_vpd, ERR_MRK
- "RT writePNOR: VPD write not supported at runtime.");
- /*@
- * @errortype
- * @reasoncode VPD::VPD_RT_WRITE_NOT_SUPPORTED
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid VPD::VPD_RT_WRITE_PNOR
- * @userdata1 target huid
- * @userdata2 VPD type
- * @devdesc VPD write not supported at runtime
- */
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- VPD::VPD_RT_WRITE_PNOR,
- VPD::VPD_RT_WRITE_NOT_SUPPORTED,
- get_huid(i_target),
- i_pnorInfo.pnorSection);
+ int64_t vpdLocation = 0;
+ uint64_t addr = 0x0;
+ const char * writeAddr = NULL;
- err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
- HWAS::SRCI_PRIORITY_HIGH);
+ TRACSSCOMP( g_trac_vpd,
+ ENTER_MRK"RT writePNOR()" );
- err->collectTrace( "VPD", 256);
+ do
+ {
+ if(INITSERVICE::spBaseServicesEnabled())
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"rt_vpd:writePNOR not supported with FSP");
+
+ /*@
+ * @errortype
+ * @reasoncode VPD::VPD_RT_WRITE_NOT_SUPPORTED
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid VPD::VPD_RT_WRITE_PNOR
+ * @userdata1 Target
+ * @userdata2 0
+ * @devdesc MBOX send not supported in HBRT
+ */
+ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD::VPD_RT_WRITE_PNOR,
+ VPD::VPD_RT_WRITE_NOT_SUPPORTED,
+ TARGETING::get_huid(i_target),
+ 0);
+
+ err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+
+ err->collectTrace( "VPD", 256);
+
+ break;
+ }
+
+ //----------------------------
+ // Write memory version of VPD
+ //----------------------------
+ // 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 write: 0x%08x",
+ addr );
+
+ // Write fake VPD in main-store
+ writeAddr = reinterpret_cast<const char *>( addr );
+ memcpy( (void*)(writeAddr),
+ i_data,
+ i_numBytes );
+
+ //--------------------------------
+ // Write PNOR cache version of VPD
+ //--------------------------------
+
+ // Check if the VPD PNOR cache is loaded for this target
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ if( vpdSwitches.pnorCacheValid )
+ {
+ PNOR::SectionInfo_t info;
+ writeAddr = NULL;
+
+ // Get SPD PNOR section info from PNOR RP
+ err = PNOR::getSectionInfo( i_pnorInfo.pnorSection,
+ info );
+ if( err )
+ {
+ break;
+ }
+
+ addr = info.vaddr;
+
+ // 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 write: 0x%08x",
+ addr );
+
+ // Write the data
+ writeAddr = reinterpret_cast<const char*>( addr );
+ memcpy( (void*)(writeAddr),
+ i_data,
+ i_numBytes );
+
+ // Flush the page to make sure it gets to the PNOR
+ err = PNOR::flush( info.id );
+ if( err )
+ {
+ break;
+ }
+ }
+
+ //------------------------
+ // Write HW version of VPD
+ //------------------------
+ err = DeviceFW::deviceOp( DeviceFW::WRITE,
+ i_target,
+ i_data,
+ i_numBytes,
+ DEVICE_EEPROM_ADDRESS(
+ EEPROM::VPD_PRIMARY,
+ i_byteAddr ) );
+ if( err )
+ {
+ break;
+ }
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_vpd,
+ EXIT_MRK"RT writePNOR()" );
return err;
}
@@ -375,7 +496,7 @@ bool resolveVpdSource( TARGETING::Target * i_target,
// PNOR needs to be loaded before we can use it
TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
- if( vpdSwitches.pnorLoaded )
+ if( vpdSwitches.pnorCacheValid )
{
o_vpdSource = VPD::PNOR;
}
OpenPOWER on IntegriCloud