Merge pull request #73 from geissonator/master
Enable SBE Updates
diff --git a/openpower/configs/hostboot/habanero.config b/openpower/configs/hostboot/habanero.config
index 8c87193..3a593a8 100755
--- a/openpower/configs/hostboot/habanero.config
+++ b/openpower/configs/hostboot/habanero.config
@@ -26,10 +26,9 @@
set PALMETTO_VDDR
# to disable sbe updates
-set NO_SBE_UPDATES
-
+# set NO_SBE_UPDATES
# Enable SBE updates
-#set SBE_UPDATE_INDEPENDENT
+set SBE_UPDATE_INDEPENDENT
unset PCIE_HOTPLUG_CONTROLLER
diff --git a/openpower/configs/hostboot/palmetto.config b/openpower/configs/hostboot/palmetto.config
index 2b30fbc..8e11a5e 100755
--- a/openpower/configs/hostboot/palmetto.config
+++ b/openpower/configs/hostboot/palmetto.config
@@ -26,10 +26,9 @@
set PALMETTO_VDDR
# to disable sbe updates
-set NO_SBE_UPDATES
-
+#set NO_SBE_UPDATES
# Enable SBE updates
-# set SBE_UPDATE_INDEPENDENT
+set SBE_UPDATE_INDEPENDENT
unset PCIE_HOTPLUG_CONTROLLER
diff --git a/openpower/package/hostboot/hostboot-0009-GOLDEN-SBE-Update-Support-Reconcile-SBE-images-and-P.patch b/openpower/package/hostboot/hostboot-0009-GOLDEN-SBE-Update-Support-Reconcile-SBE-images-and-P.patch
new file mode 100644
index 0000000..94e4c49
--- /dev/null
+++ b/openpower/package/hostboot/hostboot-0009-GOLDEN-SBE-Update-Support-Reconcile-SBE-images-and-P.patch
@@ -0,0 +1,2028 @@
+From 842770c162544b35609528b205d7c015454593fa Mon Sep 17 00:00:00 2001
+From: Mike Baiocchi <baiocchi@us.ibm.com>
+Date: Tue, 17 Feb 2015 13:07:13 -0600
+Subject: [PATCH 4/7] GOLDEN SBE Update Support - Reconcile SBE images and PNOR sides
+
+This code adds a new function at istep 6 to reconcile the two
+SBE Seeproms with the PNOR side and mode (ie, 2-sided, golden, etc).
+It also updates what happens in istep 9 in SBE_UPDATE_INDEPENDENT
+mode.
+
+Change-Id: If71ca52338a179b8cf38cfa336d9790737844715
+RTC: 120734
+(cherry picked from commit fe9afa4e7a3b0eb0e9ae16abb943039aacf34e09)
+---
+ src/include/usr/sbe/sbeif.H | 13 +-
+ src/include/usr/sbe/sbereasoncodes.H | 10 +-
+ src/usr/hwpf/hwp/slave_sbe/slave_sbe.C | 12 +
+ src/usr/sbe/HBconfig | 6 +-
+ src/usr/sbe/makefile | 5 +-
+ src/usr/sbe/sbe_resolve_sides.C | 1363 ++++++++++++++++++++++++++++++++
+ src/usr/sbe/sbe_resolve_sides.H | 259 ++++++
+ src/usr/sbe/sbe_update.C | 124 +++-
+ 8 files changed, 1753 insertions(+), 39 deletions(-)
+ create mode 100644 src/usr/sbe/sbe_resolve_sides.C
+ create mode 100644 src/usr/sbe/sbe_resolve_sides.H
+
+diff --git a/src/include/usr/sbe/sbeif.H b/src/include/usr/sbe/sbeif.H
+index 8706e91..9cf20c6 100644
+--- a/src/include/usr/sbe/sbeif.H
++++ b/src/include/usr/sbe/sbeif.H
+@@ -5,7 +5,9 @@
+ /* */
+ /* OpenPOWER HostBoot Project */
+ /* */
+-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
++/* Contributors Listed Below - COPYRIGHT 2013,2015 */
++/* [+] 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. */
+@@ -66,6 +68,15 @@ namespace SBE
+ */
+ errlHndl_t updateProcessorSbeSeeproms();
+
++ /**
++ * @brief Iterates through all the functional processors and resolves
++ * the Hostboot Base Addresses (HBB) in each SBE Image and performs
++ * any necessary operations related to GOLDEN side support.
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t resolveProcessorSbeSeeproms();
++
+
+ } //end namespace SBE
+
+diff --git a/src/include/usr/sbe/sbereasoncodes.H b/src/include/usr/sbe/sbereasoncodes.H
+index a09bb68..effb69e 100644
+--- a/src/include/usr/sbe/sbereasoncodes.H
++++ b/src/include/usr/sbe/sbereasoncodes.H
+@@ -5,7 +5,9 @@
+ /* */
+ /* OpenPOWER HostBoot Project */
+ /* */
+-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
++/* Contributors Listed Below - COPYRIGHT 2013,2015 */
++/* [+] 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. */
+@@ -54,6 +56,10 @@ enum sbeModuleId
+ SBE_CUSTOMIZE_IMG = 0x0B,
+ SBE_PERFORM_UPDATE_ACTIONS = 0x0C,
+ SBE_MASTER_VERSION_COMPARE = 0x0D,
++ SBE_RESOLVE_HBB_ADDR = 0x0E,
++ SBE_READ_SBE_IMAGE = 0x0F,
++ SBE_WRITE_SBE_IMAGE = 0x10,
++ SBE_GET_SBE_IMAGE_SIZE = 0x11,
+ };
+
+ /**
+@@ -91,6 +97,8 @@ enum sbeReasonCode
+ SBE_MISCOMPARE_WITH_MASTER_VERSION = SBE_COMP_ID | 0x13,
+ SBE_ERROR_ON_UPDATE = SBE_COMP_ID | 0x14,
+ SBE_MASTER_VERSION_DOWNLEVEL = SBE_COMP_ID | 0x15,
++ SBE_IMAGE_GET_SET_SCALAR_FAIL = SBE_COMP_ID | 0x16,
++
+ };
+
+ }; // end SBE
+diff --git a/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C b/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C
+index 49225a4..fe568e2 100644
+--- a/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C
++++ b/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C
+@@ -175,6 +175,18 @@ void* call_host_slave_sbe_config(void *io_pArgs)
+
+ }
+ }
++
++ // Resolve the side characteristics of the Processor SBE Seeproms
++ errlHndl_t err = SBE::resolveProcessorSbeSeeproms();
++ if ( err )
++ {
++ // Create IStep error log and cross reference error that occurred
++ l_stepError.addErrorDetails( err );
++
++ // Commit Error
++ errlCommit( err, HWPF_COMP_ID );
++ }
++
+ TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "call_host_slave_sbe_config exit" );
+
+diff --git a/src/usr/sbe/HBconfig b/src/usr/sbe/HBconfig
+index 0fa2441..fd2a8d0 100644
+--- a/src/usr/sbe/HBconfig
++++ b/src/usr/sbe/HBconfig
+@@ -20,9 +20,9 @@ config SBE_UPDATE_INDEPENDENT
+ depends on !SBE_UPDATE_SEQUENTIAL && !SBE_UPDATE_SIMULTANEOUS
+ help
+ If an update is necessary, and if the "current" SBE SEEPROM of this
+- IPL is not the 'GOLDEN' SBE SEEPROM, then only the current SBE SEEPROM
+- will be updated. After the update a re-IPL request will be issued.
+- The other SBE SEEPROM, whether 'GOLDEN' or not, will not be updated.
++ IPL is not pointing at PNOR's 'GOLDEN' side, then only the current SBE
++ SEEPROM will be updated. After the update a re-IPL request will be
++ issued. The other SBE SEEPROM will not be updated.
+
+ config NO_SBE_UPDATES
+ default n
+diff --git a/src/usr/sbe/makefile b/src/usr/sbe/makefile
+index 06159ff..c45206e 100644
+--- a/src/usr/sbe/makefile
++++ b/src/usr/sbe/makefile
+@@ -5,7 +5,9 @@
+ #
+ # OpenPOWER HostBoot Project
+ #
+-# COPYRIGHT International Business Machines Corp. 2013,2014
++# Contributors Listed Below - COPYRIGHT 2013,2015
++# [+] 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 +38,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/include
+ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build
+
+ OBJS += sbe_update.o
++OBJS += sbe_resolve_sides.o
+
+ SUBDIRS += test.d
+
+diff --git a/src/usr/sbe/sbe_resolve_sides.C b/src/usr/sbe/sbe_resolve_sides.C
+new file mode 100644
+index 0000000..df9958d
+--- /dev/null
++++ b/src/usr/sbe/sbe_resolve_sides.C
+@@ -0,0 +1,1363 @@
++/* IBM_PROLOG_BEGIN_TAG */
++/* This is an automatically generated prolog. */
++/* */
++/* $Source: src/usr/sbe/sbe_resolve_sides.C $ */
++/* */
++/* OpenPOWER HostBoot Project */
++/* */
++/* Contributors Listed Below - COPYRIGHT 2015 */
++/* [+] 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. */
++/* You may obtain a copy of the License at */
++/* */
++/* http://www.apache.org/licenses/LICENSE-2.0 */
++/* */
++/* Unless required by applicable law or agreed to in writing, software */
++/* distributed under the License is distributed on an "AS IS" BASIS, */
++/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
++/* implied. See the License for the specific language governing */
++/* permissions and limitations under the License. */
++/* */
++/* IBM_PROLOG_END_TAG */
++
++#include <trace/interface.H>
++#include <errl/errlentry.H>
++#include <errl/errlmanager.H>
++#include <errl/errludtarget.H>
++#include <errl/errlreasoncodes.H>
++#include <errl/hberrltypes.H>
++#include <targeting/common/predicates/predicatectm.H>
++#include <targeting/common/utilFilter.H>
++#include <targeting/common/targetservice.H>
++#include <util/misc.H>
++#include <pnor/pnorif.H>
++#include <pnor/ecc.H>
++#include <devicefw/driverif.H>
++#include <sys/mm.h>
++#include <sys/misc.h>
++#include <hwas/common/deconfigGard.H>
++#include <initservice/initserviceif.H>
++#include <config.h>
++#include <ipmi/ipmiwatchdog.H>
++#include <ipmi/ipmisensor.H>
++#include <sbe/sbeif.H>
++#include <sbe/sbereasoncodes.H>
++#include "sbe_resolve_sides.H"
++#include "sbe_update.H"
++
++// fapi support
++#include <fapi.H>
++#include <fapiHwpExecutor.H>
++#include <hwpf/plat/fapiPlatHwpInvoker.H>
++#include <hwpf/plat/fapiPlatTrace.H>
++
++//Procedures
++#include <p8_xip_customize.H>
++#include <sbe_xip_image.h>
++#include <p8_image_help_base.H>
++
++// ----------------------------------------------
++// Trace definitions
++// ----------------------------------------------
++extern trace_desc_t* g_trac_sbe;
++
++// ------------------------
++// Macros for unit testing
++//#define TRACUCOMP(args...) TRACFCOMP(args)
++#define TRACUCOMP(args...)
++
++
++using namespace ERRORLOG;
++using namespace TARGETING;
++
++namespace SBE
++{
++ enum {
++ SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE,
++ RING_BUF1_VADDR = FIXED_SEEPROM_WORK_SPACE + SBE_IMG_VADDR,
++ RING_BUF2_VADDR = RING_BUF1_VADDR + FIXED_RING_BUF_SIZE,
++ //NOTE: recycling the same memory space for different
++ //steps in the process.
++ SBE_ECC_IMG_VADDR = RING_BUF1_VADDR,
++ SBE_ECC_IMG_MAX_SIZE = VMM_VADDR_SBE_UPDATE_END - SBE_ECC_IMG_VADDR,
++ };
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t resolveProcessorSbeSeeproms()
++{
++ errlHndl_t err = NULL;
++ errlHndl_t err_cleanup = NULL;
++ sbeResolveState_t sideState;
++ bool l_cleanupVmmSpace = false;
++ bool l_restartNeeded = false;
++
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"resolveProcessorSbeSeeproms()" );
++
++ do{
++
++#ifdef CONFIG_NO_SBE_UPDATES
++ TRACFCOMP( g_trac_sbe, INFO_MRK"resolveProcessorSbeSeeproms() - "
++ "SBE updates not configured");
++ break;
++#endif
++
++#ifdef CONFIG_SBE_UPDATE_SIMULTANEOUS
++ TRACFCOMP( g_trac_sbe, INFO_MRK"resolveProcessorSbeSeeproms() - "
++ "Do Nothing in SBE_UPDATE_SIMULTANEOUS mode");
++ break;
++#endif
++
++#ifdef CONFIG_SBE_UPDATE_SEQUENTIAL
++ // Check if FSP-services are enabled and if we're running in simics
++ if ( !INITSERVICE::spBaseServicesEnabled() &&
++ !Util::isSimicsRunning() )
++ {
++ assert (false, "resolveProcessorSbeSeeproms() - "
++ "SBE_UPDATE_SEQUENTIAL mode, but FSP-services are not "
++ "enabled - Invalid Configuration");
++ }
++ else
++ {
++ TRACUCOMP( g_trac_sbe, INFO_MRK"resolveProcessorSbeSeeproms() - "
++ "Do Nothing in SBE_UPDATE_INDEPENDENT mode with FSP-"
++ "services enabled or running in simics");
++ break;
++ }
++#endif
++
++ // Get Target Service, and the system target.
++ TargetService& tS = targetService();
++ TARGETING::Target* sys = NULL;
++ (void) tS.getTopLevelTarget( sys );
++ assert(sys, "resolveProcessorSbeSeeproms() system target is NULL");
++
++
++ //Make sure procedure constants keep within expected range.
++ assert((FIXED_SEEPROM_WORK_SPACE <= VMM_SBE_UPDATE_SIZE/2),
++ "resolveProcessorSbeSeeproms() FIXED_SEEPROM_WORK_SPACE "
++ "too large");
++ assert((FIXED_RING_BUF_SIZE <= VMM_SBE_UPDATE_SIZE/4),
++ "resolveProcessorSbeSeeproms() FIXED_RING_BUF_SIZE too "
++ "large");
++
++ // Create VMM space for p8_xip_customize() procedure
++ err = createSbeImageVmmSpace();
++ if (err)
++ {
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"resolveProcessorSbeSeeproms: "
++ "createSbeImageVmmSpace() Failed. ",
++ "rc=0x%.4X", err->reasonCode() );
++
++ break;
++ }
++ else
++ {
++ // Make sure cleanup gets called
++ l_cleanupVmmSpace = true;
++ }
++
++ /*****************************************************************/
++ /* Iterate over all the functional processors and do for each: */
++ /*****************************************************************/
++ TARGETING::TargetHandleList procList;
++ TARGETING::getAllChips(procList,
++ TARGETING::TYPE_PROC,
++ true); // true: return functional targets
++
++ if( ( 0 == procList.size() ) ||
++ ( NULL == procList[0] ) )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"resolveProcessorSbeSeeproms() - "
++ "No functional processors Found!" );
++ break;
++ }
++
++ for(uint32_t i=0; i<procList.size(); i++)
++ {
++ /***********************************************/
++ /* Get Side This Processor did/will boot from */
++ /***********************************************/
++ memset(&sideState, 0, sizeof(sideState));
++ sideState.tgt = procList[i];
++
++ err = getSideState(sideState);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "resolveProcessorSbeSeeproms: Error returned "
++ "from getSideState() "
++ "rc=0x%.4X, Target UID=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(sideState.tgt));
++ // Don't break - handle error at the end of the loop
++ }
++
++
++ /**********************************************/
++ /* Determine the necessary actions */
++ /**********************************************/
++ // Skip if we got an error previously
++ if ( err == NULL )
++ {
++ err = getSideActions(sideState);
++ if (err)
++ {
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"resolveProcessorSbeSeeproms: "
++ "getSideActions() Failed "
++ "rc=0x%.4X, Target UID=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(sideState.tgt));
++
++ // Don't break - handle error at the end of the loop,
++ }
++ }
++
++ /**********************************************/
++ /* Perform the necessary actions */
++ /**********************************************/
++ // Skip if we got an error previously
++ if ( err == NULL )
++ {
++ err = performSideActions(sideState);
++ if (err)
++ {
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"resolveProcessorSbeSeeproms: "
++ "performSideActions() Failed "
++ "rc=0x%.4X, Target UID=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(sideState.tgt));
++
++ // Don't break - handle error at the end of the loop,
++ }
++ else
++ {
++ // Target updated without failure, so set IPL_RESTART
++ // flag, if necessary
++ if (sideState.actions & REIPL)
++ {
++ l_restartNeeded = true;
++ }
++ }
++ }
++
++ /**********************************************/
++ /* Handle Errors */
++ /**********************************************/
++
++ if ( err )
++ {
++ // Something failed for this target.
++
++ // Commit the error here and move on to the next target,
++ // or if no targets left, will just continue the IPL
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"resolveProcessorSbeSeeproms: "
++ "Committing Error Log rc=0x%.4X eid=0x%.8X "
++ "plid=0x%.8X for Target UID=0x%X, but "
++ "continuing procedure",
++ err->reasonCode(),
++ err->eid(),
++ err->plid(),
++ TARGETING::get_huid(sideState.tgt));
++ errlCommit( err, SBE_COMP_ID );
++ }
++
++
++ } //end of Target for loop collecting each target's SBE State
++
++
++ /**************************************************************/
++ /* Perform System Operation */
++ /**************************************************************/
++ // Restart IPL if SBE Update requires it
++ if ( l_restartNeeded == true )
++ {
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"resolveProcessorSbeSeeprom: Restart "
++ "Needed (%d).",
++ l_restartNeeded);
++
++#ifdef CONFIG_BMC_IPMI
++ sbePreShutdownIpmiCalls();
++#endif
++
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"resolveProcessorSbeSeeproms: Calling "
++ "INITSERVICE::doShutdown() with "
++ "SBE_UPDATE_REQUEST_REIPL = 0x%X",
++ SBE_UPDATE_REQUEST_REIPL );
++ INITSERVICE::doShutdown(SBE_UPDATE_REQUEST_REIPL);
++ }
++
++ }while(0);
++
++
++ // Cleanup VMM Workspace
++ if ( l_cleanupVmmSpace == true )
++ {
++ err_cleanup = cleanupSbeImageVmmSpace();
++ if ( err_cleanup != NULL )
++ {
++
++ if ( err != NULL )
++ {
++ // 2 error logs, so commit the cleanup log here
++ TRACFCOMP( g_trac_sbe,
++ ERR_MRK"resolveProcessorSbeSeeproms: Previous "
++ "error (rc=0x%X) before cleanupSbeImageVmmSpace"
++ "() failed. Committing cleanup error (rc=0x%X) "
++ "and returning original error",
++ err->reasonCode(), err_cleanup->reasonCode() );
++
++ errlCommit( err_cleanup, SBE_COMP_ID );
++ }
++ else
++ {
++ // no previous error, so returning cleanup error
++ TRACFCOMP( g_trac_sbe,
++ ERR_MRK"resolveProcessorSbeSeeproms: "
++ "cleanupSbeImageVmmSpace() failed.",
++ "rc=0x%.4X", err_cleanup->reasonCode() );
++ err = err_cleanup;
++ }
++ }
++ }
++
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"resolveProcessorSbeSeeproms()" );
++
++ return err;
++}
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t getSideState(sbeResolveState_t& io_sideState)
++{
++ errlHndl_t err = NULL;
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"getSideState()" );
++
++ do{
++
++ /***********************************************/
++ /* Get Side This Processor did/will boot from */
++ /***********************************************/
++ PNOR::sbeSeepromSide_t tmp_cur_side = PNOR::SBE_SEEPROM_INVALID;
++ err = PNOR::getSbeBootSeeprom(io_sideState.tgt, tmp_cur_side);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "resolveProcessorSbeSeeproms() - Error returned "
++ "from PNOR::getSbeBootSeeprom() "
++ "rc=0x%.4X, Target UID=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sideState.tgt));
++ break;
++ }
++
++ io_sideState.cur_side = tmp_cur_side;
++
++ io_sideState.alt_side = (tmp_cur_side == PNOR::SBE_SEEPROM0)
++ ? PNOR::SBE_SEEPROM1 : PNOR::SBE_SEEPROM0;
++
++ /**********************************************/
++ /* Get PNOR Side Information */
++ /**********************************************/
++ PNOR::SideId tmp_side = PNOR::WORKING;
++ PNOR::SideInfo_t tmp_side_info;
++ err = PNOR::getSideInfo (tmp_side, tmp_side_info);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "resolveProcessorSbeSeeproms() - Error returned "
++ "from PNOR::getSideInfo() "
++ "rc=0x%.4X, Target UID=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sideState.tgt));
++ break;
++ }
++
++ io_sideState.pnor_sideId = tmp_side_info.id;
++ io_sideState.pnor_side = tmp_side_info.side;
++ io_sideState.pnor_isGolden = tmp_side_info.isGolden;
++ io_sideState.pnor_hasOtherSide = tmp_side_info.hasOtherSide;
++
++ }while(0);
++
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"getSideState(): cur/alt=%d/%d. Side-%c(%d): "
++ "isGolden=%d, hasOtherSide=%d",
++ io_sideState.cur_side, io_sideState.alt_side,
++ io_sideState.pnor_side, io_sideState.pnor_sideId,
++ io_sideState.pnor_isGolden, io_sideState.pnor_hasOtherSide );
++
++ return err;
++}
++
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t getSideActions(sbeResolveState_t& io_sideState)
++{
++ errlHndl_t err = NULL;
++ uint32_t l_actions = NO_ACTIONS;
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"getSideActions()" );
++
++ do{
++
++ // Check if PNOR is running from its GOLDEN side
++ if ( io_sideState.pnor_isGolden == true )
++ {
++
++ // If Booting From Seeprom that is pointing to PNOR's GOLDEN Side
++ // and is possibly the READ_ONLY_SEEPROM - No Re-IPL
++ if ( io_sideState.cur_side == READ_ONLY_SEEPROM )
++ {
++ l_actions |= COPY_READ_ONLY_TO_WORKING;
++ io_sideState.update_side = io_sideState.alt_side;
++#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
++ // Need info from PNOR's non-working side for update side
++ l_actions |= USE_PNOR_ALT_SIDE;
++ TRACUCOMP( g_trac_sbe, "getSideActions(): Asking for "
++ "USE_PNOR_ALT_SIDE: actions=0x%X", l_actions);
++#endif
++ }
++ else
++ {
++ // non-READ_ONLY_SEEPROM is pointing to PNOR's GOLDEN side
++ // This requires an update and re-IPL (Possibly Genesis Mode)
++ l_actions |= COPY_READ_ONLY_TO_WORKING;
++ l_actions |= REIPL;
++ io_sideState.update_side = io_sideState.cur_side;
++
++#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
++ // Need info from PNOR's non-working side for update side
++ l_actions |= USE_PNOR_ALT_SIDE;
++ TRACUCOMP( g_trac_sbe, "getSideActions(): Asking for "
++ "USE_PNOR_ALT_SIDE: actions=0x%X", l_actions);
++#endif
++
++ }
++ }
++
++ // Even though READ_ONLY_SEEPROM is not pointing to PNOR's GOLDEN side,
++ // treat like it is if there is only 1 side (ie, Palmetto configuration)
++ else if ( ( io_sideState.pnor_hasOtherSide == false ) &&
++ ( io_sideState.cur_side == READ_ONLY_SEEPROM ) )
++ {
++ l_actions |= COPY_READ_ONLY_TO_WORKING;
++ io_sideState.update_side = io_sideState.alt_side;
++ }
++
++ else // current Seeprom not pointing to PNOR's GOLDEN side
++ {
++ l_actions |= CHECK_WORKING_HBB;
++ io_sideState.update_side = io_sideState.cur_side;
++ // REIPL action will be determined later
++ }
++
++ io_sideState.actions = l_actions;
++
++ TRACUCOMP( g_trac_sbe, "getSideActions() Tgt=0x%X: "
++ "pnor_isGolden/hasOtherSide=%d/%d, actions=0x%.8X, "
++ "Update Side=0x%X, cur=%d",
++ TARGETING::get_huid(io_sideState.tgt),
++ io_sideState.pnor_isGolden, io_sideState.pnor_hasOtherSide,
++ io_sideState.actions,
++ io_sideState.update_side,
++ io_sideState.cur_side);
++
++ }while(0);
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"getSideActions()" );
++
++ return err;
++}
++
++
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t performSideActions(sbeResolveState_t& io_sideState)
++{
++ errlHndl_t err = NULL;
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"performSideActions()" );
++
++ bool updateForHBB = false;
++ size_t image_size = 0;
++ sbeSeepromVersionInfo_t image_version;
++
++ do{
++ if ( io_sideState.actions & COPY_READ_ONLY_TO_WORKING )
++ {
++ // Copy READ_ONLY SBE Seeprom Image to Memory
++ err = readSbeImage(io_sideState.tgt,
++ reinterpret_cast<void*>(SBE_IMG_VADDR),
++ READ_ONLY_SEEPROM,
++ image_size,
++ image_version);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "performSideActions: Error returned from "
++ "getSetSbeImage() rc=0x%.4X, Target UID=0x%X, "
++ "actions = 0x%X, image_size=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sideState.tgt),
++ io_sideState.actions, image_size);
++ break;
++ }
++ }
++
++ if ( io_sideState.actions & CHECK_WORKING_HBB )
++ {
++
++ // Copy current SBE Seeprom Image to Memory
++ // NOTE: Seprate section from above because of possible future
++ // improvement to use MBPD SB Keyword bit to keep track of HBB
++
++ err = readSbeImage(io_sideState.tgt,
++ reinterpret_cast<void*>(SBE_IMG_VADDR),
++ io_sideState.update_side,
++ image_size,
++ image_version);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "performSideActions: Error returned from "
++ "getSetSbeImage() rc=0x%.4X, Target UID=0x%X, "
++ "actions = 0x%X, image_size=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sideState.tgt),
++ io_sideState.actions, image_size);
++ break;
++ }
++
++ }
++
++
++ if ( ( io_sideState.actions & COPY_READ_ONLY_TO_WORKING ) ||
++ ( io_sideState.actions & CHECK_WORKING_HBB ) )
++ {
++ // verify HBB
++ PNOR::SideId pnor_side = PNOR::WORKING;
++
++#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
++ // In certain situations need info from Alternate PNOR
++ if ( io_sideState.actions & USE_PNOR_ALT_SIDE)
++ {
++ pnor_side = PNOR::ALTERNATE;
++ }
++#endif
++
++
++
++ err = resolveImageHBBaddr(io_sideState.tgt,
++ reinterpret_cast<void*>(SBE_IMG_VADDR),
++ io_sideState.update_side,
++ pnor_side,
++ updateForHBB);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "performSideActions: Error returned from "
++ "resolveImageHBBaddr() rc=0x%.4X, Target UID=0x%X, "
++ "actions = 0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sideState.tgt),
++ io_sideState.actions);
++ break;
++ }
++
++ // Since HBB was updated, we need to re-IPL if not booting on
++ // READ_ONLY seeprom
++ if ( ( updateForHBB == true ) &&
++ ( io_sideState.cur_side != READ_ONLY_SEEPROM ) )
++ {
++ io_sideState.actions |= REIPL;
++ TRACUCOMP( g_trac_sbe, ERR_MRK
++ "performSideActions: resolveImageHBBaddr returned "
++ "updateForHBB=%d, and not on READ_ONLY_SEEPROM so "
++ "REIPL (actions=0x%X)",
++ updateForHBB, io_sideState.actions);
++ }
++ }
++
++ if ( ( io_sideState.actions & COPY_READ_ONLY_TO_WORKING ) ||
++ ( updateForHBB == true ) )
++ {
++ // Write Seeprom Image from memory to Seeprom
++ err = writeSbeImage(io_sideState.tgt,
++ reinterpret_cast<void*>(SBE_IMG_VADDR),
++ io_sideState.update_side,
++ image_size,
++ image_version);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "performSideActions: Error returned from "
++ "getSetSbeImage() rc=0x%.4X, Target UID=0x%X, "
++ "actions = 0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sideState.tgt),
++ io_sideState.actions);
++ break;
++ }
++ }
++
++ }while(0);
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"performSideActions()" );
++
++ return err;
++}
++
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t readSbeImage(TARGETING::Target* i_target,
++ void* o_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ size_t& o_image_size,
++ sbeSeepromVersionInfo_t& o_image_version)
++{
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"readSbeImage(): tgt=0x%X, i_side=%d "
++ "o_imgPtr=%p, o_image_size=0x%X",
++ TARGETING::get_huid(i_target), i_side, o_imgPtr, o_image_size);
++
++ errlHndl_t err = NULL;
++ int64_t rc = 0;
++ PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN;
++ EEPROM::eeprom_chip_types_t l_seeprom = sbe_side_sync[i_side];
++ size_t image_size_ECC = 0;
++
++ // Need to ensure that io_imgPtr is at SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
++ // since we need to use the VMM_VADDR_SBE_UPDATE space
++ assert ( o_imgPtr == reinterpret_cast<void*>(SBE_IMG_VADDR),
++ "getSetSbeImage() - o_imgPtr is not at SBE_IMG_VADDR");
++
++ do{
++
++ // Clear out back half of page block to use as temp space
++ // for ECC injected SBE Image.
++ rc = mm_remove_pages(RELEASE,
++ reinterpret_cast<void*>
++ (SBE_ECC_IMG_VADDR),
++ SBE_ECC_IMG_MAX_SIZE);
++ if( rc )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"getSetSbeImage() - Error "
++ "from mm_remove_pages : rc=%d, HUID=0x%.8X.",
++ rc, TARGETING::get_huid(i_target) );
++ /*@
++ * @errortype
++ * @moduleid SBE_READ_SBE_IMAGE
++ * @reasoncode SBE_REMOVE_PAGES_FOR_EC
++ * @userdata1 Requested Address
++ * @userdata2 rc from mm_remove_pages
++ * @devdesc updateProcessorSbeSeeproms> mm_remove_pages
++ * RELEASE failed
++ * @custdesc A problem occurred while updating processor
++ * boot code.
++ */
++ err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
++ SBE_READ_SBE_IMAGE,
++ SBE_REMOVE_PAGES_FOR_EC,
++ TO_UINT64(SBE_ECC_IMG_VADDR),
++ TO_UINT64(rc),
++ true /*Add HB SW Callout*/ );
++
++ //Target isn't directly related to fail, but could be useful
++ // to see how far we got before failing.
++ ErrlUserDetailsTarget(i_target).addToLog(err);
++ err->collectTrace(SBE_COMP_NAME);
++ break;
++ }
++
++ /*****************************************/
++ /* Get Image Size */
++ /*****************************************/
++ err = getSbeImageSize(i_target,
++ o_imgPtr,
++ i_side,
++ o_image_size);
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: - Error from "
++ "getSbeImageSize(): rc=0x%.4X, side=%d, HUID=0x%.8X.",
++ err->reasonCode(),
++ i_side, TARGETING::get_huid(i_target));
++ break;
++ }
++
++
++ /*****************************************/
++ /* Do Actual Read */
++ /*****************************************/
++ image_size_ECC = ALIGN_8((o_image_size*9)/8);
++
++ assert(image_size_ECC <= SBE_ECC_IMG_MAX_SIZE,
++ "getSetSbeImage() SBE Image with ECC too large");
++
++ // Read image to memory space
++ err = DeviceFW::deviceOp(
++ DeviceFW::READ,
++ i_target,
++ reinterpret_cast<void*>
++ (SBE_ECC_IMG_VADDR),
++ image_size_ECC,
++ DEVICE_EEPROM_ADDRESS(
++ l_seeprom,
++ SBE_IMAGE_SEEPROM_ADDRESS));
++
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: - Error "
++ "from EEPROM op: rc=0x%.4X, seeprom=%d (side=%d). "
++ "HUID=0x%.8X. SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, "
++ "size=0x%.8X, eccSize=0x%.8X, EEPROM offset=0x%X",
++ err->reasonCode(), l_seeprom, i_side,
++ TARGETING::get_huid(i_target),
++ SBE_IMG_VADDR, SBE_ECC_IMG_VADDR, o_image_size,
++ image_size_ECC, SBE_IMAGE_SEEPROM_ADDRESS);
++ break;
++ }
++
++ /*****************************************/
++ /* Remove ECC From Image */
++ /*****************************************/
++
++ // Clear destination
++ memset( o_imgPtr, 0, MAX_SEEPROM_IMAGE_SIZE );
++
++ // Remove ECC
++ eccStatus = PNOR::ECC::removeECC(reinterpret_cast<uint8_t*>
++ (SBE_ECC_IMG_VADDR),
++ reinterpret_cast<uint8_t*>
++ (o_imgPtr),
++ image_size_ECC);
++
++ // Fail if uncorrectable ECC
++ if ( eccStatus == PNOR::ECC::UNCORRECTABLE )
++ {
++ // There is an ECC issue with this SEEPROM
++
++ TRACFCOMP( g_trac_sbe,ERR_MRK"readSbeImage: ECC Error "
++ "On SBE Image Read eccStatus=%d sI=%d, sI_ECC="
++ "%d, HUID=0x%.8X, Seeprom %d (side=%d)",
++ eccStatus, o_image_size, image_size_ECC,
++ TARGETING::get_huid(i_target),
++ l_seeprom, i_side );
++
++ /*@
++ * @errortype
++ * @moduleid SBE_READ_SBE_IMAGE
++ * @reasoncode SBE_ECC_FAIL
++ * @userdata1[0:15] ECC Status
++ * @userdata1[16:31] SEEPROM Side
++ * @userdata1[32:63] Target HUID
++ * @userdata2[0:31] Size - No Ecc
++ * @userdata2[32:63] Size - ECC
++ * @devdesc ECC Fail Reading SBE Image
++ */
++ err = new ErrlEntry(ERRL_SEV_PREDICTIVE,
++ SBE_READ_SBE_IMAGE,
++ SBE_ECC_FAIL,
++ TWO_UINT32_TO_UINT64(
++ ( (eccStatus << 16 ) |
++ l_seeprom ),
++ TARGETING::get_huid(i_target)),
++ TWO_UINT32_TO_UINT64(o_image_size,
++ image_size_ECC));
++
++ err->collectTrace(SBE_COMP_NAME);
++
++ err->addPartCallout(
++ i_target,
++ HWAS::SBE_SEEPROM_PART_TYPE,
++ HWAS::SRCI_PRIORITY_HIGH,
++ HWAS::NO_DECONFIG,
++ HWAS::GARD_NULL );
++
++ ErrlUserDetailsTarget(i_target).addToLog(err);
++
++ break;
++
++ } // ECC check
++
++
++ // Read out SBE Version Info
++ bool seeprom_ver_ECC_fail = false;
++ err = getSeepromSideVersion(i_target,
++ l_seeprom,
++ o_image_version,
++ seeprom_ver_ECC_fail);
++
++
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: - Error "
++ "from getSeepromSideVersion: rc=0x%.4X, seeprom=%d "
++ "(side=%d). HUID=0x%.8X",
++ err->reasonCode(), l_seeprom, i_side,
++ TARGETING::get_huid(i_target));
++ break;
++ }
++
++ else if (seeprom_ver_ECC_fail == true)
++ {
++ // For now, any issues will be addressed in SBE Update
++ // later in the IPL
++ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: ECC fail=%d "
++ "Reading Seeprom Version seeprom=%d "
++ "(side=%d). HUID=0x%.8X",
++ seeprom_ver_ECC_fail, l_seeprom, i_side,
++ TARGETING::get_huid(i_target));
++ }
++
++ TRACDBIN(g_trac_sbe, "readSbeImage: SBE Info Version",
++ reinterpret_cast<uint8_t*>(&o_image_version),
++ sizeof(o_image_version));
++
++ }while(0);
++
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"readSbeImage() - eccStatus=%d, "
++ "size=0x%X, size_ECC=0x%X",
++ eccStatus, o_image_size, image_size_ECC);
++
++
++ return err;
++}
++
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t writeSbeImage(TARGETING::Target* i_target,
++ void* i_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ size_t i_image_size,
++ sbeSeepromVersionInfo_t& io_version)
++
++{
++ TRACFCOMP( g_trac_sbe,
++ ENTER_MRK"writeSbeImage(): tgt=0x%X, i_side=%d "
++ "i_imgPtr=%p, i_image_size=0x%X",
++ TARGETING::get_huid(i_target), i_side, i_imgPtr, i_image_size);
++
++ errlHndl_t err = NULL;
++ int64_t rc = 0;
++ EEPROM::eeprom_chip_types_t l_seeprom = sbe_side_sync[i_side];
++ size_t image_size_ECC = 0;
++
++ // For Version Information
++ size_t sbeInfoSize = sizeof(sbeSeepromVersionInfo_t);
++ size_t sbeInfoSize_ECC = (sbeInfoSize*9)/8;
++
++ uint8_t * sbeInfo_data_ECC = static_cast<uint8_t*>
++ (malloc(sbeInfoSize_ECC));
++
++
++ // Need to ensure that io_imgPtr is at SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
++ // since we need to use the VMM_VADDR_SBE_UPDATE space
++ assert ( i_imgPtr == reinterpret_cast<void*>(SBE_IMG_VADDR),
++ "writeSbeImage() - io_imgPtr is not at SBE_IMG_VADDR");
++
++ do{
++
++ // Clear out back half of page block to use as temp space
++ // for ECC injected SBE Image.
++ rc = mm_remove_pages(RELEASE,
++ reinterpret_cast<void*>
++ (SBE_ECC_IMG_VADDR),
++ SBE_ECC_IMG_MAX_SIZE);
++ if( rc )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"writeSbeImage() - Error "
++ "from mm_remove_pages : rc=%d, HUID=0x%.8X.",
++ rc, TARGETING::get_huid(i_target) );
++ /*@
++ * @errortype
++ * @moduleid SBE_WRITE_SBE_IMAGE
++ * @reasoncode SBE_REMOVE_PAGES_FOR_EC
++ * @userdata1 Requested Address
++ * @userdata2 rc from mm_remove_pages
++ * @devdesc updateProcessorSbeSeeproms> mm_remove_pages
++ * RELEASE failed
++ * @custdesc A problem occurred while updating processor
++ * boot code.
++ */
++
++ err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
++ SBE_WRITE_SBE_IMAGE,
++ SBE_REMOVE_PAGES_FOR_EC,
++ TO_UINT64(SBE_ECC_IMG_VADDR),
++ TO_UINT64(rc),
++ true /*Add HB SW Callout*/ );
++
++ //Target isn't directly related to fail, but could be useful
++ //to see how far we got before failing.
++ ErrlUserDetailsTarget(i_target).addToLog(err);
++ err->collectTrace(SBE_COMP_NAME);
++ break;
++ }
++
++ // Inject ECC
++ PNOR::ECC::injectECC(reinterpret_cast<uint8_t*>(i_imgPtr),
++ ALIGN_8(i_image_size),
++ reinterpret_cast<uint8_t*>
++ (SBE_ECC_IMG_VADDR));
++
++ /*****************************************/
++ /* Do Actual Write of Image */
++ /*****************************************/
++ image_size_ECC = ALIGN_8((i_image_size*9)/8);
++
++ assert(image_size_ECC <= SBE_ECC_IMG_MAX_SIZE,
++ "writeSbeImage() SBE Image with ECC too large");
++
++ err = deviceWrite(i_target,
++ reinterpret_cast<void*>
++ (SBE_ECC_IMG_VADDR),
++ image_size_ECC,
++ DEVICE_EEPROM_ADDRESS(
++ l_seeprom,
++ SBE_IMAGE_SEEPROM_ADDRESS));
++
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"writeSbeImage: - Error "
++ "from EEPROM op: rc=0x%.4X, seeprom=%d (side=%d). "
++ "HUID=0x%.8X. SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, "
++ "size=0x%.8X, eccSize=0x%.8X, EEPROM offset=0x%X",
++ err->reasonCode(), l_seeprom, i_side,
++ TARGETING::get_huid(i_target),
++ SBE_IMG_VADDR, SBE_ECC_IMG_VADDR, i_image_size,
++ image_size_ECC, SBE_IMAGE_SEEPROM_ADDRESS);
++ break;
++ }
++
++ /********************************************/
++ /* Do Actual Write of Version Information */
++ /********************************************/
++
++ // Update the image crc in the version information
++ uint32_t image_crc = Util::crc32_calc(i_imgPtr, i_image_size);
++
++ memcpy( &(io_version.data_crc),
++ &image_crc,
++ sizeof(image_crc));
++
++ TRACDBIN( g_trac_sbe, "writeSbeImage: Version no ECC",
++ reinterpret_cast<uint8_t*>(&io_version), sizeof(io_version));
++
++ // Inject ECC
++ memset( sbeInfo_data_ECC, 0, sbeInfoSize_ECC);
++ PNOR::ECC::injectECC(reinterpret_cast<uint8_t*>(&io_version),
++ sbeInfoSize, sbeInfo_data_ECC);
++
++ TRACDBIN( g_trac_sbe, "writeSbeImage: Version with ECC",
++ sbeInfo_data_ECC, sbeInfoSize_ECC);
++
++ err = deviceWrite( i_target,
++ sbeInfo_data_ECC,
++ sbeInfoSize_ECC,
++ DEVICE_EEPROM_ADDRESS(
++ l_seeprom,
++ SBE_VERSION_SEEPROM_ADDRESS));
++
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"writeSbeImage: - Error "
++ "Writing SBE Version Info: rc=0x%.4X, "
++ "HUID=0x%.8X, seeprom=%d, side=%d",
++ err->reasonCode(),
++ TARGETING::get_huid(i_target), l_seeprom, i_side);
++ break;
++ }
++
++ }while(0);
++
++ // Free allocated memory
++ free(sbeInfo_data_ECC);
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"writeSetSbeImage()" );
++
++ return err;
++}
++
++
++
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t getSbeImageSize(TARGETING::Target* i_target,
++ void* i_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ size_t& o_image_size)
++{
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"geSbeImageSize(): tgt=0x%X, i_side=%d "
++ "i_imgPtr=%p, o_image_size=0x%X",
++ TARGETING::get_huid(i_target), i_side, i_imgPtr, o_image_size);
++
++ errlHndl_t err = NULL;
++ PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN;
++ EEPROM::eeprom_chip_types_t l_seeprom = sbe_side_sync[i_side];
++ size_t image_size_ECC = 0;
++
++ // Need to ensure that i_imgPtr is at SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
++ // since we need to use the VMM_VADDR_SBE_UPDATE space
++
++ assert ( i_imgPtr == reinterpret_cast<void*>(SBE_IMG_VADDR),
++ "getSbeImageSize() - i_imgPtr is not at SBE_IMG_VADDR");
++
++ do{
++ // Need to read the SbeXipHeader of the image to determine size
++ // of the image to read out.
++ // Using io_imgPtr space. First read our header+ECC from SBE
++ // Seeprom and then use space after that to put header without ECC
++
++
++ size_t hdr_size = ALIGN_8(sizeof(SbeXipHeader));
++ size_t hdr_size_ECC = (hdr_size * 9)/8;
++
++ uint8_t* hdr_ptr = reinterpret_cast<uint8_t*>(i_imgPtr) + hdr_size_ECC;
++
++ memset( i_imgPtr, 0, hdr_size_ECC + hdr_size );
++
++ TRACUCOMP( g_trac_sbe, INFO_MRK"getSetSbeImage() Reading "
++ "SbeXipHeader for Target 0x%X, Seeprom %d "
++ "(side=%d), size_ECC=0x%X (size=0x%X)",
++ TARGETING::get_huid(i_target),
++ l_seeprom, i_side, hdr_size_ECC, hdr_size );
++
++ err = DeviceFW::deviceOp( DeviceFW::READ,
++ i_target,
++ i_imgPtr,
++ hdr_size_ECC,
++ DEVICE_EEPROM_ADDRESS(
++ l_seeprom,
++ SBE_IMAGE_SEEPROM_ADDRESS));
++
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeImageSize: - Error "
++ "Reading SbeXipHeader: rc=0x%.4X, seeprom=%d (side=%d). "
++ "HUID=0x%.8X. size=0x%.8X, EEPROM offset=0x%X",
++ err->reasonCode(), l_seeprom, i_side,
++ TARGETING::get_huid(i_target), sizeof(SbeXipHeader),
++ SBE_IMAGE_SEEPROM_ADDRESS);
++ break;
++ }
++
++
++ TRACDBIN( g_trac_sbe,
++ "Data with ECC read from Seeprom",
++ i_imgPtr,
++ hdr_size_ECC );
++
++ // Remove ECC
++ eccStatus = PNOR::ECC::removeECC(
++ reinterpret_cast<uint8_t*>(i_imgPtr),
++ hdr_ptr,
++ hdr_size);
++
++ // Fail if uncorrectable ECC
++ if ( eccStatus == PNOR::ECC::UNCORRECTABLE )
++ {
++ TRACFCOMP( g_trac_sbe,ERR_MRK"getSbeImageSize: ECC Error "
++ "On SBE Image Read eccStatus=%d sI=%d, sI_ECC="
++ "%d, HUID=0x%.8X, Seeprom %d (side=%d)",
++ eccStatus, o_image_size, image_size_ECC,
++ TARGETING::get_huid(i_target),
++ l_seeprom, i_side );
++ /*@
++ * @errortype
++ * @moduleid SBE_GET_SBE_IMAGE_SIZE
++ * @reasoncode SBE_ECC_FAIL
++ * @userdata1[0:15] ECC Status
++ * @userdata1[16:31] SEEPROM Side
++ * @userdata1[32:63] Target HUID
++ * @userdata2[0:31] Size - No Ecc
++ * @userdata2[32:63] Size - ECC
++ * @devdesc ECC Fail Reading SBE Image
++ */
++ err = new ErrlEntry(ERRL_SEV_PREDICTIVE,
++ SBE_GET_SBE_IMAGE_SIZE,
++ SBE_ECC_FAIL,
++ TWO_UINT32_TO_UINT64(
++ ( (eccStatus << 16 ) |
++ l_seeprom ),
++ TARGETING::get_huid(i_target)),
++ TWO_UINT32_TO_UINT64(o_image_size,
++ image_size_ECC));
++ err->collectTrace(SBE_COMP_NAME);
++ err->addPartCallout(
++ i_target,
++ HWAS::SBE_SEEPROM_PART_TYPE,
++ HWAS::SRCI_PRIORITY_HIGH,
++ HWAS::NO_DECONFIG,
++ HWAS::GARD_NULL );
++
++ ErrlUserDetailsTarget(i_target).addToLog(err);
++
++ break;
++ }
++
++ TRACDBIN( g_trac_sbe,
++ "Data without ECC read from Seeprom",
++ hdr_ptr,
++ hdr_size );
++
++ o_image_size = (((SbeXipHeader*)hdr_ptr)->iv_imageSize);
++
++ }while(0);
++
++ TRACFCOMP( g_trac_sbe,
++ EXIT_MRK"getSbeImageSize(): o_image_size=0x%X", o_image_size );
++
++ return err;
++}
++
++
++
++/////////////////////////////////////////////////////////////////////
++errlHndl_t resolveImageHBBaddr(TARGETING::Target* i_target,
++ void* io_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ PNOR::SideId i_pnorSideId,
++ bool& o_imageWasUpdated )
++{
++ errlHndl_t err = NULL;
++ uint64_t data = 0;
++ int rc = 0;
++ bool rc_fail_on_get = false; // 1=get failed, 0=set failed
++
++ o_imageWasUpdated = false;
++
++ TRACUCOMP( g_trac_sbe,
++ ENTER_MRK"resolveImageHBBaddr() - tgt=0x%X, i_side=%d, "
++ "i_pnorSideId=%d",
++ TARGETING::get_huid(i_target), i_side, i_pnorSideId);
++
++ do{
++
++ // Get info from PNOR
++ PNOR::SideInfo_t pnor_side_info;
++ err = PNOR::getSideInfo (i_pnorSideId, pnor_side_info);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "resolveImageHBBaddr() - Error returned "
++ "from PNOR::getSideInfo() rc=0x%.4X, Target UID=0x%X "
++ "i_pnorSideId",
++ err->reasonCode(),
++ TARGETING::get_huid(i_target), i_pnorSideId);
++ break;
++ }
++
++
++ // Only Need to Check/Update if PNOR has Other Side
++ // and Seeprom isn't pointing at PNOR's GOLDEN side
++ if ( ( pnor_side_info.hasOtherSide == true ) &&
++ ( pnor_side_info.isGolden == false ) )
++ {
++
++ // Read the MMIO offset associated with the HBB address
++ // from the image
++ rc = sbe_xip_get_scalar( io_imgPtr,
++ "standalone_mbox2_value",
++ &data);
++ if ( rc != 0 )
++ {
++ rc_fail_on_get = true; // get failed
++
++ TRACFCOMP( g_trac_sbe, ERR_MRK"resolveImageHBBaddr() - "
++ "sbe_xip_get_scalar() failed rc = 0x%X (%d)",
++ rc, rc_fail_on_get);
++ break;
++ }
++
++ if ( pnor_side_info.hbbMmioOffset == data )
++ {
++ TRACUCOMP( g_trac_sbe, "resolveImageHBBaddr: Image has MMIO "
++ "offset = 0x%X that matches PNOR MMIO="
++ "0x%X for HBB Address=0x%X",
++ data, pnor_side_info.hbbMmioOffset,
++ pnor_side_info.hbbAddress);
++ }
++ else
++ {
++ TRACFCOMP( g_trac_sbe, "resolveImageHBBaddr: Image has MMIO "
++ "offset = 0x%X does NOT match PNOR MMIO="
++ "0x%X for HBB Address=0x%X. Updating Image",
++ data, pnor_side_info.hbbMmioOffset,
++ pnor_side_info.hbbAddress);
++
++ TRACDBIN (g_trac_sbe, "resolveImageHBBaddr: data", &data, 8 );
++
++ TRACDBIN (g_trac_sbe, "resolveImageHBBaddr: hbbMmioOffset",
++ &pnor_side_info.hbbMmioOffset, 8 );
++ TRACDBIN (g_trac_sbe, "resolveImageHBBaddr: hbbAddress",
++ &pnor_side_info.hbbAddress, 8);
++
++ rc = sbe_xip_set_scalar( io_imgPtr, "standalone_mbox2_value",
++ pnor_side_info.hbbMmioOffset);
++
++ if ( rc != 0 )
++ {
++ rc_fail_on_get = false; // set failed
++
++ TRACFCOMP( g_trac_sbe, ERR_MRK"resolveImageHBBaddr() - "
++ "sbe_xip_set_scalar() failed rc = 0x%X (%d)",
++ rc, rc_fail_on_get);
++ break;
++ }
++ o_imageWasUpdated = true;
++ }
++
++ }
++ else
++ {
++ // pnor_side_info.hasOtherSide is false
++ TRACUCOMP( g_trac_sbe, "resolveImageHBBaddr: PNOR only has "
++ "1 side - No Update Required");
++ }
++
++ }while(0);
++
++
++ if ( ( err == NULL ) && ( rc != 0) )
++ {
++ // We failed on get/set cmd above (already traced)
++
++ /*@
++ * @errortype
++ * @moduleid SBE_RESOLVE_HBB_ADDR
++ * @reasoncode SBE_IMAGE_GET_SET_SCALAR_FAIL
++ * @userdata1 Return Code of failed operation
++ * @userdata2 True/False if Get (true) or Set (false) Op failed
++ * @devdesc sbe_xip_get/set_scalar() failed when accessing the
++ HBB Address MMIO offset in 'standalone_mbox2_value'
++ * @custdesc A problem occurred while updating processor
++ * boot code.
++ */
++ err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
++ SBE_RESOLVE_HBB_ADDR,
++ SBE_IMAGE_GET_SET_SCALAR_FAIL,
++ TO_UINT64(rc),
++ TO_UINT64(rc_fail_on_get),
++ true /*Add HB SW Callout*/ );
++
++ err->collectTrace(SBE_COMP_NAME);
++ }
++
++
++ TRACUCOMP( g_trac_sbe,
++ EXIT_MRK"resolveImageHBBaddr() - o_imageWasUpdated = %d",
++ o_imageWasUpdated);
++
++ return err;
++}
++
++#ifdef CONFIG_BMC_IPMI
++/////////////////////////////////////////////////////////////////////
++void sbePreShutdownIpmiCalls( void )
++{
++ errlHndl_t err = NULL;
++
++ TRACFCOMP( g_trac_sbe, ENTER_MRK"sbePreShutdownIpmiCalls");
++
++ do{
++ uint16_t count = 0;
++ SENSOR::RebootCountSensor l_sensor;
++
++ // Read reboot count sensor
++ err = l_sensor.getRebootCount(count);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe,
++ ERR_MRK"sbePreShutdownIpmiCalls: "
++ "FAIL Reading Reboot Sensor Count. "
++ "Committing Error Log rc=0x%.4X eid=0x%.8X "
++ "plid=0x%.8X, but continuing shutdown",
++ err->reasonCode(),
++ err->eid(),
++ err->plid());
++ err->collectTrace(SBE_COMP_NAME);
++ errlCommit( err, SBE_COMP_ID );
++
++ // No Break - Still Do Watchdog Timer Call
++ }
++ else
++ {
++ // Increment Reboot Count Sensor
++ count++;
++ TRACFCOMP( g_trac_sbe,
++ INFO_MRK"sbePreShutdownIpmiCalls: "
++ "Writing Reboot Sensor Count=%d", count);
++
++ err = l_sensor.setRebootCount( count );
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe,
++ ERR_MRK"sbePreShutdownIpmiCalls: "
++ "FAIL Writing Reboot Sensor Count to %d. "
++ "Committing Error Log rc=0x%.4X eid=0x%.8X "
++ "plid=0x%.8X, but continuing shutdown",
++ count,
++ err->reasonCode(),
++ err->eid(),
++ err->plid());
++ err->collectTrace(SBE_COMP_NAME);
++ errlCommit( err, SBE_COMP_ID );
++
++ // No Break - Still Do Watchdog Timer Call
++ }
++ }
++
++ // @todo RTC 124679 - Remove Once BMC Monitors Shutdown Attention
++ // Set Watchdog Timer To 10 seconds
++ const uint16_t SET_WD_TIMER_10_SECS = 10;
++ TRACFCOMP( g_trac_sbe,"sbePreShutdownIpmiCalls: "
++ "Set Watch Dog Timer To %d Seconds",
++ SET_WD_TIMER_10_SECS);
++
++ err = IPMIWATCHDOG::setWatchDogTimer(SET_WD_TIMER_10_SECS);
++ if(err)
++ {
++ TRACFCOMP( g_trac_sbe,
++ ERR_MRK"sbePreShutdownIpmiCalls: "
++ "FAIL Setting Watch Dog Timer to %d seconds. "
++ "Committing Error Log rc=0x%.4X eid=0x%.8X "
++ "plid=0x%.8X, but continuing shutdown",
++ SET_WD_TIMER_10_SECS,
++ err->reasonCode(),
++ err->eid(),
++ err->plid());
++
++ err->collectTrace(SBE_COMP_NAME);
++ errlCommit(err, SBE_COMP_ID );
++ }
++
++ }while(0);
++
++ TRACFCOMP( g_trac_sbe, EXIT_MRK"sbePreShutdownIpmiCalls");
++
++ return;
++}
++#endif // CONFIG_BMC_IPMI
++
++
++} //end SBE Namespace
+diff --git a/src/usr/sbe/sbe_resolve_sides.H b/src/usr/sbe/sbe_resolve_sides.H
+new file mode 100644
+index 0000000..42f727a
+--- /dev/null
++++ b/src/usr/sbe/sbe_resolve_sides.H
+@@ -0,0 +1,259 @@
++/* IBM_PROLOG_BEGIN_TAG */
++/* This is an automatically generated prolog. */
++/* */
++/* $Source: src/usr/sbe/sbe_resolve_sides.H $ */
++/* */
++/* OpenPOWER HostBoot Project */
++/* */
++/* Contributors Listed Below - COPYRIGHT 2015 */
++/* [+] 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. */
++/* You may obtain a copy of the License at */
++/* */
++/* http://www.apache.org/licenses/LICENSE-2.0 */
++/* */
++/* Unless required by applicable law or agreed to in writing, software */
++/* distributed under the License is distributed on an "AS IS" BASIS, */
++/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
++/* implied. See the License for the specific language governing */
++/* permissions and limitations under the License. */
++/* */
++/* IBM_PROLOG_END_TAG */
++#ifndef __SBE_SBE_RESOLVE_SIDES_H
++#define __SBE_SBE_RESOLVE_SIDES_H
++
++
++#include <stdint.h>
++#include <builtins.h>
++#include <errl/errlentry.H>
++#include <pnor/pnorif.H>
++#include <util/align.H>
++#include <vmmconst.h>
++#include <targeting/common/targetservice.H>
++#include <i2c/eepromif.H>
++#include "sbe_update.H"
++
++namespace SBE
++{
++ /******************************************/
++ /* Constants */
++ /******************************************/
++
++ // This seeprom is a candidate to be READ_ONLY (ie, not updated)
++ const PNOR::sbeSeepromSide_t READ_ONLY_SEEPROM = PNOR::SBE_SEEPROM1;
++
++ // Used to keep SBE Seeproms in sync with EEPROM::eeprom_chip_types_t
++ const EEPROM::eeprom_chip_types_t sbe_side_sync[2] =
++ { EEPROM::SBE_PRIMARY,
++ EEPROM::SBE_BACKUP };
++
++ /******************************************/
++ /* Enums */
++ /******************************************/
++
++ // Actions can be combined
++ enum
++ {
++ NO_ACTIONS = 0x00000000,
++ REIPL = 0x00000001,
++
++ // Use PNOR::ALTERNATE SideId for HBB Address info
++ USE_PNOR_ALT_SIDE = 0x00000002,
++
++ // NOTE: These next 2 values are mutually exclusive
++ CHECK_WORKING_HBB = 0x00000010,
++ COPY_READ_ONLY_TO_WORKING = 0x00000020,
++ };
++
++ /******************************************/
++ /* Structs */
++ /******************************************/
++ struct sbeResolveState_t
++ {
++
++ // Target Information
++ TARGETING::Target* tgt;
++
++ PNOR::sbeSeepromSide_t cur_side; // aka 'booted' side
++ PNOR::sbeSeepromSide_t alt_side; // non-booted/non-cur side
++ PNOR::sbeSeepromSide_t update_side; // side to be updated
++
++ // Info from PNOR
++ PNOR::SideId pnor_sideId;
++ char pnor_side; /**< name of the side either A or B */
++ bool pnor_isGolden; /**< True if side is golden */
++ bool pnor_hasOtherSide; /**< True if a valid alternate side exists*/
++
++ uint32_t actions;
++
++ // Constructor to default certain values
++ sbeResolveState_t() :
++ tgt(NULL), cur_side(PNOR::SBE_SEEPROM_INVALID),
++ alt_side(PNOR::SBE_SEEPROM_INVALID),
++ update_side(PNOR::SBE_SEEPROM_INVALID),
++ pnor_sideId(PNOR::WORKING),
++ pnor_side(NULL),
++ pnor_isGolden(false), pnor_hasOtherSide(false),
++ actions(NO_ACTIONS)
++ {}
++
++ };
++
++
++ /******************************************/
++ /* Functions -- High Level Functions */
++ /******************************************/
++
++ /**
++ * @brief Collects SBE Side Information for a specifc target
++ *
++ * @param[io/out] io_sideState Struct containing SBE State of the target
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t getSideState(sbeResolveState_t& io_sideState);
++
++ /**
++ * @brief Analyze and Determine Update Actions for a specific target
++ *
++ * @param[io/out] io_sideState Struct containing SBE State of the target
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t getSideActions(sbeResolveState_t& io_sideState);
++
++ /**
++ * @brief Performs the Update Actions for a specific target
++ *
++ * @param[io/out] io_sideState Struct containing SBE State of the target
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t performSideActions(sbeResolveState_t& io_sideState);
++
++
++
++ /******************************************/
++ /* Functions -- System Access */
++ /******************************************/
++
++
++ /**
++ * @brief Read SBE Image from SBE Seeprom
++ *
++ * @param[in] i_target Target processor
++ *
++ * @param[out] o_imgPtr Pointer to SBE image in memory
++ * Memory for this pointer is expected to be
++ * pre-alloacted
++ * NOTE: ECC is handled internally in this
++ * function. io_imgPtr points to non-ECC image
++ *
++ * @param[in] i_side Seeprom Side to access
++ *
++ * @param[in] o_image_size The size of the image (non-ECC)
++ *
++ * @param[in] o_version SBE Version struct from seeprom (non-ECC)
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t readSbeImage(TARGETING::Target* i_target,
++ void* o_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ size_t& o_image_size,
++ sbeSeepromVersionInfo_t& o_version);
++
++ /**
++ * @brief Write SBE Image from SBE Seeprom
++ *
++ * @param[in] i_target Target processor
++ *
++ * @param[in] i_imgPtr Pointer to SBE image in memory
++ * Memory for this pointer is expected to be
++ * pre-alloacted
++ * NOTE: ECC is handled internally in this function
++ * i_imgPtr points to non-ECC image
++ *
++ * @param[in] i_side Seeprom Side to access
++ *
++ * @param[in] i_image_size Size of image to write (non-ECC)
++ *
++ * @param[in] io_version SBE Version struct to write (non-ECC)
++ * NOTE: data_crc updated in this function
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t writeSbeImage(TARGETING::Target* i_target,
++ void* i_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ size_t i_image_size,
++ sbeSeepromVersionInfo_t& io_version);
++
++
++ /**
++ * @brief Read SBE Image Header from SBE Seeprom and gets the
++ * Image size from the heaser
++ *
++ * @param[in] i_target Target processor
++ *
++ * @param[out] i_imgPtr Pointer to pre-allocated memory to be used
++ * for different operations
++ *
++ * @param[in] i_side Seeprom Side to access
++ *
++ * @param[in] o_image_size The size of the image (non-ECC)
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t getSbeImageSize(TARGETING::Target* i_target,
++ void* i_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ size_t& o_image_size);
++
++
++
++
++ /******************************************/
++ /* Functions -- Helper Functions */
++ /******************************************/
++
++ /**
++ * @brief Check and Update (if necessary) the HBB Address MMIO offset
++ * in a customized SBE Image for the current Processor
++ *
++ * @param[in] i_target Target processor to customize
++ *
++ * @param[in/out] io_imgPtr Pointer to SBE image in memory
++ * Memory for this pointer is expected to be
++ * pre-alloacted
++ *
++ * @param[in] i_side Seeprom Side to access
++ *
++ * @param[in] i_pnorSideId PNOR side to get information for
++ *
++ * @param[out] o_imageWasUpdated Set to true if Image was updated;
++ * otherwise false
++ *
++ * @return errlHndl_t Error log handle on failure.
++ */
++ errlHndl_t resolveImageHBBaddr(TARGETING::Target* i_target,
++ void* io_imgPtr,
++ PNOR::sbeSeepromSide_t i_side,
++ PNOR::SideId i_pnorSideId,
++ bool& o_imageWasUpdated);
++
++#ifdef CONFIG_BMC_IPMI
++ /**
++ * @brief Performs any necessary IPMI calls before shutting down the system
++ *
++ * @return void Any generated Error Logs will be commited before the
++ * function returns
++ */
++ void sbePreShutdownIpmiCalls( void );
++#endif
++
++} //end namespace SBE
++#endif
+diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C
+index 97a0484..562798b 100644
+--- a/src/usr/sbe/sbe_update.C
++++ b/src/usr/sbe/sbe_update.C
+@@ -50,6 +50,7 @@
+ #include <sbe/sbeif.H>
+ #include <sbe/sbereasoncodes.H>
+ #include "sbe_update.H"
++#include "sbe_resolve_sides.H"
+
+ // fapi support
+ #include <fapi.H>
+@@ -112,6 +113,25 @@ namespace SBE
+
+ do{
+
++#ifdef CONFIG_NO_SBE_UPDATES
++ TRACFCOMP( g_trac_sbe, INFO_MRK"updateProcessorSbeSeeproms() - "
++ "SBE updates not configured");
++ break;
++#endif
++
++#ifdef CONFIG_SBE_UPDATE_SEQUENTIAL
++ // Check if FSP-services are enabled and if we're running in simics
++ if ( !INITSERVICE::spBaseServicesEnabled() &&
++ !Util::isSimicsRunning() )
++ {
++ assert (false, "resolveProcessorSbeSeeproms() - "
++ "SBE_UPDATE_SEQUENTIAL mode, but FSP-services are not "
++ "enabled - Invalid Configuration");
++ }
++ // else - continue on
++#endif
++
++
+ // Get Target Service, and the system target.
+ TargetService& tS = targetService();
+ TARGETING::Target* sys = NULL;
+@@ -204,11 +224,6 @@ namespace SBE
+ err = NULL;
+ }
+
+-#ifdef CONFIG_NO_SBE_UPDATES
+- TRACFCOMP( g_trac_sbe, INFO_MRK"updateProcessorSbeSeeproms() - "
+- "SBE updates not configured");
+- break;
+-#endif
+
+ for(uint32_t i=0; i<procList.size(); i++)
+ {
+@@ -277,7 +292,6 @@ namespace SBE
+ /**********************************************/
+ if ((err == NULL) && (sbeState.update_actions & DO_UPDATE))
+ {
+-
+ err = performUpdateActions(sbeState);
+ if (err)
+ {
+@@ -328,7 +342,6 @@ namespace SBE
+
+ } //end of Target for loop collecting each target's SBE State
+
+-
+ /**************************************************************/
+ /* Perform System Operation */
+ /**************************************************************/
+@@ -355,7 +368,7 @@ namespace SBE
+ }
+
+ #ifdef CONFIG_BMC_IPMI
+- // @todo RTC 120734 reset system's reboot count via IPMI sensor
++ sbePreShutdownIpmiCalls();
+ #endif
+
+ TRACFCOMP( g_trac_sbe,
+@@ -685,14 +698,15 @@ namespace SBE
+
+ do{
+
+- // @todo RTC 120734 - before customizing, ensure correct HBB address
+- // is set in the necessary attribute
+-
+ // cast OUR type of target to a FAPI type of target.
+ const fapi::Target
+ l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP,
+ (const_cast<TARGETING::Target*>(i_target)));
+
++ // NOTE: The p8_xip_customize_procedure uses SBE_IMAGE_OFFSET
++ // attribute for HBB address value. Purpsely leaving this
++ // attribute as-is for now and will do the check for HBB address
++ // later.
+
+ // The p8_xip_customize() procedure tries to include as much core
+ // information as possible, but is limited by SBE Image size
+@@ -871,7 +885,6 @@ namespace SBE
+ HWAS::SRCI_PRIORITY_HIGH );
+ }
+
+-
+ }while(0);
+
+ TRACUCOMP( g_trac_sbe,
+@@ -1715,6 +1728,26 @@ namespace SBE
+ // The Customized Image For This Target Still Resides In
+ // The SBE Update VMM Space: SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
+
++#ifdef CONFIG_SBE_UPDATE_INDEPENDENT
++ // Ensure HBB address value in the customized image is correct
++ // for this side
++ bool imageWasUpdated=false;
++ err = resolveImageHBBaddr ( io_sbeState.target,
++ reinterpret_cast<void*>(SBE_IMG_VADDR),
++ ((io_sbeState.seeprom_side_to_update ==
++ EEPROM::SBE_PRIMARY ) ?
++ PNOR::SBE_SEEPROM0 :
++ PNOR::SBE_SEEPROM1 ),
++ PNOR::WORKING,
++ imageWasUpdated );
++
++ if (imageWasUpdated == true )
++ {
++ TRACUCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - "
++ "HBB Address's MMIO Offset Updated in Image");
++ }
++
++#endif
+
+ // Inject ECC
+ // clear out back half of page block to use as temp space
+@@ -1941,7 +1974,6 @@ namespace SBE
+ io_sbeState.seeprom_0_ver.data_crc, isSimics_check);
+ }
+
+-
+ /**************************************************************/
+ /* Compare SEEPROM 1 with PNOR and Customized Image CRC -- */
+ /* -- dirty or clean? */
+@@ -2153,22 +2185,55 @@ namespace SBE
+ #ifdef CONFIG_SBE_UPDATE_INDEPENDENT
+
+ // The 2 SBE SEEPROMs are independent of each other
+- // Determine if PNOR is 1- or 2-sided and if there is a
+- // GOLDEN boot involved
++ // Determine if PNOR is 1- or 2-sided and if the current
++ // Seeprom is pointing at PNOR's GOLDEN side
++
++ PNOR::SideId tmp_side = PNOR::WORKING;
++ PNOR::SideInfo_t pnor_side_info;
++ err = PNOR::getSideInfo (tmp_side, pnor_side_info);
++ if ( err )
++ {
++ TRACFCOMP( g_trac_sbe, ERR_MRK
++ "SBE Update() - Error returned from "
++ "PNOR::getSideInfo() rc=0x%.4X, Target UID=0x%X",
++ err->reasonCode(),
++ TARGETING::get_huid(io_sbeState.target));
++ break;
++ }
+
+-#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
++ TRACUCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: PNOR Info: "
++ "side-%c, sideId=0x%X, isGolden=%d, hasOtherSide=%d",
++ TARGETING::get_huid(io_sbeState.target),
++ pnor_side_info.side, pnor_side_info.id,
++ pnor_side_info.isGolden, pnor_side_info.hasOtherSide);
+
+- // @todo RTC 120734 - ask PNOR if we are in "GOLDEN" mode,
+- // which would mean that we are booting off the the GOLDEN
+- // SBE SEEPROM which corresponds to the GOLDEN side of PNOR
+-/*
+- if (true)
++ if ( pnor_side_info.isGolden == true )
+ {
+ // If true, nothing to do (covered in istep 6 function)
+ l_actions = CLEAR_ACTIONS;
+
+ TRACFCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
+- "Booting GOLDEN SBE SEEPROM in PNOR 2-sided Mode. "
++ "Booting READ_ONLY SEEPROM pointing at PNOR's "
++ "GOLDEN side. No updates for cur side=%d. Continue "
++ "IPL. (sit=0x%.2X, act=0x%.8X flags=0x%.2X)",
++ TARGETING::get_huid(io_sbeState.target),
++ io_sbeState.cur_seeprom_side,
++ i_system_situation, l_actions,
++ io_sbeState.mvpdSbKeyword.flags);
++ break;
++ }
++
++ else if ( ( pnor_side_info.hasOtherSide == false ) &&
++ ( io_sbeState.cur_seeprom_side == READ_ONLY_SEEPROM ) )
++ {
++ // Even though current seeprom is not pointing at PNOR's
++ // GOLDEN side, treat like READ_ONLY if booting from READ_ONLY
++ // seeprom and and PNOR does not have another side - No Update
++ // (ie, Palmetto configuration)
++ l_actions = CLEAR_ACTIONS;
++
++ TRACFCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
++ "Treating cur like READ_ONLY SBE SEEPROM. "
+ "No updates for cur side=%d. Continue IPL. "
+ "(sit=0x%.2X, act=0x%.8X flags=0x%.2X)",
+ TARGETING::get_huid(io_sbeState.target),
+@@ -2179,22 +2244,14 @@ namespace SBE
+ }
+ else // proceed to update this side
+ {
++ // proceed to update this side
+ TRACUCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
+- "NOT Booting GOLDEN SBE SEEPROM in PNOR 2-sided "
+- "mode. Checking for update on cur side=%d ",
++ "NOT Booting READ_ONLY SEEPROM. Check for update "
++ "on cur side=%d ",
+ TARGETING::get_huid(io_sbeState.target),
+ io_sbeState.cur_seeprom_side)
+ }
+-*/
+-#else
+
+- // @todo RTC 120734 - check this assumption
+- // Assume that we're only checking/updating the current side
+- TRACUCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
+- "PNOR 1-sided so only check for update on cur side=%d",
+- TARGETING::get_huid(io_sbeState.target),
+- io_sbeState.cur_seeprom_side);
+-#endif
+
+ // Check for clean vs. dirty only on cur side
+ if ( i_system_situation & SITUATION_CUR_IS_DIRTY )
+@@ -2203,6 +2260,7 @@ namespace SBE
+ l_actions |= IPL_RESTART;
+ l_actions |= DO_UPDATE;
+ l_actions |= UPDATE_SBE;
++ l_actions |= UPDATE_MVPD; // even though flags byte not updated
+
+ // Set Update side to cur
+ io_sbeState.seeprom_side_to_update =
+--
+1.7.4.1
+
diff --git a/openpower/package/hostboot/hostboot-0010-Mark-Centaurs-as-present-functionl-on-IPL.patch b/openpower/package/hostboot/hostboot-0010-Mark-Centaurs-as-present-functionl-on-IPL.patch
new file mode 100644
index 0000000..9d9ff0f
--- /dev/null
+++ b/openpower/package/hostboot/hostboot-0010-Mark-Centaurs-as-present-functionl-on-IPL.patch
@@ -0,0 +1,56 @@
+From d569d04ce1b7451af590465e1befab0ae3634ccf Mon Sep 17 00:00:00 2001
+From: Richard J. Knight <rjknight@us.ibm.com>
+Date: Fri, 27 Feb 2015 22:13:21 -0600
+Subject: [PATCH 5/7] Mark Centaurs as present/functionl on IPL
+
+ -Update Centaur status sensor after discove targets is called
+ to initialize the Centaur Func sensors on the BMC
+
+Change-Id: I28b1047b50b690b97a20093721467f45455c5217
+RTC:124846
+(cherry picked from commit dd9502f744de8c09425d677570825699a979128f)
+---
+ src/usr/ipmi/ipmisensor.C | 15 ++++++++++++---
+ 1 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/src/usr/ipmi/ipmisensor.C b/src/usr/ipmi/ipmisensor.C
+index fba66a6..4b5b478 100644
+--- a/src/usr/ipmi/ipmisensor.C
++++ b/src/usr/ipmi/ipmisensor.C
+@@ -894,14 +894,19 @@ namespace SENSOR
+ // get all targets of the passed in type, functional or not
+ switch( i_type )
+ {
+- case TARGETING::TYPE_PROC:
+- getAllChips( l_tList, TARGETING::TYPE_PROC, false );
+- break;
+
+ case TARGETING::TYPE_DIMM:
+ getAllLogicalCards( l_tList, TARGETING::TYPE_DIMM, false );
+ break;
+
++ case TARGETING::TYPE_MEMBUF:
++ getAllChips( l_tList, TARGETING::TYPE_MEMBUF, false );
++ break;
++
++ case TARGETING::TYPE_PROC:
++ getAllChips( l_tList, TARGETING::TYPE_PROC, false );
++ break;
++
+ case TARGETING::TYPE_CORE:
+ getAllChiplets( l_tList, TARGETING::TYPE_CORE, false);
+ break;
+@@ -1024,6 +1029,10 @@ namespace SENSOR
+
+ void updateBMCSensorStatus()
+ {
++
++ // send status of all MEMBUF targets
++ updateBMCSensorStatus(TARGETING::TYPE_MEMBUF);
++
+ // send status of all DIMM targets
+ updateBMCSensorStatus(TARGETING::TYPE_DIMM);
+
+--
+1.7.4.1
+
diff --git a/openpower/package/hostboot/hostboot-0011-Update-Shutdown-Path-for-SBE-Updates.patch b/openpower/package/hostboot/hostboot-0011-Update-Shutdown-Path-for-SBE-Updates.patch
new file mode 100644
index 0000000..dc80e92
--- /dev/null
+++ b/openpower/package/hostboot/hostboot-0011-Update-Shutdown-Path-for-SBE-Updates.patch
@@ -0,0 +1,158 @@
+From c8c9edd25a04a8ff1974fd75e27a3b24b71030fc Mon Sep 17 00:00:00 2001
+From: Mike Baiocchi <baiocchi@us.ibm.com>
+Date: Fri, 27 Feb 2015 13:55:34 -0600
+Subject: [PATCH 6/7] Update Shutdown Path for SBE Updates
+
+This change will do the following:
+-- Flush out a console message to alert the user that the system is
+ shutting down to perform a SBE Update.
+-- Set the watchdog timer to 15 seconds before shutting down.
+-- Set the watchdog timer to NO_ACTIONS such that the boot count
+ sensor will handle the re-IPL.
+
+Change-Id: I3e8ca07030e50a56cd8bafc514bab036e3fdab96
+RTC: 120734
+(cherry picked from commit 20163b32e98f40e9346863e5954184958acc9af5)
+---
+ src/include/usr/ipmi/ipmiwatchdog.H | 1 +
+ src/usr/sbe/sbe_resolve_sides.C | 33 +++++++++++++++++++++++++--------
+ src/usr/sbe/sbe_resolve_sides.H | 4 ++++
+ src/usr/sbe/sbe_update.C | 14 ++++++++++++++
+ 4 files changed, 44 insertions(+), 8 deletions(-)
+
+diff --git a/src/include/usr/ipmi/ipmiwatchdog.H b/src/include/usr/ipmi/ipmiwatchdog.H
+index f23b771..62840ce 100644
+--- a/src/include/usr/ipmi/ipmiwatchdog.H
++++ b/src/include/usr/ipmi/ipmiwatchdog.H
+@@ -79,6 +79,7 @@ enum TIMER_USE
+ */
+ enum TIMER_ACTIONS
+ {
++ NO_ACTIONS = 0x00, // all bits
+ PRE_TIMEOUT_INT_SMI = 0x10, // bit 4
+ PRE_TIMEOUT_INT_NMI = 0x20, // bit 5
+ PRE_TIMEOUT_INT_MSG = 0x30, // bits 4 & 5
+diff --git a/src/usr/sbe/sbe_resolve_sides.C b/src/usr/sbe/sbe_resolve_sides.C
+index df9958d..90217b6 100644
+--- a/src/usr/sbe/sbe_resolve_sides.C
++++ b/src/usr/sbe/sbe_resolve_sides.C
+@@ -40,6 +40,7 @@
+ #include <sys/misc.h>
+ #include <hwas/common/deconfigGard.H>
+ #include <initservice/initserviceif.H>
++#include <console/consoleif.H>
+ #include <config.h>
+ #include <ipmi/ipmiwatchdog.H>
+ #include <ipmi/ipmisensor.H>
+@@ -285,7 +286,20 @@ errlHndl_t resolveProcessorSbeSeeproms()
+ l_restartNeeded);
+
+ #ifdef CONFIG_BMC_IPMI
+- sbePreShutdownIpmiCalls();
++ sbePreShutdownIpmiCalls();
++#endif
++
++#ifdef CONFIG_CONSOLE
++ #ifdef CONFIG_BMC_IPMI
++ CONSOLE::displayf(SBE_COMP_NAME, "System Shutting Down In %d "
++ "Seconds To Perform SBE Update\n",
++ SET_WD_TIMER_IN_SECS);
++ #else
++ CONSOLE::displayf(SBE_COMP_NAME, "System Shutting Down To "
++ "Perform SBE Update\n");
++ #endif
++
++ CONSOLE::flush();
+ #endif
+
+ TRACFCOMP( g_trac_sbe,
+@@ -1276,7 +1290,6 @@ errlHndl_t resolveImageHBBaddr(TARGETING::Target* i_target,
+ void sbePreShutdownIpmiCalls( void )
+ {
+ errlHndl_t err = NULL;
+-
+ TRACFCOMP( g_trac_sbe, ENTER_MRK"sbePreShutdownIpmiCalls");
+
+ do{
+@@ -1328,13 +1341,17 @@ void sbePreShutdownIpmiCalls( void )
+ }
+
+ // @todo RTC 124679 - Remove Once BMC Monitors Shutdown Attention
+- // Set Watchdog Timer To 10 seconds
+- const uint16_t SET_WD_TIMER_10_SECS = 10;
++ // Set Watchdog Timer before calling doShutdown()
+ TRACFCOMP( g_trac_sbe,"sbePreShutdownIpmiCalls: "
+ "Set Watch Dog Timer To %d Seconds",
+- SET_WD_TIMER_10_SECS);
+-
+- err = IPMIWATCHDOG::setWatchDogTimer(SET_WD_TIMER_10_SECS);
++ SET_WD_TIMER_IN_SECS);
++
++ err = IPMIWATCHDOG::setWatchDogTimer(
++ SET_WD_TIMER_IN_SECS, // new time
++ static_cast<uint8_t>
++ (IPMIWATCHDOG::DO_NOT_STOP |
++ IPMIWATCHDOG::BIOS_FRB2), // default
++ IPMIWATCHDOG::NO_ACTIONS); // boot count reset
+ if(err)
+ {
+ TRACFCOMP( g_trac_sbe,
+@@ -1342,7 +1359,7 @@ void sbePreShutdownIpmiCalls( void )
+ "FAIL Setting Watch Dog Timer to %d seconds. "
+ "Committing Error Log rc=0x%.4X eid=0x%.8X "
+ "plid=0x%.8X, but continuing shutdown",
+- SET_WD_TIMER_10_SECS,
++ SET_WD_TIMER_IN_SECS,
+ err->reasonCode(),
+ err->eid(),
+ err->plid());
+diff --git a/src/usr/sbe/sbe_resolve_sides.H b/src/usr/sbe/sbe_resolve_sides.H
+index 42f727a..d7c1f7c 100644
+--- a/src/usr/sbe/sbe_resolve_sides.H
++++ b/src/usr/sbe/sbe_resolve_sides.H
+@@ -50,6 +50,10 @@ namespace SBE
+ { EEPROM::SBE_PRIMARY,
+ EEPROM::SBE_BACKUP };
+
++ // @todo RTC 124679 - Remove Once BMC Monitors Shutdown Attention
++ // Set Watchdog Timer To 15 seconds before calling doShutdown()
++ const uint16_t SET_WD_TIMER_IN_SECS = 15;
++
+ /******************************************/
+ /* Enums */
+ /******************************************/
+diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C
+index 562798b..a20c1a8 100644
+--- a/src/usr/sbe/sbe_update.C
++++ b/src/usr/sbe/sbe_update.C
+@@ -46,6 +46,7 @@
+ #include <sys/msg.h>
+ #include <hwas/common/deconfigGard.H>
+ #include <initservice/initserviceif.H>
++#include <console/consoleif.H>
+ #include <config.h>
+ #include <sbe/sbeif.H>
+ #include <sbe/sbereasoncodes.H>
+@@ -371,6 +372,19 @@ namespace SBE
+ sbePreShutdownIpmiCalls();
+ #endif
+
++#ifdef CONFIG_CONSOLE
++ #ifdef CONFIG_BMC_IPMI
++ CONSOLE::displayf(SBE_COMP_NAME, "System Shutting Down In %d "
++ "Seconds To Perform SBE Update\n",
++ SET_WD_TIMER_IN_SECS);
++ #else
++ CONSOLE::displayf(SBE_COMP_NAME, "System Shutting Down To "
++ "Perform SBE Update\n");
++ #endif
++
++ CONSOLE::flush();
++#endif
++
+ TRACFCOMP( g_trac_sbe,
+ INFO_MRK"updateProcessorSbeSeeproms(): Calling "
+ "INITSERVICE::doShutdown() with "
+--
+1.7.4.1
+