blob: 94e4c49911488bc2657929eac7cec43b4b729731 [file] [log] [blame]
Andrew Geisslerff7983f2015-03-01 09:39:29 -06001From 842770c162544b35609528b205d7c015454593fa Mon Sep 17 00:00:00 2001
2From: Mike Baiocchi <baiocchi@us.ibm.com>
3Date: Tue, 17 Feb 2015 13:07:13 -0600
4Subject: [PATCH 4/7] GOLDEN SBE Update Support - Reconcile SBE images and PNOR sides
5
6This code adds a new function at istep 6 to reconcile the two
7SBE Seeproms with the PNOR side and mode (ie, 2-sided, golden, etc).
8It also updates what happens in istep 9 in SBE_UPDATE_INDEPENDENT
9mode.
10
11Change-Id: If71ca52338a179b8cf38cfa336d9790737844715
12RTC: 120734
13(cherry picked from commit fe9afa4e7a3b0eb0e9ae16abb943039aacf34e09)
14---
15 src/include/usr/sbe/sbeif.H | 13 +-
16 src/include/usr/sbe/sbereasoncodes.H | 10 +-
17 src/usr/hwpf/hwp/slave_sbe/slave_sbe.C | 12 +
18 src/usr/sbe/HBconfig | 6 +-
19 src/usr/sbe/makefile | 5 +-
20 src/usr/sbe/sbe_resolve_sides.C | 1363 ++++++++++++++++++++++++++++++++
21 src/usr/sbe/sbe_resolve_sides.H | 259 ++++++
22 src/usr/sbe/sbe_update.C | 124 +++-
23 8 files changed, 1753 insertions(+), 39 deletions(-)
24 create mode 100644 src/usr/sbe/sbe_resolve_sides.C
25 create mode 100644 src/usr/sbe/sbe_resolve_sides.H
26
27diff --git a/src/include/usr/sbe/sbeif.H b/src/include/usr/sbe/sbeif.H
28index 8706e91..9cf20c6 100644
29--- a/src/include/usr/sbe/sbeif.H
30+++ b/src/include/usr/sbe/sbeif.H
31@@ -5,7 +5,9 @@
32 /* */
33 /* OpenPOWER HostBoot Project */
34 /* */
35-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
36+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
37+/* [+] International Business Machines Corp. */
38+/* */
39 /* */
40 /* Licensed under the Apache License, Version 2.0 (the "License"); */
41 /* you may not use this file except in compliance with the License. */
42@@ -66,6 +68,15 @@ namespace SBE
43 */
44 errlHndl_t updateProcessorSbeSeeproms();
45
46+ /**
47+ * @brief Iterates through all the functional processors and resolves
48+ * the Hostboot Base Addresses (HBB) in each SBE Image and performs
49+ * any necessary operations related to GOLDEN side support.
50+ *
51+ * @return errlHndl_t Error log handle on failure.
52+ */
53+ errlHndl_t resolveProcessorSbeSeeproms();
54+
55
56 } //end namespace SBE
57
58diff --git a/src/include/usr/sbe/sbereasoncodes.H b/src/include/usr/sbe/sbereasoncodes.H
59index a09bb68..effb69e 100644
60--- a/src/include/usr/sbe/sbereasoncodes.H
61+++ b/src/include/usr/sbe/sbereasoncodes.H
62@@ -5,7 +5,9 @@
63 /* */
64 /* OpenPOWER HostBoot Project */
65 /* */
66-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
67+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
68+/* [+] International Business Machines Corp. */
69+/* */
70 /* */
71 /* Licensed under the Apache License, Version 2.0 (the "License"); */
72 /* you may not use this file except in compliance with the License. */
73@@ -54,6 +56,10 @@ enum sbeModuleId
74 SBE_CUSTOMIZE_IMG = 0x0B,
75 SBE_PERFORM_UPDATE_ACTIONS = 0x0C,
76 SBE_MASTER_VERSION_COMPARE = 0x0D,
77+ SBE_RESOLVE_HBB_ADDR = 0x0E,
78+ SBE_READ_SBE_IMAGE = 0x0F,
79+ SBE_WRITE_SBE_IMAGE = 0x10,
80+ SBE_GET_SBE_IMAGE_SIZE = 0x11,
81 };
82
83 /**
84@@ -91,6 +97,8 @@ enum sbeReasonCode
85 SBE_MISCOMPARE_WITH_MASTER_VERSION = SBE_COMP_ID | 0x13,
86 SBE_ERROR_ON_UPDATE = SBE_COMP_ID | 0x14,
87 SBE_MASTER_VERSION_DOWNLEVEL = SBE_COMP_ID | 0x15,
88+ SBE_IMAGE_GET_SET_SCALAR_FAIL = SBE_COMP_ID | 0x16,
89+
90 };
91
92 }; // end SBE
93diff --git a/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C b/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C
94index 49225a4..fe568e2 100644
95--- a/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C
96+++ b/src/usr/hwpf/hwp/slave_sbe/slave_sbe.C
97@@ -175,6 +175,18 @@ void* call_host_slave_sbe_config(void *io_pArgs)
98
99 }
100 }
101+
102+ // Resolve the side characteristics of the Processor SBE Seeproms
103+ errlHndl_t err = SBE::resolveProcessorSbeSeeproms();
104+ if ( err )
105+ {
106+ // Create IStep error log and cross reference error that occurred
107+ l_stepError.addErrorDetails( err );
108+
109+ // Commit Error
110+ errlCommit( err, HWPF_COMP_ID );
111+ }
112+
113 TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
114 "call_host_slave_sbe_config exit" );
115
116diff --git a/src/usr/sbe/HBconfig b/src/usr/sbe/HBconfig
117index 0fa2441..fd2a8d0 100644
118--- a/src/usr/sbe/HBconfig
119+++ b/src/usr/sbe/HBconfig
120@@ -20,9 +20,9 @@ config SBE_UPDATE_INDEPENDENT
121 depends on !SBE_UPDATE_SEQUENTIAL && !SBE_UPDATE_SIMULTANEOUS
122 help
123 If an update is necessary, and if the "current" SBE SEEPROM of this
124- IPL is not the 'GOLDEN' SBE SEEPROM, then only the current SBE SEEPROM
125- will be updated. After the update a re-IPL request will be issued.
126- The other SBE SEEPROM, whether 'GOLDEN' or not, will not be updated.
127+ IPL is not pointing at PNOR's 'GOLDEN' side, then only the current SBE
128+ SEEPROM will be updated. After the update a re-IPL request will be
129+ issued. The other SBE SEEPROM will not be updated.
130
131 config NO_SBE_UPDATES
132 default n
133diff --git a/src/usr/sbe/makefile b/src/usr/sbe/makefile
134index 06159ff..c45206e 100644
135--- a/src/usr/sbe/makefile
136+++ b/src/usr/sbe/makefile
137@@ -5,7 +5,9 @@
138 #
139 # OpenPOWER HostBoot Project
140 #
141-# COPYRIGHT International Business Machines Corp. 2013,2014
142+# Contributors Listed Below - COPYRIGHT 2013,2015
143+# [+] International Business Machines Corp.
144+#
145 #
146 # Licensed under the Apache License, Version 2.0 (the "License");
147 # you may not use this file except in compliance with the License.
148@@ -36,6 +38,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/include
149 EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build
150
151 OBJS += sbe_update.o
152+OBJS += sbe_resolve_sides.o
153
154 SUBDIRS += test.d
155
156diff --git a/src/usr/sbe/sbe_resolve_sides.C b/src/usr/sbe/sbe_resolve_sides.C
157new file mode 100644
158index 0000000..df9958d
159--- /dev/null
160+++ b/src/usr/sbe/sbe_resolve_sides.C
161@@ -0,0 +1,1363 @@
162+/* IBM_PROLOG_BEGIN_TAG */
163+/* This is an automatically generated prolog. */
164+/* */
165+/* $Source: src/usr/sbe/sbe_resolve_sides.C $ */
166+/* */
167+/* OpenPOWER HostBoot Project */
168+/* */
169+/* Contributors Listed Below - COPYRIGHT 2015 */
170+/* [+] International Business Machines Corp. */
171+/* */
172+/* */
173+/* Licensed under the Apache License, Version 2.0 (the "License"); */
174+/* you may not use this file except in compliance with the License. */
175+/* You may obtain a copy of the License at */
176+/* */
177+/* http://www.apache.org/licenses/LICENSE-2.0 */
178+/* */
179+/* Unless required by applicable law or agreed to in writing, software */
180+/* distributed under the License is distributed on an "AS IS" BASIS, */
181+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
182+/* implied. See the License for the specific language governing */
183+/* permissions and limitations under the License. */
184+/* */
185+/* IBM_PROLOG_END_TAG */
186+
187+#include <trace/interface.H>
188+#include <errl/errlentry.H>
189+#include <errl/errlmanager.H>
190+#include <errl/errludtarget.H>
191+#include <errl/errlreasoncodes.H>
192+#include <errl/hberrltypes.H>
193+#include <targeting/common/predicates/predicatectm.H>
194+#include <targeting/common/utilFilter.H>
195+#include <targeting/common/targetservice.H>
196+#include <util/misc.H>
197+#include <pnor/pnorif.H>
198+#include <pnor/ecc.H>
199+#include <devicefw/driverif.H>
200+#include <sys/mm.h>
201+#include <sys/misc.h>
202+#include <hwas/common/deconfigGard.H>
203+#include <initservice/initserviceif.H>
204+#include <config.h>
205+#include <ipmi/ipmiwatchdog.H>
206+#include <ipmi/ipmisensor.H>
207+#include <sbe/sbeif.H>
208+#include <sbe/sbereasoncodes.H>
209+#include "sbe_resolve_sides.H"
210+#include "sbe_update.H"
211+
212+// fapi support
213+#include <fapi.H>
214+#include <fapiHwpExecutor.H>
215+#include <hwpf/plat/fapiPlatHwpInvoker.H>
216+#include <hwpf/plat/fapiPlatTrace.H>
217+
218+//Procedures
219+#include <p8_xip_customize.H>
220+#include <sbe_xip_image.h>
221+#include <p8_image_help_base.H>
222+
223+// ----------------------------------------------
224+// Trace definitions
225+// ----------------------------------------------
226+extern trace_desc_t* g_trac_sbe;
227+
228+// ------------------------
229+// Macros for unit testing
230+//#define TRACUCOMP(args...) TRACFCOMP(args)
231+#define TRACUCOMP(args...)
232+
233+
234+using namespace ERRORLOG;
235+using namespace TARGETING;
236+
237+namespace SBE
238+{
239+ enum {
240+ SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE,
241+ RING_BUF1_VADDR = FIXED_SEEPROM_WORK_SPACE + SBE_IMG_VADDR,
242+ RING_BUF2_VADDR = RING_BUF1_VADDR + FIXED_RING_BUF_SIZE,
243+ //NOTE: recycling the same memory space for different
244+ //steps in the process.
245+ SBE_ECC_IMG_VADDR = RING_BUF1_VADDR,
246+ SBE_ECC_IMG_MAX_SIZE = VMM_VADDR_SBE_UPDATE_END - SBE_ECC_IMG_VADDR,
247+ };
248+
249+/////////////////////////////////////////////////////////////////////
250+errlHndl_t resolveProcessorSbeSeeproms()
251+{
252+ errlHndl_t err = NULL;
253+ errlHndl_t err_cleanup = NULL;
254+ sbeResolveState_t sideState;
255+ bool l_cleanupVmmSpace = false;
256+ bool l_restartNeeded = false;
257+
258+ TRACUCOMP( g_trac_sbe,
259+ ENTER_MRK"resolveProcessorSbeSeeproms()" );
260+
261+ do{
262+
263+#ifdef CONFIG_NO_SBE_UPDATES
264+ TRACFCOMP( g_trac_sbe, INFO_MRK"resolveProcessorSbeSeeproms() - "
265+ "SBE updates not configured");
266+ break;
267+#endif
268+
269+#ifdef CONFIG_SBE_UPDATE_SIMULTANEOUS
270+ TRACFCOMP( g_trac_sbe, INFO_MRK"resolveProcessorSbeSeeproms() - "
271+ "Do Nothing in SBE_UPDATE_SIMULTANEOUS mode");
272+ break;
273+#endif
274+
275+#ifdef CONFIG_SBE_UPDATE_SEQUENTIAL
276+ // Check if FSP-services are enabled and if we're running in simics
277+ if ( !INITSERVICE::spBaseServicesEnabled() &&
278+ !Util::isSimicsRunning() )
279+ {
280+ assert (false, "resolveProcessorSbeSeeproms() - "
281+ "SBE_UPDATE_SEQUENTIAL mode, but FSP-services are not "
282+ "enabled - Invalid Configuration");
283+ }
284+ else
285+ {
286+ TRACUCOMP( g_trac_sbe, INFO_MRK"resolveProcessorSbeSeeproms() - "
287+ "Do Nothing in SBE_UPDATE_INDEPENDENT mode with FSP-"
288+ "services enabled or running in simics");
289+ break;
290+ }
291+#endif
292+
293+ // Get Target Service, and the system target.
294+ TargetService& tS = targetService();
295+ TARGETING::Target* sys = NULL;
296+ (void) tS.getTopLevelTarget( sys );
297+ assert(sys, "resolveProcessorSbeSeeproms() system target is NULL");
298+
299+
300+ //Make sure procedure constants keep within expected range.
301+ assert((FIXED_SEEPROM_WORK_SPACE <= VMM_SBE_UPDATE_SIZE/2),
302+ "resolveProcessorSbeSeeproms() FIXED_SEEPROM_WORK_SPACE "
303+ "too large");
304+ assert((FIXED_RING_BUF_SIZE <= VMM_SBE_UPDATE_SIZE/4),
305+ "resolveProcessorSbeSeeproms() FIXED_RING_BUF_SIZE too "
306+ "large");
307+
308+ // Create VMM space for p8_xip_customize() procedure
309+ err = createSbeImageVmmSpace();
310+ if (err)
311+ {
312+ TRACFCOMP( g_trac_sbe,
313+ INFO_MRK"resolveProcessorSbeSeeproms: "
314+ "createSbeImageVmmSpace() Failed. ",
315+ "rc=0x%.4X", err->reasonCode() );
316+
317+ break;
318+ }
319+ else
320+ {
321+ // Make sure cleanup gets called
322+ l_cleanupVmmSpace = true;
323+ }
324+
325+ /*****************************************************************/
326+ /* Iterate over all the functional processors and do for each: */
327+ /*****************************************************************/
328+ TARGETING::TargetHandleList procList;
329+ TARGETING::getAllChips(procList,
330+ TARGETING::TYPE_PROC,
331+ true); // true: return functional targets
332+
333+ if( ( 0 == procList.size() ) ||
334+ ( NULL == procList[0] ) )
335+ {
336+ TRACFCOMP( g_trac_sbe, ERR_MRK"resolveProcessorSbeSeeproms() - "
337+ "No functional processors Found!" );
338+ break;
339+ }
340+
341+ for(uint32_t i=0; i<procList.size(); i++)
342+ {
343+ /***********************************************/
344+ /* Get Side This Processor did/will boot from */
345+ /***********************************************/
346+ memset(&sideState, 0, sizeof(sideState));
347+ sideState.tgt = procList[i];
348+
349+ err = getSideState(sideState);
350+ if ( err )
351+ {
352+ TRACFCOMP( g_trac_sbe, ERR_MRK
353+ "resolveProcessorSbeSeeproms: Error returned "
354+ "from getSideState() "
355+ "rc=0x%.4X, Target UID=0x%X",
356+ err->reasonCode(),
357+ TARGETING::get_huid(sideState.tgt));
358+ // Don't break - handle error at the end of the loop
359+ }
360+
361+
362+ /**********************************************/
363+ /* Determine the necessary actions */
364+ /**********************************************/
365+ // Skip if we got an error previously
366+ if ( err == NULL )
367+ {
368+ err = getSideActions(sideState);
369+ if (err)
370+ {
371+ TRACFCOMP( g_trac_sbe,
372+ INFO_MRK"resolveProcessorSbeSeeproms: "
373+ "getSideActions() Failed "
374+ "rc=0x%.4X, Target UID=0x%X",
375+ err->reasonCode(),
376+ TARGETING::get_huid(sideState.tgt));
377+
378+ // Don't break - handle error at the end of the loop,
379+ }
380+ }
381+
382+ /**********************************************/
383+ /* Perform the necessary actions */
384+ /**********************************************/
385+ // Skip if we got an error previously
386+ if ( err == NULL )
387+ {
388+ err = performSideActions(sideState);
389+ if (err)
390+ {
391+ TRACFCOMP( g_trac_sbe,
392+ INFO_MRK"resolveProcessorSbeSeeproms: "
393+ "performSideActions() Failed "
394+ "rc=0x%.4X, Target UID=0x%X",
395+ err->reasonCode(),
396+ TARGETING::get_huid(sideState.tgt));
397+
398+ // Don't break - handle error at the end of the loop,
399+ }
400+ else
401+ {
402+ // Target updated without failure, so set IPL_RESTART
403+ // flag, if necessary
404+ if (sideState.actions & REIPL)
405+ {
406+ l_restartNeeded = true;
407+ }
408+ }
409+ }
410+
411+ /**********************************************/
412+ /* Handle Errors */
413+ /**********************************************/
414+
415+ if ( err )
416+ {
417+ // Something failed for this target.
418+
419+ // Commit the error here and move on to the next target,
420+ // or if no targets left, will just continue the IPL
421+ TRACFCOMP( g_trac_sbe,
422+ INFO_MRK"resolveProcessorSbeSeeproms: "
423+ "Committing Error Log rc=0x%.4X eid=0x%.8X "
424+ "plid=0x%.8X for Target UID=0x%X, but "
425+ "continuing procedure",
426+ err->reasonCode(),
427+ err->eid(),
428+ err->plid(),
429+ TARGETING::get_huid(sideState.tgt));
430+ errlCommit( err, SBE_COMP_ID );
431+ }
432+
433+
434+ } //end of Target for loop collecting each target's SBE State
435+
436+
437+ /**************************************************************/
438+ /* Perform System Operation */
439+ /**************************************************************/
440+ // Restart IPL if SBE Update requires it
441+ if ( l_restartNeeded == true )
442+ {
443+ TRACFCOMP( g_trac_sbe,
444+ INFO_MRK"resolveProcessorSbeSeeprom: Restart "
445+ "Needed (%d).",
446+ l_restartNeeded);
447+
448+#ifdef CONFIG_BMC_IPMI
449+ sbePreShutdownIpmiCalls();
450+#endif
451+
452+ TRACFCOMP( g_trac_sbe,
453+ INFO_MRK"resolveProcessorSbeSeeproms: Calling "
454+ "INITSERVICE::doShutdown() with "
455+ "SBE_UPDATE_REQUEST_REIPL = 0x%X",
456+ SBE_UPDATE_REQUEST_REIPL );
457+ INITSERVICE::doShutdown(SBE_UPDATE_REQUEST_REIPL);
458+ }
459+
460+ }while(0);
461+
462+
463+ // Cleanup VMM Workspace
464+ if ( l_cleanupVmmSpace == true )
465+ {
466+ err_cleanup = cleanupSbeImageVmmSpace();
467+ if ( err_cleanup != NULL )
468+ {
469+
470+ if ( err != NULL )
471+ {
472+ // 2 error logs, so commit the cleanup log here
473+ TRACFCOMP( g_trac_sbe,
474+ ERR_MRK"resolveProcessorSbeSeeproms: Previous "
475+ "error (rc=0x%X) before cleanupSbeImageVmmSpace"
476+ "() failed. Committing cleanup error (rc=0x%X) "
477+ "and returning original error",
478+ err->reasonCode(), err_cleanup->reasonCode() );
479+
480+ errlCommit( err_cleanup, SBE_COMP_ID );
481+ }
482+ else
483+ {
484+ // no previous error, so returning cleanup error
485+ TRACFCOMP( g_trac_sbe,
486+ ERR_MRK"resolveProcessorSbeSeeproms: "
487+ "cleanupSbeImageVmmSpace() failed.",
488+ "rc=0x%.4X", err_cleanup->reasonCode() );
489+ err = err_cleanup;
490+ }
491+ }
492+ }
493+
494+
495+ TRACUCOMP( g_trac_sbe,
496+ EXIT_MRK"resolveProcessorSbeSeeproms()" );
497+
498+ return err;
499+}
500+
501+/////////////////////////////////////////////////////////////////////
502+errlHndl_t getSideState(sbeResolveState_t& io_sideState)
503+{
504+ errlHndl_t err = NULL;
505+ TRACUCOMP( g_trac_sbe,
506+ ENTER_MRK"getSideState()" );
507+
508+ do{
509+
510+ /***********************************************/
511+ /* Get Side This Processor did/will boot from */
512+ /***********************************************/
513+ PNOR::sbeSeepromSide_t tmp_cur_side = PNOR::SBE_SEEPROM_INVALID;
514+ err = PNOR::getSbeBootSeeprom(io_sideState.tgt, tmp_cur_side);
515+ if ( err )
516+ {
517+ TRACFCOMP( g_trac_sbe, ERR_MRK
518+ "resolveProcessorSbeSeeproms() - Error returned "
519+ "from PNOR::getSbeBootSeeprom() "
520+ "rc=0x%.4X, Target UID=0x%X",
521+ err->reasonCode(),
522+ TARGETING::get_huid(io_sideState.tgt));
523+ break;
524+ }
525+
526+ io_sideState.cur_side = tmp_cur_side;
527+
528+ io_sideState.alt_side = (tmp_cur_side == PNOR::SBE_SEEPROM0)
529+ ? PNOR::SBE_SEEPROM1 : PNOR::SBE_SEEPROM0;
530+
531+ /**********************************************/
532+ /* Get PNOR Side Information */
533+ /**********************************************/
534+ PNOR::SideId tmp_side = PNOR::WORKING;
535+ PNOR::SideInfo_t tmp_side_info;
536+ err = PNOR::getSideInfo (tmp_side, tmp_side_info);
537+ if ( err )
538+ {
539+ TRACFCOMP( g_trac_sbe, ERR_MRK
540+ "resolveProcessorSbeSeeproms() - Error returned "
541+ "from PNOR::getSideInfo() "
542+ "rc=0x%.4X, Target UID=0x%X",
543+ err->reasonCode(),
544+ TARGETING::get_huid(io_sideState.tgt));
545+ break;
546+ }
547+
548+ io_sideState.pnor_sideId = tmp_side_info.id;
549+ io_sideState.pnor_side = tmp_side_info.side;
550+ io_sideState.pnor_isGolden = tmp_side_info.isGolden;
551+ io_sideState.pnor_hasOtherSide = tmp_side_info.hasOtherSide;
552+
553+ }while(0);
554+
555+
556+ TRACUCOMP( g_trac_sbe,
557+ EXIT_MRK"getSideState(): cur/alt=%d/%d. Side-%c(%d): "
558+ "isGolden=%d, hasOtherSide=%d",
559+ io_sideState.cur_side, io_sideState.alt_side,
560+ io_sideState.pnor_side, io_sideState.pnor_sideId,
561+ io_sideState.pnor_isGolden, io_sideState.pnor_hasOtherSide );
562+
563+ return err;
564+}
565+
566+
567+/////////////////////////////////////////////////////////////////////
568+errlHndl_t getSideActions(sbeResolveState_t& io_sideState)
569+{
570+ errlHndl_t err = NULL;
571+ uint32_t l_actions = NO_ACTIONS;
572+ TRACUCOMP( g_trac_sbe,
573+ ENTER_MRK"getSideActions()" );
574+
575+ do{
576+
577+ // Check if PNOR is running from its GOLDEN side
578+ if ( io_sideState.pnor_isGolden == true )
579+ {
580+
581+ // If Booting From Seeprom that is pointing to PNOR's GOLDEN Side
582+ // and is possibly the READ_ONLY_SEEPROM - No Re-IPL
583+ if ( io_sideState.cur_side == READ_ONLY_SEEPROM )
584+ {
585+ l_actions |= COPY_READ_ONLY_TO_WORKING;
586+ io_sideState.update_side = io_sideState.alt_side;
587+#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
588+ // Need info from PNOR's non-working side for update side
589+ l_actions |= USE_PNOR_ALT_SIDE;
590+ TRACUCOMP( g_trac_sbe, "getSideActions(): Asking for "
591+ "USE_PNOR_ALT_SIDE: actions=0x%X", l_actions);
592+#endif
593+ }
594+ else
595+ {
596+ // non-READ_ONLY_SEEPROM is pointing to PNOR's GOLDEN side
597+ // This requires an update and re-IPL (Possibly Genesis Mode)
598+ l_actions |= COPY_READ_ONLY_TO_WORKING;
599+ l_actions |= REIPL;
600+ io_sideState.update_side = io_sideState.cur_side;
601+
602+#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
603+ // Need info from PNOR's non-working side for update side
604+ l_actions |= USE_PNOR_ALT_SIDE;
605+ TRACUCOMP( g_trac_sbe, "getSideActions(): Asking for "
606+ "USE_PNOR_ALT_SIDE: actions=0x%X", l_actions);
607+#endif
608+
609+ }
610+ }
611+
612+ // Even though READ_ONLY_SEEPROM is not pointing to PNOR's GOLDEN side,
613+ // treat like it is if there is only 1 side (ie, Palmetto configuration)
614+ else if ( ( io_sideState.pnor_hasOtherSide == false ) &&
615+ ( io_sideState.cur_side == READ_ONLY_SEEPROM ) )
616+ {
617+ l_actions |= COPY_READ_ONLY_TO_WORKING;
618+ io_sideState.update_side = io_sideState.alt_side;
619+ }
620+
621+ else // current Seeprom not pointing to PNOR's GOLDEN side
622+ {
623+ l_actions |= CHECK_WORKING_HBB;
624+ io_sideState.update_side = io_sideState.cur_side;
625+ // REIPL action will be determined later
626+ }
627+
628+ io_sideState.actions = l_actions;
629+
630+ TRACUCOMP( g_trac_sbe, "getSideActions() Tgt=0x%X: "
631+ "pnor_isGolden/hasOtherSide=%d/%d, actions=0x%.8X, "
632+ "Update Side=0x%X, cur=%d",
633+ TARGETING::get_huid(io_sideState.tgt),
634+ io_sideState.pnor_isGolden, io_sideState.pnor_hasOtherSide,
635+ io_sideState.actions,
636+ io_sideState.update_side,
637+ io_sideState.cur_side);
638+
639+ }while(0);
640+
641+ TRACUCOMP( g_trac_sbe,
642+ EXIT_MRK"getSideActions()" );
643+
644+ return err;
645+}
646+
647+
648+
649+/////////////////////////////////////////////////////////////////////
650+errlHndl_t performSideActions(sbeResolveState_t& io_sideState)
651+{
652+ errlHndl_t err = NULL;
653+ TRACUCOMP( g_trac_sbe,
654+ ENTER_MRK"performSideActions()" );
655+
656+ bool updateForHBB = false;
657+ size_t image_size = 0;
658+ sbeSeepromVersionInfo_t image_version;
659+
660+ do{
661+ if ( io_sideState.actions & COPY_READ_ONLY_TO_WORKING )
662+ {
663+ // Copy READ_ONLY SBE Seeprom Image to Memory
664+ err = readSbeImage(io_sideState.tgt,
665+ reinterpret_cast<void*>(SBE_IMG_VADDR),
666+ READ_ONLY_SEEPROM,
667+ image_size,
668+ image_version);
669+ if ( err )
670+ {
671+ TRACFCOMP( g_trac_sbe, ERR_MRK
672+ "performSideActions: Error returned from "
673+ "getSetSbeImage() rc=0x%.4X, Target UID=0x%X, "
674+ "actions = 0x%X, image_size=0x%X",
675+ err->reasonCode(),
676+ TARGETING::get_huid(io_sideState.tgt),
677+ io_sideState.actions, image_size);
678+ break;
679+ }
680+ }
681+
682+ if ( io_sideState.actions & CHECK_WORKING_HBB )
683+ {
684+
685+ // Copy current SBE Seeprom Image to Memory
686+ // NOTE: Seprate section from above because of possible future
687+ // improvement to use MBPD SB Keyword bit to keep track of HBB
688+
689+ err = readSbeImage(io_sideState.tgt,
690+ reinterpret_cast<void*>(SBE_IMG_VADDR),
691+ io_sideState.update_side,
692+ image_size,
693+ image_version);
694+ if ( err )
695+ {
696+ TRACFCOMP( g_trac_sbe, ERR_MRK
697+ "performSideActions: Error returned from "
698+ "getSetSbeImage() rc=0x%.4X, Target UID=0x%X, "
699+ "actions = 0x%X, image_size=0x%X",
700+ err->reasonCode(),
701+ TARGETING::get_huid(io_sideState.tgt),
702+ io_sideState.actions, image_size);
703+ break;
704+ }
705+
706+ }
707+
708+
709+ if ( ( io_sideState.actions & COPY_READ_ONLY_TO_WORKING ) ||
710+ ( io_sideState.actions & CHECK_WORKING_HBB ) )
711+ {
712+ // verify HBB
713+ PNOR::SideId pnor_side = PNOR::WORKING;
714+
715+#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
716+ // In certain situations need info from Alternate PNOR
717+ if ( io_sideState.actions & USE_PNOR_ALT_SIDE)
718+ {
719+ pnor_side = PNOR::ALTERNATE;
720+ }
721+#endif
722+
723+
724+
725+ err = resolveImageHBBaddr(io_sideState.tgt,
726+ reinterpret_cast<void*>(SBE_IMG_VADDR),
727+ io_sideState.update_side,
728+ pnor_side,
729+ updateForHBB);
730+ if ( err )
731+ {
732+ TRACFCOMP( g_trac_sbe, ERR_MRK
733+ "performSideActions: Error returned from "
734+ "resolveImageHBBaddr() rc=0x%.4X, Target UID=0x%X, "
735+ "actions = 0x%X",
736+ err->reasonCode(),
737+ TARGETING::get_huid(io_sideState.tgt),
738+ io_sideState.actions);
739+ break;
740+ }
741+
742+ // Since HBB was updated, we need to re-IPL if not booting on
743+ // READ_ONLY seeprom
744+ if ( ( updateForHBB == true ) &&
745+ ( io_sideState.cur_side != READ_ONLY_SEEPROM ) )
746+ {
747+ io_sideState.actions |= REIPL;
748+ TRACUCOMP( g_trac_sbe, ERR_MRK
749+ "performSideActions: resolveImageHBBaddr returned "
750+ "updateForHBB=%d, and not on READ_ONLY_SEEPROM so "
751+ "REIPL (actions=0x%X)",
752+ updateForHBB, io_sideState.actions);
753+ }
754+ }
755+
756+ if ( ( io_sideState.actions & COPY_READ_ONLY_TO_WORKING ) ||
757+ ( updateForHBB == true ) )
758+ {
759+ // Write Seeprom Image from memory to Seeprom
760+ err = writeSbeImage(io_sideState.tgt,
761+ reinterpret_cast<void*>(SBE_IMG_VADDR),
762+ io_sideState.update_side,
763+ image_size,
764+ image_version);
765+ if ( err )
766+ {
767+ TRACFCOMP( g_trac_sbe, ERR_MRK
768+ "performSideActions: Error returned from "
769+ "getSetSbeImage() rc=0x%.4X, Target UID=0x%X, "
770+ "actions = 0x%X",
771+ err->reasonCode(),
772+ TARGETING::get_huid(io_sideState.tgt),
773+ io_sideState.actions);
774+ break;
775+ }
776+ }
777+
778+ }while(0);
779+
780+ TRACUCOMP( g_trac_sbe,
781+ EXIT_MRK"performSideActions()" );
782+
783+ return err;
784+}
785+
786+
787+/////////////////////////////////////////////////////////////////////
788+errlHndl_t readSbeImage(TARGETING::Target* i_target,
789+ void* o_imgPtr,
790+ PNOR::sbeSeepromSide_t i_side,
791+ size_t& o_image_size,
792+ sbeSeepromVersionInfo_t& o_image_version)
793+{
794+ TRACUCOMP( g_trac_sbe,
795+ ENTER_MRK"readSbeImage(): tgt=0x%X, i_side=%d "
796+ "o_imgPtr=%p, o_image_size=0x%X",
797+ TARGETING::get_huid(i_target), i_side, o_imgPtr, o_image_size);
798+
799+ errlHndl_t err = NULL;
800+ int64_t rc = 0;
801+ PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN;
802+ EEPROM::eeprom_chip_types_t l_seeprom = sbe_side_sync[i_side];
803+ size_t image_size_ECC = 0;
804+
805+ // Need to ensure that io_imgPtr is at SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
806+ // since we need to use the VMM_VADDR_SBE_UPDATE space
807+ assert ( o_imgPtr == reinterpret_cast<void*>(SBE_IMG_VADDR),
808+ "getSetSbeImage() - o_imgPtr is not at SBE_IMG_VADDR");
809+
810+ do{
811+
812+ // Clear out back half of page block to use as temp space
813+ // for ECC injected SBE Image.
814+ rc = mm_remove_pages(RELEASE,
815+ reinterpret_cast<void*>
816+ (SBE_ECC_IMG_VADDR),
817+ SBE_ECC_IMG_MAX_SIZE);
818+ if( rc )
819+ {
820+ TRACFCOMP( g_trac_sbe, ERR_MRK"getSetSbeImage() - Error "
821+ "from mm_remove_pages : rc=%d, HUID=0x%.8X.",
822+ rc, TARGETING::get_huid(i_target) );
823+ /*@
824+ * @errortype
825+ * @moduleid SBE_READ_SBE_IMAGE
826+ * @reasoncode SBE_REMOVE_PAGES_FOR_EC
827+ * @userdata1 Requested Address
828+ * @userdata2 rc from mm_remove_pages
829+ * @devdesc updateProcessorSbeSeeproms> mm_remove_pages
830+ * RELEASE failed
831+ * @custdesc A problem occurred while updating processor
832+ * boot code.
833+ */
834+ err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
835+ SBE_READ_SBE_IMAGE,
836+ SBE_REMOVE_PAGES_FOR_EC,
837+ TO_UINT64(SBE_ECC_IMG_VADDR),
838+ TO_UINT64(rc),
839+ true /*Add HB SW Callout*/ );
840+
841+ //Target isn't directly related to fail, but could be useful
842+ // to see how far we got before failing.
843+ ErrlUserDetailsTarget(i_target).addToLog(err);
844+ err->collectTrace(SBE_COMP_NAME);
845+ break;
846+ }
847+
848+ /*****************************************/
849+ /* Get Image Size */
850+ /*****************************************/
851+ err = getSbeImageSize(i_target,
852+ o_imgPtr,
853+ i_side,
854+ o_image_size);
855+ if(err)
856+ {
857+ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: - Error from "
858+ "getSbeImageSize(): rc=0x%.4X, side=%d, HUID=0x%.8X.",
859+ err->reasonCode(),
860+ i_side, TARGETING::get_huid(i_target));
861+ break;
862+ }
863+
864+
865+ /*****************************************/
866+ /* Do Actual Read */
867+ /*****************************************/
868+ image_size_ECC = ALIGN_8((o_image_size*9)/8);
869+
870+ assert(image_size_ECC <= SBE_ECC_IMG_MAX_SIZE,
871+ "getSetSbeImage() SBE Image with ECC too large");
872+
873+ // Read image to memory space
874+ err = DeviceFW::deviceOp(
875+ DeviceFW::READ,
876+ i_target,
877+ reinterpret_cast<void*>
878+ (SBE_ECC_IMG_VADDR),
879+ image_size_ECC,
880+ DEVICE_EEPROM_ADDRESS(
881+ l_seeprom,
882+ SBE_IMAGE_SEEPROM_ADDRESS));
883+
884+ if(err)
885+ {
886+ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: - Error "
887+ "from EEPROM op: rc=0x%.4X, seeprom=%d (side=%d). "
888+ "HUID=0x%.8X. SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, "
889+ "size=0x%.8X, eccSize=0x%.8X, EEPROM offset=0x%X",
890+ err->reasonCode(), l_seeprom, i_side,
891+ TARGETING::get_huid(i_target),
892+ SBE_IMG_VADDR, SBE_ECC_IMG_VADDR, o_image_size,
893+ image_size_ECC, SBE_IMAGE_SEEPROM_ADDRESS);
894+ break;
895+ }
896+
897+ /*****************************************/
898+ /* Remove ECC From Image */
899+ /*****************************************/
900+
901+ // Clear destination
902+ memset( o_imgPtr, 0, MAX_SEEPROM_IMAGE_SIZE );
903+
904+ // Remove ECC
905+ eccStatus = PNOR::ECC::removeECC(reinterpret_cast<uint8_t*>
906+ (SBE_ECC_IMG_VADDR),
907+ reinterpret_cast<uint8_t*>
908+ (o_imgPtr),
909+ image_size_ECC);
910+
911+ // Fail if uncorrectable ECC
912+ if ( eccStatus == PNOR::ECC::UNCORRECTABLE )
913+ {
914+ // There is an ECC issue with this SEEPROM
915+
916+ TRACFCOMP( g_trac_sbe,ERR_MRK"readSbeImage: ECC Error "
917+ "On SBE Image Read eccStatus=%d sI=%d, sI_ECC="
918+ "%d, HUID=0x%.8X, Seeprom %d (side=%d)",
919+ eccStatus, o_image_size, image_size_ECC,
920+ TARGETING::get_huid(i_target),
921+ l_seeprom, i_side );
922+
923+ /*@
924+ * @errortype
925+ * @moduleid SBE_READ_SBE_IMAGE
926+ * @reasoncode SBE_ECC_FAIL
927+ * @userdata1[0:15] ECC Status
928+ * @userdata1[16:31] SEEPROM Side
929+ * @userdata1[32:63] Target HUID
930+ * @userdata2[0:31] Size - No Ecc
931+ * @userdata2[32:63] Size - ECC
932+ * @devdesc ECC Fail Reading SBE Image
933+ */
934+ err = new ErrlEntry(ERRL_SEV_PREDICTIVE,
935+ SBE_READ_SBE_IMAGE,
936+ SBE_ECC_FAIL,
937+ TWO_UINT32_TO_UINT64(
938+ ( (eccStatus << 16 ) |
939+ l_seeprom ),
940+ TARGETING::get_huid(i_target)),
941+ TWO_UINT32_TO_UINT64(o_image_size,
942+ image_size_ECC));
943+
944+ err->collectTrace(SBE_COMP_NAME);
945+
946+ err->addPartCallout(
947+ i_target,
948+ HWAS::SBE_SEEPROM_PART_TYPE,
949+ HWAS::SRCI_PRIORITY_HIGH,
950+ HWAS::NO_DECONFIG,
951+ HWAS::GARD_NULL );
952+
953+ ErrlUserDetailsTarget(i_target).addToLog(err);
954+
955+ break;
956+
957+ } // ECC check
958+
959+
960+ // Read out SBE Version Info
961+ bool seeprom_ver_ECC_fail = false;
962+ err = getSeepromSideVersion(i_target,
963+ l_seeprom,
964+ o_image_version,
965+ seeprom_ver_ECC_fail);
966+
967+
968+ if(err)
969+ {
970+ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: - Error "
971+ "from getSeepromSideVersion: rc=0x%.4X, seeprom=%d "
972+ "(side=%d). HUID=0x%.8X",
973+ err->reasonCode(), l_seeprom, i_side,
974+ TARGETING::get_huid(i_target));
975+ break;
976+ }
977+
978+ else if (seeprom_ver_ECC_fail == true)
979+ {
980+ // For now, any issues will be addressed in SBE Update
981+ // later in the IPL
982+ TRACFCOMP( g_trac_sbe, ERR_MRK"readSbeImage: ECC fail=%d "
983+ "Reading Seeprom Version seeprom=%d "
984+ "(side=%d). HUID=0x%.8X",
985+ seeprom_ver_ECC_fail, l_seeprom, i_side,
986+ TARGETING::get_huid(i_target));
987+ }
988+
989+ TRACDBIN(g_trac_sbe, "readSbeImage: SBE Info Version",
990+ reinterpret_cast<uint8_t*>(&o_image_version),
991+ sizeof(o_image_version));
992+
993+ }while(0);
994+
995+
996+ TRACUCOMP( g_trac_sbe,
997+ EXIT_MRK"readSbeImage() - eccStatus=%d, "
998+ "size=0x%X, size_ECC=0x%X",
999+ eccStatus, o_image_size, image_size_ECC);
1000+
1001+
1002+ return err;
1003+}
1004+
1005+
1006+/////////////////////////////////////////////////////////////////////
1007+errlHndl_t writeSbeImage(TARGETING::Target* i_target,
1008+ void* i_imgPtr,
1009+ PNOR::sbeSeepromSide_t i_side,
1010+ size_t i_image_size,
1011+ sbeSeepromVersionInfo_t& io_version)
1012+
1013+{
1014+ TRACFCOMP( g_trac_sbe,
1015+ ENTER_MRK"writeSbeImage(): tgt=0x%X, i_side=%d "
1016+ "i_imgPtr=%p, i_image_size=0x%X",
1017+ TARGETING::get_huid(i_target), i_side, i_imgPtr, i_image_size);
1018+
1019+ errlHndl_t err = NULL;
1020+ int64_t rc = 0;
1021+ EEPROM::eeprom_chip_types_t l_seeprom = sbe_side_sync[i_side];
1022+ size_t image_size_ECC = 0;
1023+
1024+ // For Version Information
1025+ size_t sbeInfoSize = sizeof(sbeSeepromVersionInfo_t);
1026+ size_t sbeInfoSize_ECC = (sbeInfoSize*9)/8;
1027+
1028+ uint8_t * sbeInfo_data_ECC = static_cast<uint8_t*>
1029+ (malloc(sbeInfoSize_ECC));
1030+
1031+
1032+ // Need to ensure that io_imgPtr is at SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
1033+ // since we need to use the VMM_VADDR_SBE_UPDATE space
1034+ assert ( i_imgPtr == reinterpret_cast<void*>(SBE_IMG_VADDR),
1035+ "writeSbeImage() - io_imgPtr is not at SBE_IMG_VADDR");
1036+
1037+ do{
1038+
1039+ // Clear out back half of page block to use as temp space
1040+ // for ECC injected SBE Image.
1041+ rc = mm_remove_pages(RELEASE,
1042+ reinterpret_cast<void*>
1043+ (SBE_ECC_IMG_VADDR),
1044+ SBE_ECC_IMG_MAX_SIZE);
1045+ if( rc )
1046+ {
1047+ TRACFCOMP( g_trac_sbe, ERR_MRK"writeSbeImage() - Error "
1048+ "from mm_remove_pages : rc=%d, HUID=0x%.8X.",
1049+ rc, TARGETING::get_huid(i_target) );
1050+ /*@
1051+ * @errortype
1052+ * @moduleid SBE_WRITE_SBE_IMAGE
1053+ * @reasoncode SBE_REMOVE_PAGES_FOR_EC
1054+ * @userdata1 Requested Address
1055+ * @userdata2 rc from mm_remove_pages
1056+ * @devdesc updateProcessorSbeSeeproms> mm_remove_pages
1057+ * RELEASE failed
1058+ * @custdesc A problem occurred while updating processor
1059+ * boot code.
1060+ */
1061+
1062+ err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
1063+ SBE_WRITE_SBE_IMAGE,
1064+ SBE_REMOVE_PAGES_FOR_EC,
1065+ TO_UINT64(SBE_ECC_IMG_VADDR),
1066+ TO_UINT64(rc),
1067+ true /*Add HB SW Callout*/ );
1068+
1069+ //Target isn't directly related to fail, but could be useful
1070+ //to see how far we got before failing.
1071+ ErrlUserDetailsTarget(i_target).addToLog(err);
1072+ err->collectTrace(SBE_COMP_NAME);
1073+ break;
1074+ }
1075+
1076+ // Inject ECC
1077+ PNOR::ECC::injectECC(reinterpret_cast<uint8_t*>(i_imgPtr),
1078+ ALIGN_8(i_image_size),
1079+ reinterpret_cast<uint8_t*>
1080+ (SBE_ECC_IMG_VADDR));
1081+
1082+ /*****************************************/
1083+ /* Do Actual Write of Image */
1084+ /*****************************************/
1085+ image_size_ECC = ALIGN_8((i_image_size*9)/8);
1086+
1087+ assert(image_size_ECC <= SBE_ECC_IMG_MAX_SIZE,
1088+ "writeSbeImage() SBE Image with ECC too large");
1089+
1090+ err = deviceWrite(i_target,
1091+ reinterpret_cast<void*>
1092+ (SBE_ECC_IMG_VADDR),
1093+ image_size_ECC,
1094+ DEVICE_EEPROM_ADDRESS(
1095+ l_seeprom,
1096+ SBE_IMAGE_SEEPROM_ADDRESS));
1097+
1098+ if(err)
1099+ {
1100+ TRACFCOMP( g_trac_sbe, ERR_MRK"writeSbeImage: - Error "
1101+ "from EEPROM op: rc=0x%.4X, seeprom=%d (side=%d). "
1102+ "HUID=0x%.8X. SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, "
1103+ "size=0x%.8X, eccSize=0x%.8X, EEPROM offset=0x%X",
1104+ err->reasonCode(), l_seeprom, i_side,
1105+ TARGETING::get_huid(i_target),
1106+ SBE_IMG_VADDR, SBE_ECC_IMG_VADDR, i_image_size,
1107+ image_size_ECC, SBE_IMAGE_SEEPROM_ADDRESS);
1108+ break;
1109+ }
1110+
1111+ /********************************************/
1112+ /* Do Actual Write of Version Information */
1113+ /********************************************/
1114+
1115+ // Update the image crc in the version information
1116+ uint32_t image_crc = Util::crc32_calc(i_imgPtr, i_image_size);
1117+
1118+ memcpy( &(io_version.data_crc),
1119+ &image_crc,
1120+ sizeof(image_crc));
1121+
1122+ TRACDBIN( g_trac_sbe, "writeSbeImage: Version no ECC",
1123+ reinterpret_cast<uint8_t*>(&io_version), sizeof(io_version));
1124+
1125+ // Inject ECC
1126+ memset( sbeInfo_data_ECC, 0, sbeInfoSize_ECC);
1127+ PNOR::ECC::injectECC(reinterpret_cast<uint8_t*>(&io_version),
1128+ sbeInfoSize, sbeInfo_data_ECC);
1129+
1130+ TRACDBIN( g_trac_sbe, "writeSbeImage: Version with ECC",
1131+ sbeInfo_data_ECC, sbeInfoSize_ECC);
1132+
1133+ err = deviceWrite( i_target,
1134+ sbeInfo_data_ECC,
1135+ sbeInfoSize_ECC,
1136+ DEVICE_EEPROM_ADDRESS(
1137+ l_seeprom,
1138+ SBE_VERSION_SEEPROM_ADDRESS));
1139+
1140+ if(err)
1141+ {
1142+ TRACFCOMP( g_trac_sbe, ERR_MRK"writeSbeImage: - Error "
1143+ "Writing SBE Version Info: rc=0x%.4X, "
1144+ "HUID=0x%.8X, seeprom=%d, side=%d",
1145+ err->reasonCode(),
1146+ TARGETING::get_huid(i_target), l_seeprom, i_side);
1147+ break;
1148+ }
1149+
1150+ }while(0);
1151+
1152+ // Free allocated memory
1153+ free(sbeInfo_data_ECC);
1154+
1155+ TRACUCOMP( g_trac_sbe,
1156+ EXIT_MRK"writeSetSbeImage()" );
1157+
1158+ return err;
1159+}
1160+
1161+
1162+
1163+
1164+/////////////////////////////////////////////////////////////////////
1165+errlHndl_t getSbeImageSize(TARGETING::Target* i_target,
1166+ void* i_imgPtr,
1167+ PNOR::sbeSeepromSide_t i_side,
1168+ size_t& o_image_size)
1169+{
1170+ TRACUCOMP( g_trac_sbe,
1171+ ENTER_MRK"geSbeImageSize(): tgt=0x%X, i_side=%d "
1172+ "i_imgPtr=%p, o_image_size=0x%X",
1173+ TARGETING::get_huid(i_target), i_side, i_imgPtr, o_image_size);
1174+
1175+ errlHndl_t err = NULL;
1176+ PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN;
1177+ EEPROM::eeprom_chip_types_t l_seeprom = sbe_side_sync[i_side];
1178+ size_t image_size_ECC = 0;
1179+
1180+ // Need to ensure that i_imgPtr is at SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
1181+ // since we need to use the VMM_VADDR_SBE_UPDATE space
1182+
1183+ assert ( i_imgPtr == reinterpret_cast<void*>(SBE_IMG_VADDR),
1184+ "getSbeImageSize() - i_imgPtr is not at SBE_IMG_VADDR");
1185+
1186+ do{
1187+ // Need to read the SbeXipHeader of the image to determine size
1188+ // of the image to read out.
1189+ // Using io_imgPtr space. First read our header+ECC from SBE
1190+ // Seeprom and then use space after that to put header without ECC
1191+
1192+
1193+ size_t hdr_size = ALIGN_8(sizeof(SbeXipHeader));
1194+ size_t hdr_size_ECC = (hdr_size * 9)/8;
1195+
1196+ uint8_t* hdr_ptr = reinterpret_cast<uint8_t*>(i_imgPtr) + hdr_size_ECC;
1197+
1198+ memset( i_imgPtr, 0, hdr_size_ECC + hdr_size );
1199+
1200+ TRACUCOMP( g_trac_sbe, INFO_MRK"getSetSbeImage() Reading "
1201+ "SbeXipHeader for Target 0x%X, Seeprom %d "
1202+ "(side=%d), size_ECC=0x%X (size=0x%X)",
1203+ TARGETING::get_huid(i_target),
1204+ l_seeprom, i_side, hdr_size_ECC, hdr_size );
1205+
1206+ err = DeviceFW::deviceOp( DeviceFW::READ,
1207+ i_target,
1208+ i_imgPtr,
1209+ hdr_size_ECC,
1210+ DEVICE_EEPROM_ADDRESS(
1211+ l_seeprom,
1212+ SBE_IMAGE_SEEPROM_ADDRESS));
1213+
1214+ if(err)
1215+ {
1216+ TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeImageSize: - Error "
1217+ "Reading SbeXipHeader: rc=0x%.4X, seeprom=%d (side=%d). "
1218+ "HUID=0x%.8X. size=0x%.8X, EEPROM offset=0x%X",
1219+ err->reasonCode(), l_seeprom, i_side,
1220+ TARGETING::get_huid(i_target), sizeof(SbeXipHeader),
1221+ SBE_IMAGE_SEEPROM_ADDRESS);
1222+ break;
1223+ }
1224+
1225+
1226+ TRACDBIN( g_trac_sbe,
1227+ "Data with ECC read from Seeprom",
1228+ i_imgPtr,
1229+ hdr_size_ECC );
1230+
1231+ // Remove ECC
1232+ eccStatus = PNOR::ECC::removeECC(
1233+ reinterpret_cast<uint8_t*>(i_imgPtr),
1234+ hdr_ptr,
1235+ hdr_size);
1236+
1237+ // Fail if uncorrectable ECC
1238+ if ( eccStatus == PNOR::ECC::UNCORRECTABLE )
1239+ {
1240+ TRACFCOMP( g_trac_sbe,ERR_MRK"getSbeImageSize: ECC Error "
1241+ "On SBE Image Read eccStatus=%d sI=%d, sI_ECC="
1242+ "%d, HUID=0x%.8X, Seeprom %d (side=%d)",
1243+ eccStatus, o_image_size, image_size_ECC,
1244+ TARGETING::get_huid(i_target),
1245+ l_seeprom, i_side );
1246+ /*@
1247+ * @errortype
1248+ * @moduleid SBE_GET_SBE_IMAGE_SIZE
1249+ * @reasoncode SBE_ECC_FAIL
1250+ * @userdata1[0:15] ECC Status
1251+ * @userdata1[16:31] SEEPROM Side
1252+ * @userdata1[32:63] Target HUID
1253+ * @userdata2[0:31] Size - No Ecc
1254+ * @userdata2[32:63] Size - ECC
1255+ * @devdesc ECC Fail Reading SBE Image
1256+ */
1257+ err = new ErrlEntry(ERRL_SEV_PREDICTIVE,
1258+ SBE_GET_SBE_IMAGE_SIZE,
1259+ SBE_ECC_FAIL,
1260+ TWO_UINT32_TO_UINT64(
1261+ ( (eccStatus << 16 ) |
1262+ l_seeprom ),
1263+ TARGETING::get_huid(i_target)),
1264+ TWO_UINT32_TO_UINT64(o_image_size,
1265+ image_size_ECC));
1266+ err->collectTrace(SBE_COMP_NAME);
1267+ err->addPartCallout(
1268+ i_target,
1269+ HWAS::SBE_SEEPROM_PART_TYPE,
1270+ HWAS::SRCI_PRIORITY_HIGH,
1271+ HWAS::NO_DECONFIG,
1272+ HWAS::GARD_NULL );
1273+
1274+ ErrlUserDetailsTarget(i_target).addToLog(err);
1275+
1276+ break;
1277+ }
1278+
1279+ TRACDBIN( g_trac_sbe,
1280+ "Data without ECC read from Seeprom",
1281+ hdr_ptr,
1282+ hdr_size );
1283+
1284+ o_image_size = (((SbeXipHeader*)hdr_ptr)->iv_imageSize);
1285+
1286+ }while(0);
1287+
1288+ TRACFCOMP( g_trac_sbe,
1289+ EXIT_MRK"getSbeImageSize(): o_image_size=0x%X", o_image_size );
1290+
1291+ return err;
1292+}
1293+
1294+
1295+
1296+/////////////////////////////////////////////////////////////////////
1297+errlHndl_t resolveImageHBBaddr(TARGETING::Target* i_target,
1298+ void* io_imgPtr,
1299+ PNOR::sbeSeepromSide_t i_side,
1300+ PNOR::SideId i_pnorSideId,
1301+ bool& o_imageWasUpdated )
1302+{
1303+ errlHndl_t err = NULL;
1304+ uint64_t data = 0;
1305+ int rc = 0;
1306+ bool rc_fail_on_get = false; // 1=get failed, 0=set failed
1307+
1308+ o_imageWasUpdated = false;
1309+
1310+ TRACUCOMP( g_trac_sbe,
1311+ ENTER_MRK"resolveImageHBBaddr() - tgt=0x%X, i_side=%d, "
1312+ "i_pnorSideId=%d",
1313+ TARGETING::get_huid(i_target), i_side, i_pnorSideId);
1314+
1315+ do{
1316+
1317+ // Get info from PNOR
1318+ PNOR::SideInfo_t pnor_side_info;
1319+ err = PNOR::getSideInfo (i_pnorSideId, pnor_side_info);
1320+ if ( err )
1321+ {
1322+ TRACFCOMP( g_trac_sbe, ERR_MRK
1323+ "resolveImageHBBaddr() - Error returned "
1324+ "from PNOR::getSideInfo() rc=0x%.4X, Target UID=0x%X "
1325+ "i_pnorSideId",
1326+ err->reasonCode(),
1327+ TARGETING::get_huid(i_target), i_pnorSideId);
1328+ break;
1329+ }
1330+
1331+
1332+ // Only Need to Check/Update if PNOR has Other Side
1333+ // and Seeprom isn't pointing at PNOR's GOLDEN side
1334+ if ( ( pnor_side_info.hasOtherSide == true ) &&
1335+ ( pnor_side_info.isGolden == false ) )
1336+ {
1337+
1338+ // Read the MMIO offset associated with the HBB address
1339+ // from the image
1340+ rc = sbe_xip_get_scalar( io_imgPtr,
1341+ "standalone_mbox2_value",
1342+ &data);
1343+ if ( rc != 0 )
1344+ {
1345+ rc_fail_on_get = true; // get failed
1346+
1347+ TRACFCOMP( g_trac_sbe, ERR_MRK"resolveImageHBBaddr() - "
1348+ "sbe_xip_get_scalar() failed rc = 0x%X (%d)",
1349+ rc, rc_fail_on_get);
1350+ break;
1351+ }
1352+
1353+ if ( pnor_side_info.hbbMmioOffset == data )
1354+ {
1355+ TRACUCOMP( g_trac_sbe, "resolveImageHBBaddr: Image has MMIO "
1356+ "offset = 0x%X that matches PNOR MMIO="
1357+ "0x%X for HBB Address=0x%X",
1358+ data, pnor_side_info.hbbMmioOffset,
1359+ pnor_side_info.hbbAddress);
1360+ }
1361+ else
1362+ {
1363+ TRACFCOMP( g_trac_sbe, "resolveImageHBBaddr: Image has MMIO "
1364+ "offset = 0x%X does NOT match PNOR MMIO="
1365+ "0x%X for HBB Address=0x%X. Updating Image",
1366+ data, pnor_side_info.hbbMmioOffset,
1367+ pnor_side_info.hbbAddress);
1368+
1369+ TRACDBIN (g_trac_sbe, "resolveImageHBBaddr: data", &data, 8 );
1370+
1371+ TRACDBIN (g_trac_sbe, "resolveImageHBBaddr: hbbMmioOffset",
1372+ &pnor_side_info.hbbMmioOffset, 8 );
1373+ TRACDBIN (g_trac_sbe, "resolveImageHBBaddr: hbbAddress",
1374+ &pnor_side_info.hbbAddress, 8);
1375+
1376+ rc = sbe_xip_set_scalar( io_imgPtr, "standalone_mbox2_value",
1377+ pnor_side_info.hbbMmioOffset);
1378+
1379+ if ( rc != 0 )
1380+ {
1381+ rc_fail_on_get = false; // set failed
1382+
1383+ TRACFCOMP( g_trac_sbe, ERR_MRK"resolveImageHBBaddr() - "
1384+ "sbe_xip_set_scalar() failed rc = 0x%X (%d)",
1385+ rc, rc_fail_on_get);
1386+ break;
1387+ }
1388+ o_imageWasUpdated = true;
1389+ }
1390+
1391+ }
1392+ else
1393+ {
1394+ // pnor_side_info.hasOtherSide is false
1395+ TRACUCOMP( g_trac_sbe, "resolveImageHBBaddr: PNOR only has "
1396+ "1 side - No Update Required");
1397+ }
1398+
1399+ }while(0);
1400+
1401+
1402+ if ( ( err == NULL ) && ( rc != 0) )
1403+ {
1404+ // We failed on get/set cmd above (already traced)
1405+
1406+ /*@
1407+ * @errortype
1408+ * @moduleid SBE_RESOLVE_HBB_ADDR
1409+ * @reasoncode SBE_IMAGE_GET_SET_SCALAR_FAIL
1410+ * @userdata1 Return Code of failed operation
1411+ * @userdata2 True/False if Get (true) or Set (false) Op failed
1412+ * @devdesc sbe_xip_get/set_scalar() failed when accessing the
1413+ HBB Address MMIO offset in 'standalone_mbox2_value'
1414+ * @custdesc A problem occurred while updating processor
1415+ * boot code.
1416+ */
1417+ err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
1418+ SBE_RESOLVE_HBB_ADDR,
1419+ SBE_IMAGE_GET_SET_SCALAR_FAIL,
1420+ TO_UINT64(rc),
1421+ TO_UINT64(rc_fail_on_get),
1422+ true /*Add HB SW Callout*/ );
1423+
1424+ err->collectTrace(SBE_COMP_NAME);
1425+ }
1426+
1427+
1428+ TRACUCOMP( g_trac_sbe,
1429+ EXIT_MRK"resolveImageHBBaddr() - o_imageWasUpdated = %d",
1430+ o_imageWasUpdated);
1431+
1432+ return err;
1433+}
1434+
1435+#ifdef CONFIG_BMC_IPMI
1436+/////////////////////////////////////////////////////////////////////
1437+void sbePreShutdownIpmiCalls( void )
1438+{
1439+ errlHndl_t err = NULL;
1440+
1441+ TRACFCOMP( g_trac_sbe, ENTER_MRK"sbePreShutdownIpmiCalls");
1442+
1443+ do{
1444+ uint16_t count = 0;
1445+ SENSOR::RebootCountSensor l_sensor;
1446+
1447+ // Read reboot count sensor
1448+ err = l_sensor.getRebootCount(count);
1449+ if ( err )
1450+ {
1451+ TRACFCOMP( g_trac_sbe,
1452+ ERR_MRK"sbePreShutdownIpmiCalls: "
1453+ "FAIL Reading Reboot Sensor Count. "
1454+ "Committing Error Log rc=0x%.4X eid=0x%.8X "
1455+ "plid=0x%.8X, but continuing shutdown",
1456+ err->reasonCode(),
1457+ err->eid(),
1458+ err->plid());
1459+ err->collectTrace(SBE_COMP_NAME);
1460+ errlCommit( err, SBE_COMP_ID );
1461+
1462+ // No Break - Still Do Watchdog Timer Call
1463+ }
1464+ else
1465+ {
1466+ // Increment Reboot Count Sensor
1467+ count++;
1468+ TRACFCOMP( g_trac_sbe,
1469+ INFO_MRK"sbePreShutdownIpmiCalls: "
1470+ "Writing Reboot Sensor Count=%d", count);
1471+
1472+ err = l_sensor.setRebootCount( count );
1473+ if ( err )
1474+ {
1475+ TRACFCOMP( g_trac_sbe,
1476+ ERR_MRK"sbePreShutdownIpmiCalls: "
1477+ "FAIL Writing Reboot Sensor Count to %d. "
1478+ "Committing Error Log rc=0x%.4X eid=0x%.8X "
1479+ "plid=0x%.8X, but continuing shutdown",
1480+ count,
1481+ err->reasonCode(),
1482+ err->eid(),
1483+ err->plid());
1484+ err->collectTrace(SBE_COMP_NAME);
1485+ errlCommit( err, SBE_COMP_ID );
1486+
1487+ // No Break - Still Do Watchdog Timer Call
1488+ }
1489+ }
1490+
1491+ // @todo RTC 124679 - Remove Once BMC Monitors Shutdown Attention
1492+ // Set Watchdog Timer To 10 seconds
1493+ const uint16_t SET_WD_TIMER_10_SECS = 10;
1494+ TRACFCOMP( g_trac_sbe,"sbePreShutdownIpmiCalls: "
1495+ "Set Watch Dog Timer To %d Seconds",
1496+ SET_WD_TIMER_10_SECS);
1497+
1498+ err = IPMIWATCHDOG::setWatchDogTimer(SET_WD_TIMER_10_SECS);
1499+ if(err)
1500+ {
1501+ TRACFCOMP( g_trac_sbe,
1502+ ERR_MRK"sbePreShutdownIpmiCalls: "
1503+ "FAIL Setting Watch Dog Timer to %d seconds. "
1504+ "Committing Error Log rc=0x%.4X eid=0x%.8X "
1505+ "plid=0x%.8X, but continuing shutdown",
1506+ SET_WD_TIMER_10_SECS,
1507+ err->reasonCode(),
1508+ err->eid(),
1509+ err->plid());
1510+
1511+ err->collectTrace(SBE_COMP_NAME);
1512+ errlCommit(err, SBE_COMP_ID );
1513+ }
1514+
1515+ }while(0);
1516+
1517+ TRACFCOMP( g_trac_sbe, EXIT_MRK"sbePreShutdownIpmiCalls");
1518+
1519+ return;
1520+}
1521+#endif // CONFIG_BMC_IPMI
1522+
1523+
1524+} //end SBE Namespace
1525diff --git a/src/usr/sbe/sbe_resolve_sides.H b/src/usr/sbe/sbe_resolve_sides.H
1526new file mode 100644
1527index 0000000..42f727a
1528--- /dev/null
1529+++ b/src/usr/sbe/sbe_resolve_sides.H
1530@@ -0,0 +1,259 @@
1531+/* IBM_PROLOG_BEGIN_TAG */
1532+/* This is an automatically generated prolog. */
1533+/* */
1534+/* $Source: src/usr/sbe/sbe_resolve_sides.H $ */
1535+/* */
1536+/* OpenPOWER HostBoot Project */
1537+/* */
1538+/* Contributors Listed Below - COPYRIGHT 2015 */
1539+/* [+] International Business Machines Corp. */
1540+/* */
1541+/* */
1542+/* Licensed under the Apache License, Version 2.0 (the "License"); */
1543+/* you may not use this file except in compliance with the License. */
1544+/* You may obtain a copy of the License at */
1545+/* */
1546+/* http://www.apache.org/licenses/LICENSE-2.0 */
1547+/* */
1548+/* Unless required by applicable law or agreed to in writing, software */
1549+/* distributed under the License is distributed on an "AS IS" BASIS, */
1550+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
1551+/* implied. See the License for the specific language governing */
1552+/* permissions and limitations under the License. */
1553+/* */
1554+/* IBM_PROLOG_END_TAG */
1555+#ifndef __SBE_SBE_RESOLVE_SIDES_H
1556+#define __SBE_SBE_RESOLVE_SIDES_H
1557+
1558+
1559+#include <stdint.h>
1560+#include <builtins.h>
1561+#include <errl/errlentry.H>
1562+#include <pnor/pnorif.H>
1563+#include <util/align.H>
1564+#include <vmmconst.h>
1565+#include <targeting/common/targetservice.H>
1566+#include <i2c/eepromif.H>
1567+#include "sbe_update.H"
1568+
1569+namespace SBE
1570+{
1571+ /******************************************/
1572+ /* Constants */
1573+ /******************************************/
1574+
1575+ // This seeprom is a candidate to be READ_ONLY (ie, not updated)
1576+ const PNOR::sbeSeepromSide_t READ_ONLY_SEEPROM = PNOR::SBE_SEEPROM1;
1577+
1578+ // Used to keep SBE Seeproms in sync with EEPROM::eeprom_chip_types_t
1579+ const EEPROM::eeprom_chip_types_t sbe_side_sync[2] =
1580+ { EEPROM::SBE_PRIMARY,
1581+ EEPROM::SBE_BACKUP };
1582+
1583+ /******************************************/
1584+ /* Enums */
1585+ /******************************************/
1586+
1587+ // Actions can be combined
1588+ enum
1589+ {
1590+ NO_ACTIONS = 0x00000000,
1591+ REIPL = 0x00000001,
1592+
1593+ // Use PNOR::ALTERNATE SideId for HBB Address info
1594+ USE_PNOR_ALT_SIDE = 0x00000002,
1595+
1596+ // NOTE: These next 2 values are mutually exclusive
1597+ CHECK_WORKING_HBB = 0x00000010,
1598+ COPY_READ_ONLY_TO_WORKING = 0x00000020,
1599+ };
1600+
1601+ /******************************************/
1602+ /* Structs */
1603+ /******************************************/
1604+ struct sbeResolveState_t
1605+ {
1606+
1607+ // Target Information
1608+ TARGETING::Target* tgt;
1609+
1610+ PNOR::sbeSeepromSide_t cur_side; // aka 'booted' side
1611+ PNOR::sbeSeepromSide_t alt_side; // non-booted/non-cur side
1612+ PNOR::sbeSeepromSide_t update_side; // side to be updated
1613+
1614+ // Info from PNOR
1615+ PNOR::SideId pnor_sideId;
1616+ char pnor_side; /**< name of the side either A or B */
1617+ bool pnor_isGolden; /**< True if side is golden */
1618+ bool pnor_hasOtherSide; /**< True if a valid alternate side exists*/
1619+
1620+ uint32_t actions;
1621+
1622+ // Constructor to default certain values
1623+ sbeResolveState_t() :
1624+ tgt(NULL), cur_side(PNOR::SBE_SEEPROM_INVALID),
1625+ alt_side(PNOR::SBE_SEEPROM_INVALID),
1626+ update_side(PNOR::SBE_SEEPROM_INVALID),
1627+ pnor_sideId(PNOR::WORKING),
1628+ pnor_side(NULL),
1629+ pnor_isGolden(false), pnor_hasOtherSide(false),
1630+ actions(NO_ACTIONS)
1631+ {}
1632+
1633+ };
1634+
1635+
1636+ /******************************************/
1637+ /* Functions -- High Level Functions */
1638+ /******************************************/
1639+
1640+ /**
1641+ * @brief Collects SBE Side Information for a specifc target
1642+ *
1643+ * @param[io/out] io_sideState Struct containing SBE State of the target
1644+ *
1645+ * @return errlHndl_t Error log handle on failure.
1646+ */
1647+ errlHndl_t getSideState(sbeResolveState_t& io_sideState);
1648+
1649+ /**
1650+ * @brief Analyze and Determine Update Actions for a specific target
1651+ *
1652+ * @param[io/out] io_sideState Struct containing SBE State of the target
1653+ *
1654+ * @return errlHndl_t Error log handle on failure.
1655+ */
1656+ errlHndl_t getSideActions(sbeResolveState_t& io_sideState);
1657+
1658+ /**
1659+ * @brief Performs the Update Actions for a specific target
1660+ *
1661+ * @param[io/out] io_sideState Struct containing SBE State of the target
1662+ *
1663+ * @return errlHndl_t Error log handle on failure.
1664+ */
1665+ errlHndl_t performSideActions(sbeResolveState_t& io_sideState);
1666+
1667+
1668+
1669+ /******************************************/
1670+ /* Functions -- System Access */
1671+ /******************************************/
1672+
1673+
1674+ /**
1675+ * @brief Read SBE Image from SBE Seeprom
1676+ *
1677+ * @param[in] i_target Target processor
1678+ *
1679+ * @param[out] o_imgPtr Pointer to SBE image in memory
1680+ * Memory for this pointer is expected to be
1681+ * pre-alloacted
1682+ * NOTE: ECC is handled internally in this
1683+ * function. io_imgPtr points to non-ECC image
1684+ *
1685+ * @param[in] i_side Seeprom Side to access
1686+ *
1687+ * @param[in] o_image_size The size of the image (non-ECC)
1688+ *
1689+ * @param[in] o_version SBE Version struct from seeprom (non-ECC)
1690+ *
1691+ * @return errlHndl_t Error log handle on failure.
1692+ */
1693+ errlHndl_t readSbeImage(TARGETING::Target* i_target,
1694+ void* o_imgPtr,
1695+ PNOR::sbeSeepromSide_t i_side,
1696+ size_t& o_image_size,
1697+ sbeSeepromVersionInfo_t& o_version);
1698+
1699+ /**
1700+ * @brief Write SBE Image from SBE Seeprom
1701+ *
1702+ * @param[in] i_target Target processor
1703+ *
1704+ * @param[in] i_imgPtr Pointer to SBE image in memory
1705+ * Memory for this pointer is expected to be
1706+ * pre-alloacted
1707+ * NOTE: ECC is handled internally in this function
1708+ * i_imgPtr points to non-ECC image
1709+ *
1710+ * @param[in] i_side Seeprom Side to access
1711+ *
1712+ * @param[in] i_image_size Size of image to write (non-ECC)
1713+ *
1714+ * @param[in] io_version SBE Version struct to write (non-ECC)
1715+ * NOTE: data_crc updated in this function
1716+ *
1717+ * @return errlHndl_t Error log handle on failure.
1718+ */
1719+ errlHndl_t writeSbeImage(TARGETING::Target* i_target,
1720+ void* i_imgPtr,
1721+ PNOR::sbeSeepromSide_t i_side,
1722+ size_t i_image_size,
1723+ sbeSeepromVersionInfo_t& io_version);
1724+
1725+
1726+ /**
1727+ * @brief Read SBE Image Header from SBE Seeprom and gets the
1728+ * Image size from the heaser
1729+ *
1730+ * @param[in] i_target Target processor
1731+ *
1732+ * @param[out] i_imgPtr Pointer to pre-allocated memory to be used
1733+ * for different operations
1734+ *
1735+ * @param[in] i_side Seeprom Side to access
1736+ *
1737+ * @param[in] o_image_size The size of the image (non-ECC)
1738+ *
1739+ * @return errlHndl_t Error log handle on failure.
1740+ */
1741+ errlHndl_t getSbeImageSize(TARGETING::Target* i_target,
1742+ void* i_imgPtr,
1743+ PNOR::sbeSeepromSide_t i_side,
1744+ size_t& o_image_size);
1745+
1746+
1747+
1748+
1749+ /******************************************/
1750+ /* Functions -- Helper Functions */
1751+ /******************************************/
1752+
1753+ /**
1754+ * @brief Check and Update (if necessary) the HBB Address MMIO offset
1755+ * in a customized SBE Image for the current Processor
1756+ *
1757+ * @param[in] i_target Target processor to customize
1758+ *
1759+ * @param[in/out] io_imgPtr Pointer to SBE image in memory
1760+ * Memory for this pointer is expected to be
1761+ * pre-alloacted
1762+ *
1763+ * @param[in] i_side Seeprom Side to access
1764+ *
1765+ * @param[in] i_pnorSideId PNOR side to get information for
1766+ *
1767+ * @param[out] o_imageWasUpdated Set to true if Image was updated;
1768+ * otherwise false
1769+ *
1770+ * @return errlHndl_t Error log handle on failure.
1771+ */
1772+ errlHndl_t resolveImageHBBaddr(TARGETING::Target* i_target,
1773+ void* io_imgPtr,
1774+ PNOR::sbeSeepromSide_t i_side,
1775+ PNOR::SideId i_pnorSideId,
1776+ bool& o_imageWasUpdated);
1777+
1778+#ifdef CONFIG_BMC_IPMI
1779+ /**
1780+ * @brief Performs any necessary IPMI calls before shutting down the system
1781+ *
1782+ * @return void Any generated Error Logs will be commited before the
1783+ * function returns
1784+ */
1785+ void sbePreShutdownIpmiCalls( void );
1786+#endif
1787+
1788+} //end namespace SBE
1789+#endif
1790diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C
1791index 97a0484..562798b 100644
1792--- a/src/usr/sbe/sbe_update.C
1793+++ b/src/usr/sbe/sbe_update.C
1794@@ -50,6 +50,7 @@
1795 #include <sbe/sbeif.H>
1796 #include <sbe/sbereasoncodes.H>
1797 #include "sbe_update.H"
1798+#include "sbe_resolve_sides.H"
1799
1800 // fapi support
1801 #include <fapi.H>
1802@@ -112,6 +113,25 @@ namespace SBE
1803
1804 do{
1805
1806+#ifdef CONFIG_NO_SBE_UPDATES
1807+ TRACFCOMP( g_trac_sbe, INFO_MRK"updateProcessorSbeSeeproms() - "
1808+ "SBE updates not configured");
1809+ break;
1810+#endif
1811+
1812+#ifdef CONFIG_SBE_UPDATE_SEQUENTIAL
1813+ // Check if FSP-services are enabled and if we're running in simics
1814+ if ( !INITSERVICE::spBaseServicesEnabled() &&
1815+ !Util::isSimicsRunning() )
1816+ {
1817+ assert (false, "resolveProcessorSbeSeeproms() - "
1818+ "SBE_UPDATE_SEQUENTIAL mode, but FSP-services are not "
1819+ "enabled - Invalid Configuration");
1820+ }
1821+ // else - continue on
1822+#endif
1823+
1824+
1825 // Get Target Service, and the system target.
1826 TargetService& tS = targetService();
1827 TARGETING::Target* sys = NULL;
1828@@ -204,11 +224,6 @@ namespace SBE
1829 err = NULL;
1830 }
1831
1832-#ifdef CONFIG_NO_SBE_UPDATES
1833- TRACFCOMP( g_trac_sbe, INFO_MRK"updateProcessorSbeSeeproms() - "
1834- "SBE updates not configured");
1835- break;
1836-#endif
1837
1838 for(uint32_t i=0; i<procList.size(); i++)
1839 {
1840@@ -277,7 +292,6 @@ namespace SBE
1841 /**********************************************/
1842 if ((err == NULL) && (sbeState.update_actions & DO_UPDATE))
1843 {
1844-
1845 err = performUpdateActions(sbeState);
1846 if (err)
1847 {
1848@@ -328,7 +342,6 @@ namespace SBE
1849
1850 } //end of Target for loop collecting each target's SBE State
1851
1852-
1853 /**************************************************************/
1854 /* Perform System Operation */
1855 /**************************************************************/
1856@@ -355,7 +368,7 @@ namespace SBE
1857 }
1858
1859 #ifdef CONFIG_BMC_IPMI
1860- // @todo RTC 120734 reset system's reboot count via IPMI sensor
1861+ sbePreShutdownIpmiCalls();
1862 #endif
1863
1864 TRACFCOMP( g_trac_sbe,
1865@@ -685,14 +698,15 @@ namespace SBE
1866
1867 do{
1868
1869- // @todo RTC 120734 - before customizing, ensure correct HBB address
1870- // is set in the necessary attribute
1871-
1872 // cast OUR type of target to a FAPI type of target.
1873 const fapi::Target
1874 l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP,
1875 (const_cast<TARGETING::Target*>(i_target)));
1876
1877+ // NOTE: The p8_xip_customize_procedure uses SBE_IMAGE_OFFSET
1878+ // attribute for HBB address value. Purpsely leaving this
1879+ // attribute as-is for now and will do the check for HBB address
1880+ // later.
1881
1882 // The p8_xip_customize() procedure tries to include as much core
1883 // information as possible, but is limited by SBE Image size
1884@@ -871,7 +885,6 @@ namespace SBE
1885 HWAS::SRCI_PRIORITY_HIGH );
1886 }
1887
1888-
1889 }while(0);
1890
1891 TRACUCOMP( g_trac_sbe,
1892@@ -1715,6 +1728,26 @@ namespace SBE
1893 // The Customized Image For This Target Still Resides In
1894 // The SBE Update VMM Space: SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE
1895
1896+#ifdef CONFIG_SBE_UPDATE_INDEPENDENT
1897+ // Ensure HBB address value in the customized image is correct
1898+ // for this side
1899+ bool imageWasUpdated=false;
1900+ err = resolveImageHBBaddr ( io_sbeState.target,
1901+ reinterpret_cast<void*>(SBE_IMG_VADDR),
1902+ ((io_sbeState.seeprom_side_to_update ==
1903+ EEPROM::SBE_PRIMARY ) ?
1904+ PNOR::SBE_SEEPROM0 :
1905+ PNOR::SBE_SEEPROM1 ),
1906+ PNOR::WORKING,
1907+ imageWasUpdated );
1908+
1909+ if (imageWasUpdated == true )
1910+ {
1911+ TRACUCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - "
1912+ "HBB Address's MMIO Offset Updated in Image");
1913+ }
1914+
1915+#endif
1916
1917 // Inject ECC
1918 // clear out back half of page block to use as temp space
1919@@ -1941,7 +1974,6 @@ namespace SBE
1920 io_sbeState.seeprom_0_ver.data_crc, isSimics_check);
1921 }
1922
1923-
1924 /**************************************************************/
1925 /* Compare SEEPROM 1 with PNOR and Customized Image CRC -- */
1926 /* -- dirty or clean? */
1927@@ -2153,22 +2185,55 @@ namespace SBE
1928 #ifdef CONFIG_SBE_UPDATE_INDEPENDENT
1929
1930 // The 2 SBE SEEPROMs are independent of each other
1931- // Determine if PNOR is 1- or 2-sided and if there is a
1932- // GOLDEN boot involved
1933+ // Determine if PNOR is 1- or 2-sided and if the current
1934+ // Seeprom is pointing at PNOR's GOLDEN side
1935+
1936+ PNOR::SideId tmp_side = PNOR::WORKING;
1937+ PNOR::SideInfo_t pnor_side_info;
1938+ err = PNOR::getSideInfo (tmp_side, pnor_side_info);
1939+ if ( err )
1940+ {
1941+ TRACFCOMP( g_trac_sbe, ERR_MRK
1942+ "SBE Update() - Error returned from "
1943+ "PNOR::getSideInfo() rc=0x%.4X, Target UID=0x%X",
1944+ err->reasonCode(),
1945+ TARGETING::get_huid(io_sbeState.target));
1946+ break;
1947+ }
1948
1949-#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
1950+ TRACUCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: PNOR Info: "
1951+ "side-%c, sideId=0x%X, isGolden=%d, hasOtherSide=%d",
1952+ TARGETING::get_huid(io_sbeState.target),
1953+ pnor_side_info.side, pnor_side_info.id,
1954+ pnor_side_info.isGolden, pnor_side_info.hasOtherSide);
1955
1956- // @todo RTC 120734 - ask PNOR if we are in "GOLDEN" mode,
1957- // which would mean that we are booting off the the GOLDEN
1958- // SBE SEEPROM which corresponds to the GOLDEN side of PNOR
1959-/*
1960- if (true)
1961+ if ( pnor_side_info.isGolden == true )
1962 {
1963 // If true, nothing to do (covered in istep 6 function)
1964 l_actions = CLEAR_ACTIONS;
1965
1966 TRACFCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
1967- "Booting GOLDEN SBE SEEPROM in PNOR 2-sided Mode. "
1968+ "Booting READ_ONLY SEEPROM pointing at PNOR's "
1969+ "GOLDEN side. No updates for cur side=%d. Continue "
1970+ "IPL. (sit=0x%.2X, act=0x%.8X flags=0x%.2X)",
1971+ TARGETING::get_huid(io_sbeState.target),
1972+ io_sbeState.cur_seeprom_side,
1973+ i_system_situation, l_actions,
1974+ io_sbeState.mvpdSbKeyword.flags);
1975+ break;
1976+ }
1977+
1978+ else if ( ( pnor_side_info.hasOtherSide == false ) &&
1979+ ( io_sbeState.cur_seeprom_side == READ_ONLY_SEEPROM ) )
1980+ {
1981+ // Even though current seeprom is not pointing at PNOR's
1982+ // GOLDEN side, treat like READ_ONLY if booting from READ_ONLY
1983+ // seeprom and and PNOR does not have another side - No Update
1984+ // (ie, Palmetto configuration)
1985+ l_actions = CLEAR_ACTIONS;
1986+
1987+ TRACFCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
1988+ "Treating cur like READ_ONLY SBE SEEPROM. "
1989 "No updates for cur side=%d. Continue IPL. "
1990 "(sit=0x%.2X, act=0x%.8X flags=0x%.2X)",
1991 TARGETING::get_huid(io_sbeState.target),
1992@@ -2179,22 +2244,14 @@ namespace SBE
1993 }
1994 else // proceed to update this side
1995 {
1996+ // proceed to update this side
1997 TRACUCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
1998- "NOT Booting GOLDEN SBE SEEPROM in PNOR 2-sided "
1999- "mode. Checking for update on cur side=%d ",
2000+ "NOT Booting READ_ONLY SEEPROM. Check for update "
2001+ "on cur side=%d ",
2002 TARGETING::get_huid(io_sbeState.target),
2003 io_sbeState.cur_seeprom_side)
2004 }
2005-*/
2006-#else
2007
2008- // @todo RTC 120734 - check this assumption
2009- // Assume that we're only checking/updating the current side
2010- TRACUCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: "
2011- "PNOR 1-sided so only check for update on cur side=%d",
2012- TARGETING::get_huid(io_sbeState.target),
2013- io_sbeState.cur_seeprom_side);
2014-#endif
2015
2016 // Check for clean vs. dirty only on cur side
2017 if ( i_system_situation & SITUATION_CUR_IS_DIRTY )
2018@@ -2203,6 +2260,7 @@ namespace SBE
2019 l_actions |= IPL_RESTART;
2020 l_actions |= DO_UPDATE;
2021 l_actions |= UPDATE_SBE;
2022+ l_actions |= UPDATE_MVPD; // even though flags byte not updated
2023
2024 // Set Update side to cur
2025 io_sbeState.seeprom_side_to_update =
2026--
20271.7.4.1
2028