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
+