blob: e51afbfdec0ce02981e8051dea91820e54ccd255 [file] [log] [blame]
Matt Ploetzc7e794c2015-06-03 09:41:10 -05001From 9597cf58b44fd0c16da9d3592e8fd586a4dbf04d Mon Sep 17 00:00:00 2001
2From: Bill Schwartz <whs@us.ibm.com>
3Date: Fri, 27 Feb 2015 15:41:10 -0600
4Subject: [PATCH] Add support for backplane VPD
5
6Replace the temporary use of mem buf to access planar vpd with new
7planar vpd interfaces.
8
9Change-Id: I24cda4d713806330a9f61d588006d63966f92550
10RTC: 118373
11Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/16326
12Tested-by: Jenkins Server
13Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
14---
15 src/include/usr/devicefw/userif.H | 23 +
16 src/include/usr/vpd/cvpdenums.H | 1 -
17 src/include/usr/vpd/pvpdenums.H | 96 ++++
18 src/include/usr/vpd/vpd_if.H | 8 +
19 src/include/usr/vpd/vpdreasoncodes.H | 4 +
20 src/usr/devtree/bld_devtree.C | 85 ++--
21 src/usr/hwas/hwasPlat.C | 6 +-
22 src/usr/hwas/hwasPlatCallout.C | 6 +-
23 src/usr/i2c/eepromdd.C | 5 +
24 src/usr/ipmi/ipmifruinv.C | 502 +++++++++++++--------
25 src/usr/ipmi/ipmifruinvprvt.H | 112 ++++-
26 src/usr/targeting/common/xmltohb/target_types.xml | 2 +
27 .../targeting/common/xmltohb/target_types_hb.xml | 5 +
28 src/usr/vpd/HBconfig | 27 ++
29 src/usr/vpd/cvpd.C | 36 +-
30 src/usr/vpd/cvpd.H | 22 +-
31 src/usr/vpd/ipvpd.C | 50 +-
32 src/usr/vpd/ipvpd.H | 22 +-
33 src/usr/vpd/pvpd.C | 369 +++++++++++++++
34 src/usr/vpd/pvpd.H | 149 ++++++
35 src/usr/vpd/vpd.C | 17 +-
36 src/usr/vpd/vpd.H | 1 +
37 src/usr/vpd/vpd.mk | 5 +-
38 23 files changed, 1307 insertions(+), 246 deletions(-)
39 create mode 100644 src/include/usr/vpd/pvpdenums.H
40 create mode 100644 src/usr/vpd/pvpd.C
41 create mode 100644 src/usr/vpd/pvpd.H
42
43diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H
44index 6d041f2..eac5366 100644
45--- a/src/include/usr/devicefw/userif.H
46+++ b/src/include/usr/devicefw/userif.H
47@@ -61,6 +61,7 @@ namespace DeviceFW
48 GPIO,
49 LPC,
50 IPMIBT, // As opposed to other phy's
51+ PVPD,
52
53 LAST_ACCESS_TYPE,
54 };
55@@ -166,6 +167,28 @@ namespace DeviceFW
56 static_cast<uint64_t>(( i_location ))
57
58 /**
59+ * Construct the device addressing parameters for the PVPD device ops.
60+ * @param[in] i_record - The enumeration of the PVPD record to access.
61+ * @param[in] i_keyword - The enumeration of the PVPD keyword, located
62+ * within the i_record Record to access.
63+ */
64+ #define DEVICE_PVPD_ADDRESS( i_record, i_keyword )\
65+ DEVICE_PVPD_FORCE_ADDRESS( i_record, i_keyword, VPD::AUTOSELECT )
66+
67+ /**
68+ * Construct the device addressing parameters for the PVPD device ops.
69+ * @param[in] i_record - The enumeration of the PVPD record to access.
70+ * @param[in] i_keyword - The enumeration of the PVPD keyword, located
71+ * within the i_record Record to access.
72+ * @param[in] i_location - The location of the data (PNOR/SEEPROM)
73+ see vpd_if.H
74+ */
75+ #define DEVICE_PVPD_FORCE_ADDRESS( i_record, i_keyword, i_location )\
76+ DeviceFW::PVPD, static_cast<uint64_t>(( i_record )),\
77+ static_cast<uint64_t>(( i_keyword )),\
78+ static_cast<uint64_t>(( i_location ))
79+
80+ /**
81 * Construct the device addressing parameters for the SCAN device ops.
82 * @param[in] i_ring - The ring address to scan
83 * @param[in] i_ringlen - The length of the ring to scan in bits
84diff --git a/src/include/usr/vpd/cvpdenums.H b/src/include/usr/vpd/cvpdenums.H
85index 4b5adb2..79b8109 100644
86--- a/src/include/usr/vpd/cvpdenums.H
87+++ b/src/include/usr/vpd/cvpdenums.H
88@@ -45,7 +45,6 @@ namespace CVPD
89 OPFR = 0x05,
90 VNDR = 0x06,
91 SPDX = 0x07,
92- OSYS = 0x08,
93 // Last Record
94 CVPD_LAST_RECORD,
95 CVPD_TEST_RECORD, // Test purposes ONLY!
96diff --git a/src/include/usr/vpd/pvpdenums.H b/src/include/usr/vpd/pvpdenums.H
97new file mode 100644
98index 0000000..acf3bbd
99--- /dev/null
100+++ b/src/include/usr/vpd/pvpdenums.H
101@@ -0,0 +1,96 @@
102+/* IBM_PROLOG_BEGIN_TAG */
103+/* This is an automatically generated prolog. */
104+/* */
105+/* $Source: src/include/usr/vpd/pvpdenums.H $ */
106+/* */
107+/* OpenPOWER HostBoot Project */
108+/* */
109+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
110+/* [+] International Business Machines Corp. */
111+/* */
112+/* */
113+/* Licensed under the Apache License, Version 2.0 (the "License"); */
114+/* you may not use this file except in compliance with the License. */
115+/* You may obtain a copy of the License at */
116+/* */
117+/* http://www.apache.org/licenses/LICENSE-2.0 */
118+/* */
119+/* Unless required by applicable law or agreed to in writing, software */
120+/* distributed under the License is distributed on an "AS IS" BASIS, */
121+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
122+/* implied. See the License for the specific language governing */
123+/* permissions and limitations under the License. */
124+/* */
125+/* IBM_PROLOG_END_TAG */
126+#ifndef __PVPDENUMS_H
127+#define __PVPDENUMS_H
128+
129+#include <vpd/ipvpdenums.H>
130+
131+namespace PVPD
132+{
133+
134+ /**
135+ * @brief Enumeration for the PVPD Records that contain
136+ * the keyword enumerations below.
137+ *
138+ */
139+ enum pvpdRecord
140+ {
141+ PVPD_FIRST_RECORD = 0x00,
142+ VINI = PVPD_FIRST_RECORD,
143+ OSYS = 0x01,
144+ OPFR = 0x02,
145+ VNDR = 0x03,
146+ // Last Record
147+ PVPD_LAST_RECORD,
148+ PVPD_TEST_RECORD, // Test purposes ONLY!
149+
150+ //Start common IPVPD enums
151+ PVPD_INVALID_RECORD = IPVPD::INVALID_RECORD,
152+ };
153+
154+ /**
155+ * @brief Enumerations for PVPD keywords that can be
156+ * accessed in the PVPD.
157+ */
158+ enum pvpdKeyword
159+ {
160+ PVPD_FIRST_KEYWORD = 0x00,
161+ pdI = PVPD_FIRST_KEYWORD,
162+ B3 = 0x01,
163+ B4 = 0x02,
164+ B7 = 0x03,
165+ CC = 0x04,
166+ CE = 0x05,
167+ CT = 0x06,
168+ DR = 0x07,
169+ ET = 0x08,
170+ FN = 0x09,
171+ HE = 0x0a,
172+ HW = 0x0b,
173+ IN = 0x0c,
174+ MM = 0x0d,
175+ PF = 0x0e,
176+ PN = 0x0f,
177+ RT = 0x10,
178+ SN = 0x11,
179+ SS = 0x12,
180+ VD = 0x13,
181+ VN = 0x14,
182+ VP = 0x15,
183+ VS = 0x16,
184+ VZ = 0x17,
185+
186+ // Last Keyword
187+ PVPD_LAST_KEYWORD,
188+ PVPD_TEST_KEYWORD, // Test purposes ONLY!
189+
190+ //Start common IPVPD enums
191+ FULL_RECORD = IPVPD::FULL_RECORD,
192+ PVPD_INVALID_KEYWORD = IPVPD::INVALID_KEYWORD,
193+ };
194+
195+}; // end PVPD
196+
197+#endif
198diff --git a/src/include/usr/vpd/vpd_if.H b/src/include/usr/vpd/vpd_if.H
199index 0b3298a..d3915ee 100644
200--- a/src/include/usr/vpd/vpd_if.H
201+++ b/src/include/usr/vpd/vpd_if.H
202@@ -71,6 +71,14 @@ namespace VPD
203 bool cvpdPresent ( TARGETING::Target * i_target );
204
205 /**
206+ * @brief This function checks to see if the given pvpd target
207+ * is present
208+ * @param[in] i_target - Target device to search for pvpd
209+ * @return bool - true if pvpd is present, false if it is not.
210+ */
211+ bool pvpdPresent ( TARGETING::Target * i_target );
212+
213+ /**
214 * @brief This function checks if the PNOR cache for this target is in
215 * sync with the SEEPROM, if not it loads the PNOR cache from SEEPROM.
216 * @param[in] i_target - Target device
217diff --git a/src/include/usr/vpd/vpdreasoncodes.H b/src/include/usr/vpd/vpdreasoncodes.H
218index 88668b7..2cfe8a6 100644
219--- a/src/include/usr/vpd/vpdreasoncodes.H
220+++ b/src/include/usr/vpd/vpdreasoncodes.H
221@@ -61,6 +61,9 @@ enum vpdModuleId
222 VPD_IPVPD_LOAD_PNOR = 0x33,
223 VPD_IPVPD_GET_RECORD_LIST_SEEPROM = 0x34,
224
225+ // PVPD
226+ VPD_PVPD_PRESENCEDETECT = 0x50,
227+
228 // DIMM SPD
229 VPD_SPD_GET_KEYWORD_VALUE = 0x61,
230 VPD_SPD_GET_VALUE = 0x62,
231@@ -131,6 +134,7 @@ enum vpdReasonCode
232 VPD_UNEXPECTED_TARGET_TYPE = VPD_COMP_ID | 0x33,
233 VPD_WRITE_DEST_UNRESOLVED = VPD_COMP_ID | 0x34,
234 VPD_CACHE_SIZE_EXCEEDED = VPD_COMP_ID | 0x35,
235+ VPD_INVALID_LENGTH = VPD_COMP_ID | 0x36,
236 };
237
238
239diff --git a/src/usr/devtree/bld_devtree.C b/src/usr/devtree/bld_devtree.C
240index a8ece97..a311efe 100644
241--- a/src/usr/devtree/bld_devtree.C
242+++ b/src/usr/devtree/bld_devtree.C
243@@ -45,7 +45,7 @@
244 #include <fsi/fsiif.H>
245 #include <config.h>
246 #include <devicefw/userif.H>
247-#include <vpd/cvpdenums.H>
248+#include <vpd/pvpdenums.H>
249 #include <i2c/i2cif.H>
250 #include <i2c/eepromif.H>
251 #include <ipmi/ipmisensor.H>
252@@ -351,12 +351,9 @@ void add_i2c_info( const TARGETING::Target* i_targ,
253 }
254 else if( l_type == TARGETING::TYPE_MEMBUF )
255 {
256- //@fixme-RTC:118373-Remove Hab/Palm workaround
257- // once node vpd is supported
258- sprintf( l_label, "system-vpd" );
259- /*sprintf( l_label, "memb-vpd-%d",
260+ sprintf( l_label, "memb-vpd-%d",
261 eep2->assocTarg
262- ->getAttr<TARGETING::ATTR_POSITION>() );*/
263+ ->getAttr<TARGETING::ATTR_POSITION>() );
264 }
265 else if( l_type == TARGETING::TYPE_DIMM )
266 {
267@@ -1054,39 +1051,46 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree)
268 3) Default to 'unknown'
269 */
270 bool foundvpd = false;
271- // TODO RTC 118373 -- update to account for firestone/memory riser
272- TARGETING::TargetHandleList l_membTargetList;
273- getAllChips(l_membTargetList, TYPE_MEMBUF);
274-
275- //if can't find a centaur for the CVPD, default to unknown
276- if (l_membTargetList.size())
277+ TARGETING::TargetHandleList l_nodeTargetList;
278+ PredicateCTM predNode(CLASS_ENC, TYPE_NODE);
279+ PredicateHwas predFunctional;
280+ predFunctional.functional(true);
281+ PredicatePostfixExpr nodeCheckExpr;
282+ nodeCheckExpr.push(&predNode).push(&predFunctional).And();
283+
284+ targetService().getAssociated(l_nodeTargetList, sys,
285+ TargetService::CHILD, TargetService::IMMEDIATE,
286+ &nodeCheckExpr);
287+
288+ //if can't find a node for the PVPD, default to unknown
289+ if (l_nodeTargetList.size())
290 {
291- TARGETING::Target * l_pMem = l_membTargetList[0];
292+ TARGETING::Target * l_pNode = l_nodeTargetList[0];
293 size_t vpdSize = 0x0;
294
295 // Note: First read with NULL for o_buffer sets vpdSize to the
296 // correct length
297- errhdl = deviceRead( l_pMem,
298+ errhdl = deviceRead( l_pNode,
299 NULL,
300 vpdSize,
301- DEVICE_CVPD_ADDRESS( CVPD::OSYS,
302- CVPD::MM ));
303+ DEVICE_PVPD_ADDRESS( PVPD::OSYS,
304+ PVPD::MM ));
305
306 if(errhdl)
307 {
308 TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't get OSYS:MM size for HUID=0x%.8X",
309- TARGETING::get_huid(l_pMem));
310+ TARGETING::get_huid(l_pNode));
311
312 // Try the OPFR record
313- errlHndl_t opfr_errhdl = deviceRead( l_pMem,
314+ errlHndl_t opfr_errhdl = deviceRead( l_pNode,
315 NULL,
316 vpdSize,
317- DEVICE_CVPD_ADDRESS( CVPD::OPFR,
318- CVPD::DR ));
319+ DEVICE_PVPD_ADDRESS( PVPD::OPFR,
320+ PVPD::DR ));
321 if(opfr_errhdl)
322 {
323 TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't get OPFR:DR size for HUID=0x%.8X",
324- TARGETING::get_huid(l_pMem));
325+ TARGETING::get_huid(l_pNode));
326 delete opfr_errhdl; //delete OPFR log, VPD is just bad
327 }
328 else
329@@ -1095,16 +1099,16 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree)
330 errhdl = NULL;
331 char drBuf[vpdSize+1];
332 memset(&drBuf, 0x0, (vpdSize+1)); //null terminated str
333- errhdl = deviceRead( l_pMem,
334+ errhdl = deviceRead( l_pNode,
335 reinterpret_cast<void*>( &drBuf ),
336 vpdSize,
337- DEVICE_CVPD_ADDRESS( CVPD::OPFR,
338- CVPD::DR ));
339+ DEVICE_PVPD_ADDRESS( PVPD::OPFR,
340+ PVPD::DR ));
341
342 if(errhdl)
343 {
344 TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't read OPFR:DR for HUID=0x%.8X",
345- TARGETING::get_huid(l_pMem));
346+ TARGETING::get_huid(l_pNode));
347 }
348 else
349 {
350@@ -1117,16 +1121,16 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree)
351 {
352 char mmBuf[vpdSize+1];
353 memset(&mmBuf, 0x0, (vpdSize+1)); //ensure null terminated str
354- errhdl = deviceRead( l_pMem,
355+ errhdl = deviceRead( l_pNode,
356 reinterpret_cast<void*>( &mmBuf ),
357 vpdSize,
358- DEVICE_CVPD_ADDRESS( CVPD::OSYS,
359- CVPD::MM ));
360+ DEVICE_PVPD_ADDRESS( PVPD::OSYS,
361+ PVPD::MM ));
362
363 if(errhdl)
364 {
365 TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't read OSYS:MM for HUID=0x%.8X",
366- TARGETING::get_huid(l_pMem));
367+ TARGETING::get_huid(l_pNode));
368 }
369 else
370 {
371@@ -1153,42 +1157,40 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree)
372 1) OSYS:SS
373 2) Default to 'unavailable'
374 */
375- // TODO RTC 118373 -- update to account for firestone/memory riser
376 foundvpd = false;
377- if( l_membTargetList.size() )
378+ if( l_nodeTargetList.size() )
379 {
380- // TODO RTC 118373 - Should be able to read from attribute
381- TARGETING::Target * l_pMem = l_membTargetList[0];
382+ TARGETING::Target * l_pNode = l_nodeTargetList[0];
383 size_t vpdSize = 0x0;
384
385 // Note: First read with NULL for o_buffer sets vpdSize to the
386 // correct length
387- errhdl = deviceRead( l_pMem,
388+ errhdl = deviceRead( l_pNode,
389 NULL,
390 vpdSize,
391- DEVICE_CVPD_ADDRESS( CVPD::OSYS,
392- CVPD::SS ));
393+ DEVICE_PVPD_ADDRESS( PVPD::OSYS,
394+ PVPD::SS ));
395
396 if(errhdl)
397 {
398 TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't get OSYS:SS size for HUID=0x%.8X",
399- TARGETING::get_huid(l_pMem));
400+ TARGETING::get_huid(l_pNode));
401 // Note - not supporting old vpd versions without OSYS here
402 }
403 else
404 {
405 char ssBuf[vpdSize+1];
406 memset(&ssBuf, 0x0, (vpdSize+1)); //ensure null terminated str
407- errhdl = deviceRead( l_pMem,
408+ errhdl = deviceRead( l_pNode,
409 reinterpret_cast<void*>( &ssBuf ),
410 vpdSize,
411- DEVICE_CVPD_ADDRESS( CVPD::OSYS,
412- CVPD::SS ));
413+ DEVICE_PVPD_ADDRESS( PVPD::OSYS,
414+ PVPD::SS ));
415
416 if(errhdl)
417 {
418 TRACFCOMP(g_trac_devtree,ERR_MRK" Couldn't read OSYS:SS for HUID=0x%.8X",
419- TARGETING::get_huid(l_pMem));
420+ TARGETING::get_huid(l_pNode));
421 }
422 else
423 {
424@@ -1205,7 +1207,6 @@ errlHndl_t bld_fdt_system(devTree * i_dt, bool i_smallTree)
425 delete errhdl;
426 errhdl = NULL;
427 }
428-
429 if( !foundvpd ) //serial number not found, default to unavailable
430 {
431 i_dt->addPropertyString(rootNode, "system-id", "unavailable");
432diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C
433index 80c36f9..ef631b5 100644
434--- a/src/usr/hwas/hwasPlat.C
435+++ b/src/usr/hwas/hwasPlat.C
436@@ -421,9 +421,13 @@ errlHndl_t platPresenceDetect(TargetHandleList &io_targets)
437 HWAS_DBG("pTarget %.8X - detected present",
438 pTarget->getAttr<ATTR_HUID>());
439
440- // on to the next target
441+ // If there is planar VPD, then don't skip the presence detect.
442+ // The presence detect will log any problems and load pnor.
443+#if !defined(CONFIG_HAVE_PVPD)
444+ // on to the next target if there is no Planar VPD
445 pTarget_it++;
446 continue;
447+#endif
448 }
449
450 // call deviceRead() to see if they are present
451diff --git a/src/usr/hwas/hwasPlatCallout.C b/src/usr/hwas/hwasPlatCallout.C
452index 0f15082..03756a8 100644
453--- a/src/usr/hwas/hwasPlatCallout.C
454+++ b/src/usr/hwas/hwasPlatCallout.C
455@@ -122,10 +122,12 @@ errlHndl_t platHandleHWCallout(
456 } // switch i_deconfigState
457
458 // check to see if this target is the master processor
459- // and if it's been deconfigured.
460+ // and if it's being deconfigured.
461+ // NOTE: will be non-functional early in IPL before discovery complete.
462 TARGETING::Target *l_masterProc;
463 TARGETING::targetService().masterProcChipTargetHandle(l_masterProc);
464- if (i_pTarget == l_masterProc)
465+ if ( (i_pTarget == l_masterProc) &&
466+ (NO_DECONFIG != i_deconfigState) )
467 {
468 const TARGETING::HwasState hwasState =
469 l_masterProc->getAttr<TARGETING::ATTR_HWAS_STATE>();
470diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C
471index 372fcc7..b2e1c90 100755
472--- a/src/usr/i2c/eepromdd.C
473+++ b/src/usr/i2c/eepromdd.C
474@@ -97,6 +97,11 @@ DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD,
475 TARGETING::TYPE_MEMBUF,
476 eepromPerformOp );
477
478+// Register the perform Op with the routing code for Nodes.
479+DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD,
480+ DeviceFW::EEPROM,
481+ TARGETING::TYPE_NODE,
482+ eepromPerformOp );
483
484 // ------------------------------------------------------------------
485 // eepromPerformOp
486diff --git a/src/usr/ipmi/ipmifruinv.C b/src/usr/ipmi/ipmifruinv.C
487index cc2f06a..49c5e7e 100644
488--- a/src/usr/ipmi/ipmifruinv.C
489+++ b/src/usr/ipmi/ipmifruinv.C
490@@ -29,6 +29,7 @@
491 #include <devicefw/userif.H>
492 #include <vpd/spdenums.H>
493 #include <vpd/cvpdenums.H>
494+#include <vpd/pvpdenums.H>
495 #include <targeting/common/commontargeting.H>
496 #include <targeting/common/utilFilter.H>
497 #include <errl/errlmanager.H>
498@@ -51,7 +52,17 @@ inline static bool comparePairs(
499 const std::pair<TARGETING::TargetHandle_t, uint8_t>& i_lhs,
500 const std::pair<TARGETING::TargetHandle_t, uint8_t>& i_rhs)
501 {
502- return (i_lhs.second < i_rhs.second);
503+ bool l_compare = i_lhs.second < i_rhs.second;
504+
505+ // in case of a tie, if the left is a Node, sort it first.
506+ if (i_lhs.second == i_rhs.second)
507+ {
508+ if (TARGETING::TYPE_NODE==i_lhs.first->getAttr<TARGETING::ATTR_TYPE>())
509+ {
510+ l_compare = true;
511+ }
512+ }
513+ return l_compare;
514 }
515
516 IpmiFruInv::IpmiFruInv(TARGETING::TargetHandle_t i_target)
517@@ -82,7 +93,14 @@ IpmiFruInv *IpmiFruInv::Factory(TARGETING::TargetHandleList i_targets,
518 l_fru = new procIpmiFruInv(l_target, i_updateData);
519 break;
520 case TARGETING::TYPE_MEMBUF:
521- // @todo-RTC:117702
522+ // A memory riser card will have a mem buff with a distinct FRU ID
523+ l_fru = new membufIpmiFruInv(l_target, i_targets, i_updateData);
524+ break;
525+ case TARGETING::TYPE_NODE:
526+ // When the planar eeprom is shared for planar vpd and memory vpd,
527+ // the node and membufs will have the same FRU ID. The node has
528+ // been sorted ahead of the membufs. The membufs are extra targets
529+ // for their ECIDs.
530 l_fru = new backplaneIpmiFruInv(l_target, i_targets, i_updateData);
531 break;
532 case TARGETING::TYPE_SYS:
533@@ -425,11 +443,11 @@ errlHndl_t isdimmIpmiFruInv::buildProductInfoArea(std::vector<uint8_t> &io_data)
534 io_data.push_back(uint8_t(0)); // Empty FRU File ID bytes
535 io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
536
537- //Finalize section formatting
538- postFormatProcessing(io_data);
539-
540 } while (0);
541
542+ //Finalize section formatting
543+ postFormatProcessing(io_data);
544+
545 if (l_errl)
546 {
547 TRACFCOMP(g_trac_ipmi,"isdimIpmiFruInv::buildProductInfoArea - Errors "
548@@ -580,11 +598,11 @@ errlHndl_t procIpmiFruInv::buildBoardInfoArea(std::vector<uint8_t> &io_data)
549 //Indicate end of custom fields
550 io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
551
552- //Complete formatting for this data record
553- postFormatProcessing(io_data);
554-
555 } while (0);
556
557+ //Complete formatting for this data record
558+ postFormatProcessing(io_data);
559+
560 if (l_errl)
561 {
562 TRACFCOMP(g_trac_ipmi,"buildBoardInfoArea - Errors Collecting ISDimm "
563@@ -610,64 +628,18 @@ errlHndl_t procIpmiFruInv::buildMultiRecordInfoArea(
564 errlHndl_t procIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data,
565 uint8_t i_record,
566 uint8_t i_keyword,
567- bool i_ascii)
568+ bool i_ascii,
569+ bool i_typeLengthByte)
570 {
571- size_t l_vpdSize = 0;
572 errlHndl_t l_errl = NULL;
573
574- do {
575-
576- //First get size of data by passing NULL
577- l_errl = deviceRead(iv_target,
578- NULL,
579- l_vpdSize,
580- DEVICE_MVPD_ADDRESS(i_record, i_keyword));
581-
582- if (l_errl)
583- {
584- TRACFCOMP(g_trac_ipmi,"procIpmiFruInv::addVpdData - Error while "
585- "reading MVPD keyword size");
586- break;
587- }
588-
589- //Assert if vpd field is too large to fit in IPMI fru inventory format
590- assert(l_vpdSize < IPMIFRUINV::TYPELENGTH_BYTE_ASCII);
591-
592- if (l_vpdSize > 0)
593- {
594- //Determine how big data is and expand it to handle the soon to
595- //be read VPD data
596- uint8_t l_offset = io_data.size();
597- io_data.resize(l_offset + 1 + l_vpdSize);
598-
599- //Add on the data to the type/length byte indicating it is ascii
600- // otherwise leave it as binary
601- if (i_ascii)
602- {
603- io_data.at(l_offset) = l_vpdSize
604- + IPMIFRUINV::TYPELENGTH_BYTE_ASCII;
605- }
606- else
607- {
608- io_data.at(l_offset) = l_vpdSize;
609- }
610-
611- //Read the VPD data directly into fru inventory data buffer
612- l_errl = deviceRead(iv_target,&io_data[l_offset+1],l_vpdSize,
613- DEVICE_MVPD_ADDRESS(i_record, i_keyword));
614- }
615- else
616- {
617- TRACFCOMP(g_trac_ipmi,"procIpmiFruInv::addVpdData - "
618- " No size returned for MVPD keyword");
619- }
620- } while(0);
621-
622- if (l_errl)
623- {
624- TRACFCOMP(g_trac_ipmi, "addVpdData - Error acquiring data from Vpd.");
625- }
626-
627+ l_errl = addCommonVpdData(iv_target,
628+ io_data,
629+ DeviceFW::MVPD,
630+ i_record,
631+ i_keyword,
632+ i_ascii,
633+ i_typeLengthByte);
634 return l_errl;
635 }
636
637@@ -699,8 +671,7 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea(
638 preFormatProcessing(io_data, false);
639 //Set Chassis Enclosure Type - Not Ascii
640 // Also, do not include type/length byte
641- //@fixme RTC Story 118373
642- l_errl = addVpdData(io_data, CVPD::OSYS, CVPD::ET, false, false);
643+ l_errl = addVpdData(io_data, PVPD::OSYS, PVPD::ET, false, false);
644
645 //Support Legacy VPD without OSYS record
646 if (l_errl)
647@@ -714,12 +685,10 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea(
648 //Set default chassis type
649 io_data.push_back(IPMIFRUINV::DEFAULT_CHASSIS_TYPE);
650 //Set chassis part number - ascii formatted field
651- //@fixme RTC Story 118373
652- l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VP, true);
653+ l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VP, true);
654 if (l_errl) { break; }
655 //Set chassis serial number - ascii formatted field
656- //@fixme RTC Story 118373
657- l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VS, true);
658+ l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VS, true);
659 if (l_errl) { break; }
660 }
661 else
662@@ -728,13 +697,11 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea(
663 " Using NEW OSYS RECORD FOR Chassis VPD Data");
664
665 //Set chassis part number - ascii formatted field
666- //@fixme RTC Story 118373
667- l_errl = addVpdData(io_data, CVPD::OSYS, CVPD::MM, true);
668+ l_errl = addVpdData(io_data, PVPD::OSYS, PVPD::MM, true);
669 if (l_errl) { break; }
670
671 //Set chassis serial number - ascii formatted field
672- //@fixme RTC Story 118373
673- l_errl = addVpdData(io_data, CVPD::OSYS, CVPD::SS, true);
674+ l_errl = addVpdData(io_data, PVPD::OSYS, PVPD::SS, true);
675 if (l_errl) { break; }
676
677 }
678@@ -743,10 +710,11 @@ errlHndl_t backplaneIpmiFruInv::buildChassisInfoArea(
679 io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
680 io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
681
682- //Complete record data formatting
683- postFormatProcessing(io_data);
684 } while (0);
685
686+ //Complete record data formatting
687+ postFormatProcessing(io_data);
688+
689 if (l_errl)
690 {
691 TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::buildChassisInfoArea - "
692@@ -771,67 +739,39 @@ errlHndl_t backplaneIpmiFruInv::buildBoardInfoArea(
693 io_data.push_back(0);
694
695 //Set Vendor Name - ascii formatted data
696- //@fixme RTC Story 118373
697- l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VN, true);
698+ l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VN, true);
699 if (l_errl) { break; }
700
701 //Set Product Name - ascii formatted data
702- //@fixme RTC Story 118373
703- l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::DR, true);
704+ l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::DR, true);
705 if (l_errl) { break; }
706
707 //Set Product Serial number - ascii formatted data
708- //@fixme RTC Story 118373
709- l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VS, true);
710+ //TODO RTC:117702 use attribute when 122890 is available
711+ l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VS, true);
712 if (l_errl) { break; }
713
714 //Set Product Part number - ascii formatted data
715- //@fixme RTC Story 118373
716- l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VP, true);
717- if (l_errl) { break; }
718+ //TODO RTC:117702 use attribute when 122890 is available
719+ l_errl = addVpdData(io_data, PVPD::OPFR, PVPD::VP, true);
720
721 //Push Fru File ID Byte - NULL
722 io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
723
724- bool l_setCustomData = false;
725- // Check if we should add ECID
726- for (TARGETING::TargetHandleList::const_iterator extraTargets_it =
727- iv_extraTargets.begin();
728- extraTargets_it != iv_extraTargets.end();
729- ++extraTargets_it
730- )
731+ //Only set the ECID Data during an update scenario
732+ if (iv_isUpdate == true)
733 {
734- TARGETING::TargetHandle_t l_extraTarget = *extraTargets_it;
735-
736- //Only set the ECID Data during an update scenario
737- if (iv_isUpdate == true &&
738- (l_extraTarget->getAttr<TARGETING::ATTR_TYPE>() ==
739- TARGETING::TYPE_MEMBUF))
740- {
741- TARGETING::ATTR_ECID_type ecidInfo;
742- bool getEcid =
743- l_extraTarget->tryGetAttr<TARGETING::ATTR_ECID>(ecidInfo);
744- if (getEcid)
745- {
746- l_setCustomData = true;
747- addEcidData(l_extraTarget, ecidInfo, io_data);
748- }
749- }
750+ customEcidData (iv_extraTargets, io_data);
751 }
752
753- //If no Custom data was sent, an Empty Byte is needed
754- if (!l_setCustomData)
755- {
756- io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
757- }
758 //Indicate End of Custom Fields
759 io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
760
761- //Complete record data formatting
762- postFormatProcessing(io_data);
763-
764 } while (0);
765
766+ //Complete record data formatting
767+ postFormatProcessing(io_data);
768+
769 if (l_errl)
770 {
771 TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::buildBoardInfoArea - "
772@@ -860,74 +800,17 @@ errlHndl_t backplaneIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data,
773 uint8_t i_keyword,
774 bool i_ascii,
775 bool i_typeLengthByte)
776+
777 {
778- size_t l_vpdSize = 0;
779 errlHndl_t l_errl = NULL;
780
781- do {
782- //First get size of data with NULL parameter
783- l_errl = deviceRead(iv_target,
784- NULL,
785- l_vpdSize,
786- //@fixme RTC Story 118373
787- DEVICE_CVPD_ADDRESS(i_record, i_keyword));
788-
789- if (l_errl)
790- {
791- TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::addVpdData - Error "
792- "while reading CVPD keyword size");
793- break;
794- }
795-
796- //Assert if vpd field is too large to fit in IPMI fru inventory format
797- assert(l_vpdSize < IPMIFRUINV::TYPELENGTH_BYTE_ASCII);
798-
799- if (l_vpdSize > 0)
800- {
801- uint8_t l_offset = 0;
802- //Add on the typelength byte if requested
803- if (i_typeLengthByte)
804- {
805- //Determine how big data is and expand it to handle the soon to
806- //be read VPD data
807- l_offset = io_data.size();
808- io_data.resize(l_offset + 1 + l_vpdSize);
809- //Add on the data to the type/length byte indicating it is ascii
810- // otherwise leave it as binary
811- if (i_ascii)
812- {
813- io_data.at(l_offset) = l_vpdSize
814- + IPMIFRUINV::TYPELENGTH_BYTE_ASCII;
815- }
816- else
817- {
818- io_data.at(l_offset) = l_vpdSize;
819- }
820- l_offset += 1;
821- }
822- else
823- {
824- //Determine how big data is and expand it to handle the soon to
825- //be read VPD data
826- l_offset = io_data.size();
827- io_data.resize(l_offset + l_vpdSize);
828- }
829- //Read the VPD data directly into fru inventory data buffer
830- l_errl = deviceRead(iv_target,&io_data[l_offset],l_vpdSize,
831- DEVICE_CVPD_ADDRESS(i_record, i_keyword));
832- }
833- else
834- {
835- TRACFCOMP(g_trac_ipmi,"backplaneIpmiFruInv::addVpdData - "
836- " No size returned for CVPD keyword");
837- }
838- } while(0);
839-
840- if (l_errl)
841- {
842- TRACFCOMP(g_trac_ipmi, "backplaneIpmiFruInv::addVpdData - Error "
843- "acquiring data from Vpd.");
844- }
845+ l_errl = addCommonVpdData(iv_target,
846+ io_data,
847+ DeviceFW::PVPD,
848+ i_record,
849+ i_keyword,
850+ i_ascii,
851+ i_typeLengthByte);
852
853 return l_errl;
854 }
855@@ -1106,11 +989,11 @@ errlHndl_t systemFwIpmiFruInv::buildProductInfoArea(std::vector<uint8_t>
856
857 io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
858
859- //Finalize section formatting
860- postFormatProcessing(io_data);
861-
862 } while(0);
863
864+ //Finalize section formatting
865+ postFormatProcessing(io_data);
866+
867 return l_errl;
868 }
869
870@@ -1121,7 +1004,155 @@ errlHndl_t systemFwIpmiFruInv::buildMultiRecordInfoArea(std::vector<uint8_t>
871 return IpmiFruInv::buildEmptyArea(io_data);
872 }
873
874+//##############################################################################
875+membufIpmiFruInv::membufIpmiFruInv( TARGETING::TargetHandle_t i_target,
876+ TARGETING::TargetHandleList i_extraTargets,
877+ bool i_isUpdate)
878+ :IpmiFruInv(i_target),
879+ iv_isUpdate(i_isUpdate),
880+ iv_extraTargets(i_extraTargets)
881+{
882+};
883+
884+errlHndl_t membufIpmiFruInv::buildInternalUseArea(
885+ std::vector<uint8_t> &io_data)
886+{
887+ //This section not needed for the mem buf type
888+ return IpmiFruInv::buildEmptyArea(io_data);
889+}
890+
891+errlHndl_t membufIpmiFruInv::buildChassisInfoArea(
892+ std::vector<uint8_t> &io_data)
893+{
894+ //This section not needed for the mem buf type
895+ return IpmiFruInv::buildEmptyArea(io_data);
896+}
897+
898+errlHndl_t membufIpmiFruInv::buildBoardInfoArea(
899+ std::vector<uint8_t> &io_data)
900+{
901+ errlHndl_t l_errl = NULL;
902+
903+ do {
904+ //Set formatting data that goes at the beginning of the record
905+ preFormatProcessing(io_data, true);
906+
907+ //Set MFG Date/Time - Blank
908+ io_data.push_back(0);
909+ io_data.push_back(0);
910+ io_data.push_back(0);
911+
912+ //Set Vendor Name - ascii formatted data
913+ l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VN, true);
914+ if (l_errl) { break; }
915+
916+ //Set Product Name - ascii formatted data
917+ l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::DR, true);
918+ if (l_errl) { break; }
919+
920+ //Set Product Serial number - ascii formatted data
921+ //TODO RTC:117702 use attribute when 122890 is available
922+ l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VS, true);
923+ if (l_errl) { break; }
924+
925+ //Set Product Part number - ascii formatted data
926+ //TODO RTC:117702 use attribute when 122890 is available
927+ l_errl = addVpdData(io_data, CVPD::OPFR, CVPD::VP, true);
928+ if (l_errl) { break; }
929+
930+ //Push Fru File ID Byte - NULL
931+ io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
932+
933+ //Only set the ECID Data during an update scenario
934+ if (iv_isUpdate == true)
935+ {
936+ customEcidData (iv_extraTargets, io_data);
937+ }
938+
939+ //Indicate End of Custom Fields
940+ io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
941+
942+ } while (0);
943+
944+ //Complete record data formatting
945+ postFormatProcessing(io_data);
946+
947+ if (l_errl)
948+ {
949+ TRACFCOMP(g_trac_ipmi,"membufIpmiFruInv::buildBoardInfoArea - "
950+ "Errors collecting board info data");
951+ }
952+
953+ return l_errl;
954+}
955+
956+errlHndl_t membufIpmiFruInv::buildProductInfoArea(
957+ std::vector<uint8_t> &io_data)
958+{
959+ //This section not needed for the mem buf type
960+ return IpmiFruInv::buildEmptyArea(io_data);
961+}
962+
963+errlHndl_t membufIpmiFruInv::buildMultiRecordInfoArea(
964+ std::vector<uint8_t> &io_data)
965+{
966+ //This section not needed for the mem buf type
967+ return IpmiFruInv::buildEmptyArea(io_data);
968+}
969+
970+errlHndl_t membufIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data,
971+ uint8_t i_record,
972+ uint8_t i_keyword,
973+ bool i_ascii,
974+ bool i_typeLengthByte)
975+{
976+ errlHndl_t l_errl = NULL;
977+
978+ l_errl = addCommonVpdData(iv_target,
979+ io_data,
980+ DeviceFW::CVPD,
981+ i_record,
982+ i_keyword,
983+ i_ascii,
984+ i_typeLengthByte);
985+ return l_errl;
986+}
987+//##############################################################################
988+void IpmiFruInv::customEcidData(TARGETING::TargetHandleList i_extraTargets,
989+ std::vector<uint8_t> &io_data)
990+{
991+
992+ bool l_setCustomData = false;
993+ // Check if we should add ECID
994+ for (TARGETING::TargetHandleList::const_iterator extraTargets_it =
995+ i_extraTargets.begin();
996+ extraTargets_it != i_extraTargets.end();
997+ ++extraTargets_it
998+ )
999+ {
1000+ TARGETING::TargetHandle_t l_extraTarget = *extraTargets_it;
1001+
1002+ //Only set the ECID Data during an update scenario
1003+ if ( l_extraTarget->getAttr<TARGETING::ATTR_TYPE>() ==
1004+ TARGETING::TYPE_MEMBUF)
1005+ {
1006+ TARGETING::ATTR_ECID_type ecidInfo;
1007+ bool getEcid =
1008+ l_extraTarget->tryGetAttr<TARGETING::ATTR_ECID>(ecidInfo);
1009+ if (getEcid)
1010+ {
1011+ l_setCustomData = true;
1012+ addEcidData(l_extraTarget, ecidInfo, io_data);
1013+ }
1014+ }
1015+ }
1016
1017+ //If no Custom data was sent, an Empty Byte is needed
1018+ if (!l_setCustomData)
1019+ {
1020+ io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
1021+ }
1022+}
1023
1024 void IpmiFruInv::addEcidData(const TARGETING::TargetHandle_t& i_target,
1025 const TARGETING::ATTR_ECID_type& i_ecidInfo,
1026@@ -1149,6 +1180,94 @@ void IpmiFruInv::addEcidData(const TARGETING::TargetHandle_t& i_target,
1027 return;
1028 }
1029
1030+errlHndl_t IpmiFruInv::addCommonVpdData(
1031+ const TARGETING::TargetHandle_t& i_target,
1032+ std::vector<uint8_t> &io_data,
1033+ DeviceFW::AccessType i_accessType,
1034+ uint8_t i_record,
1035+ uint8_t i_keyword,
1036+ bool i_ascii,
1037+ bool i_typeLengthByte)
1038+{
1039+ size_t l_vpdSize = 0;
1040+ errlHndl_t l_errl = NULL;
1041+
1042+ do {
1043+ // First get size with NULL call:
1044+ // Bypass DEVICE_?VPD_ADDRESS inorder to maximize common code
1045+ l_errl = deviceRead(i_target,
1046+ NULL,
1047+ l_vpdSize,
1048+ i_accessType,
1049+ i_record,
1050+ i_keyword,
1051+ VPD::AUTOSELECT);
1052+
1053+ if (l_errl)
1054+ {
1055+ TRACFCOMP(g_trac_ipmi,"addCommonVpdData - Error "
1056+ "while reading keyword size");
1057+ break;
1058+ }
1059+
1060+ //Assert if vpd field is too large to fit in IPMI fru inventory format
1061+ assert(l_vpdSize < IPMIFRUINV::TYPELENGTH_BYTE_ASCII);
1062+
1063+ if (l_vpdSize > 0)
1064+ {
1065+ uint8_t l_offset = 0;
1066+ //Add on the typelength byte if requested
1067+ if (i_typeLengthByte)
1068+ {
1069+ //Determine how big data is and expand it to handle the soon to
1070+ //be read VPD data
1071+ l_offset = io_data.size();
1072+ io_data.resize(l_offset + 1 + l_vpdSize);
1073+ //Add on the data to the type/length byte indicating it is ascii
1074+ // otherwise leave it as binary
1075+ if (i_ascii)
1076+ {
1077+ io_data.at(l_offset) = l_vpdSize
1078+ + IPMIFRUINV::TYPELENGTH_BYTE_ASCII;
1079+ }
1080+ else
1081+ {
1082+ io_data.at(l_offset) = l_vpdSize;
1083+ }
1084+ l_offset += 1;
1085+ }
1086+ else
1087+ {
1088+ //Determine how big data is and expand it to handle the soon to
1089+ //be read VPD data
1090+ l_offset = io_data.size();
1091+ io_data.resize(l_offset + l_vpdSize);
1092+ }
1093+ //Read the VPD data directly into fru inventory data buffer
1094+ l_errl = deviceRead(i_target,
1095+ &io_data[l_offset],
1096+ l_vpdSize,
1097+ i_accessType,
1098+ i_record,
1099+ i_keyword,
1100+ VPD::AUTOSELECT);
1101+ }
1102+ else
1103+ {
1104+ TRACFCOMP(g_trac_ipmi,"addCommonVpdData - "
1105+ " No size returned for keyword");
1106+ }
1107+ } while(0);
1108+
1109+ if (l_errl)
1110+ {
1111+ TRACFCOMP(g_trac_ipmi, "addCommonVpdData - Error "
1112+ "acquiring data from Vpd.");
1113+ }
1114+
1115+ return l_errl;
1116+}
1117+
1118 void IPMIFRUINV::clearData(uint8_t i_fruId)
1119 {
1120 uint8_t l_clearData[] =
1121@@ -1292,10 +1411,12 @@ void IPMIFRUINV::gatherClearData(const TARGETING::Target* i_pSys,
1122 std::map<uint8_t,bool>& io_frusToClear)
1123 {
1124 TARGETING::PredicateCTM predChip(TARGETING::CLASS_CHIP);
1125+ TARGETING::PredicateCTM predNode(TARGETING::CLASS_ENC,
1126+ TARGETING::TYPE_NODE);
1127 TARGETING::PredicateCTM predDimm(TARGETING::CLASS_LOGICAL_CARD,
1128 TARGETING::TYPE_DIMM);
1129 TARGETING::PredicatePostfixExpr checkAllExpr;
1130- checkAllExpr.push(&predChip).push(&predDimm).Or();
1131+ checkAllExpr.push(&predChip).push(&predNode).Or().push(&predDimm).Or();
1132 TARGETING::TargetHandleList l_allPossibleFrus;
1133 TARGETING::targetService().getAssociated( l_allPossibleFrus, i_pSys,
1134 TARGETING::TargetService::CHILD, TARGETING::TargetService::ALL,
1135@@ -1336,14 +1457,19 @@ void IPMIFRUINV::gatherSetData(const TARGETING::Target* i_pSys,
1136 // may be needed
1137 l_present.present(true);
1138
1139+ checkExpr.push(&predChip);
1140+ TARGETING::PredicateCTM predNode(TARGETING::CLASS_ENC,
1141+ TARGETING::TYPE_NODE);
1142+ checkExpr.push(&predNode).Or();
1143+
1144 //When updating data on a later pass ignore dimms
1145 if (i_updateData)
1146 {
1147- checkExpr.push(&predChip).push(&l_present).And();
1148+ checkExpr.push(&l_present).And();
1149 }
1150 else
1151 {
1152- checkExpr.push(&predChip).push(&predDimm).Or().push(&l_present).And();
1153+ checkExpr.push(&predDimm).Or().push(&l_present).And();
1154 }
1155
1156 TARGETING::TargetHandleList pCheckPres;
1157@@ -1374,6 +1500,10 @@ void IPMIFRUINV::gatherSetData(const TARGETING::Target* i_pSys,
1158 }
1159
1160 //Sort the vector by FRU_ID for later use.
1161+ //When the planar eeprom is shared for planar and memory buffer vpd, the
1162+ //node and membuffs will have the same FRU ID. For this case, sort the Node
1163+ //to be ahead of the mem buffs. The mem buffs will be extra targets for
1164+ //their ECIDs.
1165 std::sort(io_potentialFrus.begin(),
1166 io_potentialFrus.end(),
1167 comparePairs);
1168diff --git a/src/usr/ipmi/ipmifruinvprvt.H b/src/usr/ipmi/ipmifruinvprvt.H
1169index 468a47f..57d6e13 100644
1170--- a/src/usr/ipmi/ipmifruinvprvt.H
1171+++ b/src/usr/ipmi/ipmifruinvprvt.H
1172@@ -186,6 +186,32 @@ class IpmiFruInv
1173 const TARGETING::ATTR_ECID_type& i_ecidInfo,
1174 std::vector<uint8_t> &io_data);
1175
1176+ /**
1177+ * @brief Adds Ecid attribute data from extra targets as custom data
1178+ * @param[in] TargetHandleList, Handle to list of extra
1179+ * targets associated with this FRU Record
1180+ * @param[in/out] data, The container to put ECID attribute data in
1181+ */
1182+ void customEcidData(TARGETING::TargetHandleList i_extraTargets,
1183+ std::vector<uint8_t> &io_data);
1184+
1185+ /**
1186+ * @brief Retrieve vpd record keyword and add to IPMI Fru Inventory record
1187+ * @param[in/out] data, The container with record data
1188+ * @param[in] access, Indicates vpd module to access (MVPD,PVPD,CPVD)
1189+ * @param[in] record, Indicates major offset in the VPD to get more data
1190+ * @param[in] keyword, Indicates minor offset in the VPD to get more data
1191+ * @param[in] ascii, Indicates if VPD field is in ascii format or not
1192+ */
1193+ errlHndl_t addCommonVpdData(
1194+ const TARGETING::TargetHandle_t& i_target,
1195+ std::vector<uint8_t> &io_data,
1196+ DeviceFW::AccessType i_accessType,
1197+ uint8_t i_record,
1198+ uint8_t i_keyword,
1199+ bool i_ascii,
1200+ bool i_typeLengthByte);
1201+
1202 private:
1203
1204 /**
1205@@ -376,11 +402,13 @@ class procIpmiFruInv : public IpmiFruInv
1206 * @param[in] record, Indicates major offset in the VPD to get more data
1207 * @param[in] keyword, Indicates minor offset in the VPD to get more data
1208 * @param[in] ascii, Indicates if VPD field is in ascii format or not
1209+ * @param[in] typeLengthBtye, Indicates whether type length to be added.
1210 */
1211 errlHndl_t addVpdData(std::vector<uint8_t> &io_data,
1212 uint8_t i_record,
1213 uint8_t i_keyword,
1214- bool i_ascii=false);
1215+ bool i_ascii=false,
1216+ bool i_typeLengthByte=true);
1217
1218 };
1219
1220@@ -453,13 +481,13 @@ class backplaneIpmiFruInv : public IpmiFruInv
1221 * @param[in] record, Indicates major offset in the VPD to get more data
1222 * @param[in] keyword, Indicates minor offset in the VPD to get more data
1223 * @param[in] ascii, Indicates if VPD field is in ascii format or not
1224+ * @param[in] typeLengthBtye, Indicates whether type length to be added.
1225 */
1226 errlHndl_t addVpdData(std::vector<uint8_t> &io_data,
1227 uint8_t i_record,
1228 uint8_t i_keyword,
1229 bool i_ascii=false,
1230 bool i_typeLengthByte=true);
1231-
1232 };
1233
1234 //Child class for building up System Firwmare Fru Inventory Record Data
1235@@ -507,4 +535,84 @@ class systemFwIpmiFruInv : public IpmiFruInv
1236
1237 };
1238
1239+//Child class for building up membuf Fru Inventory Record Data. For example,
1240+//for a memory riser card Fru.
1241+class membufIpmiFruInv : public IpmiFruInv
1242+{
1243+
1244+ public:
1245+
1246+ /**
1247+ * @brief Constructor
1248+ *
1249+ * @param[in] TargetHandle_t, Handle to target for which
1250+ * to get relevant IPMI FRU Data from
1251+ * @param[in] TargetHandleList, Handle to list of extra
1252+ * targets associated with this FRU Record
1253+ * @param[in] isUpdate, Indicator if the code is updating
1254+ * existing data, or setting base data.
1255+ */
1256+ membufIpmiFruInv( TARGETING::TargetHandle_t i_target,
1257+ TARGETING::TargetHandleList i_extraTargets,
1258+ bool i_isUpdate );
1259+
1260+ /**
1261+ * @brief Builds the Internal Use Area Data Section
1262+ * @param[in/out] data, The container to put internal use area data in
1263+ */
1264+ errlHndl_t buildInternalUseArea(std::vector<uint8_t> &io_data);
1265+
1266+ /**
1267+ * @brief Builds the Chassis Info Area Data Section
1268+ * @param[in/out] data, The container to put chassis info area data in
1269+ */
1270+ errlHndl_t buildChassisInfoArea(std::vector<uint8_t> &io_data);
1271+
1272+ /**
1273+ * @brief Builds the Board Info Area Data Section
1274+ * @param[in/out] data, The container to put board info area data in
1275+ */
1276+ errlHndl_t buildBoardInfoArea(std::vector<uint8_t> &io_data);
1277+
1278+ /**
1279+ * @brief Builds the Product Info Area Data Section
1280+ * @param[in/out] data, The container to put product info area data in
1281+ */
1282+ errlHndl_t buildProductInfoArea(std::vector<uint8_t>& io_data);
1283+
1284+ /**
1285+ * @brief Builds the MultiRecord Info Area Data Section
1286+ * @param[in/out] data, The container to put multirecord info area data in
1287+ */
1288+ errlHndl_t buildMultiRecordInfoArea(std::vector<uint8_t>& io_data);
1289+
1290+ protected:
1291+ //Indicator if a data update is happening.
1292+ //True - means we are solely updating certain data
1293+ //False - means we are doing the initial 'base' data set
1294+ bool iv_isUpdate;
1295+
1296+ //The list of Extra Targets if multiple targets are
1297+ //associated with one FRU_ID
1298+ TARGETING::TargetHandleList iv_extraTargets;
1299+
1300+ private:
1301+
1302+ /**
1303+ * @brief Adds the specified VPD data to the data to build up a given
1304+ * IPMI Fru Inventory record
1305+ * @param[in/out] data, The container with record data
1306+ * @param[in] record, Indicates major offset in the VPD to get more data
1307+ * @param[in] keyword, Indicates minor offset in the VPD to get more data
1308+ * @param[in] ascii, Indicates if VPD field is in ascii format or not
1309+ * @param[in] typeLengthBtye, Indicates whether type length to be added.
1310+ */
1311+ errlHndl_t addVpdData(std::vector<uint8_t> &io_data,
1312+ uint8_t i_record,
1313+ uint8_t i_keyword,
1314+ bool i_ascii=false,
1315+ bool i_typeLengthByte=true);
1316+
1317+};
1318+
1319 #endif
1320diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml
1321index 82ec014..759b73e 100644
1322--- a/src/usr/targeting/common/xmltohb/target_types.xml
1323+++ b/src/usr/targeting/common/xmltohb/target_types.xml
1324@@ -913,6 +913,8 @@
1325 <attribute><id>FRU_ID</id></attribute>
1326 <attribute><id>TPM_PRIMARY_INFO</id></attribute>
1327 <attribute><id>TPM_BACKUP_INFO</id></attribute>
1328+ <attribute><id>EEPROM_VPD_PRIMARY_INFO</id></attribute>
1329+ <attribute><id>VPD_REC_NUM</id></attribute>
1330 </targetType>
1331
1332 <targetType>
1333diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml
1334index b0429da..d023f50 100644
1335--- a/src/usr/targeting/common/xmltohb/target_types_hb.xml
1336+++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml
1337@@ -180,6 +180,11 @@
1338 </targetTypeExtension>
1339
1340 <targetTypeExtension>
1341+ <id>enc-node-power8</id>
1342+ <attribute><id>VPD_SWITCHES</id></attribute>
1343+</targetTypeExtension>
1344+
1345+<targetTypeExtension>
1346 <id>lcard-dimm</id>
1347 <attribute><id>VPD_SWITCHES</id></attribute>
1348 <attribute><id>IPMI_SENSORS</id></attribute>
1349diff --git a/src/usr/vpd/HBconfig b/src/usr/vpd/HBconfig
1350index 1361834..1d6e6f1 100644
1351--- a/src/usr/vpd/HBconfig
1352+++ b/src/usr/vpd/HBconfig
1353@@ -33,6 +33,28 @@ config CVPD_WRITE
1354 help
1355 Ensure at least one of the CVPD WRITEs are enabled
1356
1357+config PVPD_READ_FROM_PNOR
1358+ default n
1359+ help
1360+ Read Planar VPD data from PNOR cache
1361+
1362+config PVPD_READ_FROM_HW
1363+ default n
1364+ help
1365+ Read Planar VPD data from HW resources
1366+
1367+config PVPD_WRITE_TO_PNOR
1368+ default y if PVPD_READ_FROM_PNOR
1369+ depends on PVPD_READ_FROM_PNOR
1370+ help
1371+ Write Planar VPD data to PNOR cache
1372+
1373+config PVPD_WRITE_TO_HW
1374+ default y if PVPD_READ_FROM_HW
1375+ depends on PVPD_READ_FROM_HW
1376+ help
1377+ Write Planar VPD data to HW resources
1378+
1379 config MVPD_READ_FROM_PNOR
1380 default y
1381 help
1382@@ -105,6 +127,11 @@ config HAVE_MBVPD
1383 help
1384 Have MemBuff/Centaur VPD, PNOR or HW
1385
1386+config HAVE_PVPD
1387+ default y if PVPD_READ_FROM_PNOR || PVPD_READ_FROM_HW
1388+ help
1389+ Have Planar VPD, PNOR or HW
1390+
1391 config PALMETTO_PASS1
1392 default n
1393 help
1394diff --git a/src/usr/vpd/cvpd.C b/src/usr/vpd/cvpd.C
1395index 50815f1..fa37dc9 100644
1396--- a/src/usr/vpd/cvpd.C
1397+++ b/src/usr/vpd/cvpd.C
1398@@ -5,7 +5,7 @@
1399 /* */
1400 /* OpenPOWER HostBoot Project */
1401 /* */
1402-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
1403+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
1404 /* [+] Google Inc. */
1405 /* [+] International Business Machines Corp. */
1406 /* */
1407@@ -31,7 +31,10 @@
1408 #include <trace/interface.H>
1409 #include <errl/errlentry.H>
1410 #include <errl/errlmanager.H>
1411+#include <targeting/common/commontargeting.H>
1412 #include <targeting/common/targetservice.H>
1413+#include <targeting/common/util.H>
1414+#include <targeting/common/utilFilter.H>
1415 #include <devicefw/driverif.H>
1416 #include <vfs/vfs.H>
1417 #include <vpd/vpdreasoncodes.H>
1418@@ -40,6 +43,7 @@
1419 #include <i2c/eepromif.H>
1420 #include <config.h>
1421 #include "cvpd.H"
1422+#include "pvpd.H"
1423 #include "vpd.H"
1424
1425 // ----------------------------------------------
1426@@ -233,15 +237,41 @@ IpVpdFacade(CVPD::SECTION_SIZE,
1427 iv_configInfo.vpdReadHW = true;
1428 #else
1429 iv_configInfo.vpdReadHW = false;
1430-#endif
1431+#endif
1432 #ifdef CONFIG_CVPD_WRITE_TO_PNOR
1433 iv_configInfo.vpdWritePNOR = true;
1434 #else
1435 iv_configInfo.vpdWritePNOR = false;
1436-#endif
1437+#endif
1438 #ifdef CONFIG_CVPD_WRITE_TO_HW
1439 iv_configInfo.vpdWriteHW = true;
1440 #else
1441 iv_configInfo.vpdWriteHW = false;
1442 #endif
1443 }
1444+
1445+// Retrun lists of records that should be copied to pnor.
1446+void CvpdFacade::getRecordLists(
1447+ const recordInfo* & o_primaryVpdRecords,
1448+ uint64_t & o_primaryRecSize,
1449+ const recordInfo* & o_altVpdRecords,
1450+ uint64_t & o_altRecSize)
1451+{
1452+ // Always return this object's list
1453+ o_primaryVpdRecords = iv_vpdRecords;
1454+ o_primaryRecSize = iv_recSize;
1455+
1456+ // If the planar errprom being shared with a mem buf,
1457+ // then return the pvpd list as the alternative record list.
1458+ // At thip point, if the membufs are be processed, then the node
1459+ // might not have been discovered yet. If pvpd is being cached, then
1460+ // include the pvpd list as the altnative.
1461+#ifdef CONFIG_PVPD_READ_FROM_PNOR
1462+ o_altVpdRecords = Singleton<PvpdFacade>::instance().iv_vpdRecords;
1463+ o_altRecSize = Singleton<PvpdFacade>::instance().iv_recSize;
1464+#else
1465+ o_altVpdRecords = NULL;
1466+ o_altRecSize = 0;
1467+#endif
1468+}
1469+
1470diff --git a/src/usr/vpd/cvpd.H b/src/usr/vpd/cvpd.H
1471index e7a2d9f..9c729c3 100644
1472--- a/src/usr/vpd/cvpd.H
1473+++ b/src/usr/vpd/cvpd.H
1474@@ -79,7 +79,6 @@ namespace CVPD
1475 { OPFR, "OPFR" },
1476 { VNDR, "VNDR" },
1477 { SPDX, "SPDX" },
1478- { OSYS, "OSYS" },
1479 // -------------------------------------------------------------------
1480 // DO NOT USE!! This is for test purposes ONLY!
1481 { CVPD_TEST_RECORD, "TEST" },
1482@@ -182,5 +181,26 @@ class CvpdFacade: public IpVpdFacade
1483 */
1484 CvpdFacade( );
1485
1486+ private:
1487+
1488+ /**
1489+ * @brief This function returns a primary and an alternate list of records
1490+ * that should be copied to pnor. The Alternate list is optional.
1491+ *
1492+ * @param[out] o_primaryVpdRecords - Pointer to array of VPD Records to use
1493+ *
1494+ * @param[out] o_primaryRecSize - Size of o_primaryVpdRecords array
1495+ *
1496+ * @param[out] o_altVpdRecords - Pointer to array of VPD Records to use
1497+ *
1498+ * @param[out] o_altRecSize - Size of o_altVpdRecords array
1499+ *
1500+ */
1501+ void getRecordLists(
1502+ const recordInfo* & o_primaryVpdRecords,
1503+ uint64_t & o_primaryRecSize,
1504+ const recordInfo* & o_altVpdRecords,
1505+ uint64_t & o_altRecSize);
1506+
1507 };
1508 #endif // __CVPD_H
1509diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C
1510index 3da20b2..e148bc9 100644
1511--- a/src/usr/vpd/ipvpd.C
1512+++ b/src/usr/vpd/ipvpd.C
1513@@ -43,6 +43,7 @@
1514 #include <vpd/ipvpdenums.H>
1515
1516 #include "vpd.H"
1517+#include "cvpd.H"
1518 #include "ipvpd.H"
1519 #include "errlud_vpd.H"
1520
1521@@ -1336,6 +1337,19 @@ IpVpdFacade::getRecordListSeeprom ( std::list<TocPtRecord> & o_recList,
1522 return err;
1523 }
1524
1525+ // Get the list of records that should be copied to pnor.
1526+ // The list of records for this vpd sub class will be the primary list.
1527+ // If the eeprom is being shared, then their might be an alternate list
1528+ // to also include.
1529+ const recordInfo* l_primaryVpdRecords = NULL;
1530+ uint64_t l_primaryRecSize = 0;
1531+ const recordInfo* l_altVpdRecords = NULL;
1532+ uint64_t l_altRecSize = 0;
1533+ getRecordLists(l_primaryVpdRecords,
1534+ l_primaryRecSize,
1535+ l_altVpdRecords,
1536+ l_altRecSize);
1537+
1538 offset = le16toh( toc_rec->record_offset ) + 1; // skip 'large resource'
1539
1540 // Read the PT keyword(s) from the VTOC
1541@@ -1367,20 +1381,36 @@ IpVpdFacade::getRecordListSeeprom ( std::list<TocPtRecord> & o_recList,
1542 vtoc_pt_offset < pt_len;
1543 vtoc_pt_offset += sizeof(TocPtRecord) )
1544 {
1545+ bool l_found = false;
1546 toc_rec =
1547 reinterpret_cast<TocPtRecord*>(l_buffer + vtoc_pt_offset);
1548
1549 // Save record if on the list for this target
1550- for ( uint32_t rec = 0; rec < iv_recSize; rec++ )
1551+ for ( uint32_t rec = 0; rec < l_primaryRecSize; rec++ )
1552 {
1553 if ( memcmp( toc_rec->record_name,
1554- iv_vpdRecords[rec].recordName,
1555+ l_primaryVpdRecords[rec].recordName,
1556 RECORD_BYTE_SIZE ) == 0 )
1557 {
1558 o_recList.push_back(*toc_rec);
1559+ l_found = true;
1560 break;
1561 }
1562 }
1563+ // if not found, check the alternate list
1564+ if (!l_found)
1565+ {
1566+ for ( uint32_t rec = 0; rec < l_altRecSize; rec++ )
1567+ {
1568+ if ( memcmp( toc_rec->record_name,
1569+ l_altVpdRecords[rec].recordName,
1570+ RECORD_BYTE_SIZE ) == 0 )
1571+ {
1572+ o_recList.push_back(*toc_rec);
1573+ break;
1574+ }
1575+ }
1576+ }
1577 }
1578 }
1579
1580@@ -2182,3 +2212,19 @@ void IpVpdFacade::setConfigFlagsHW ( )
1581 iv_configInfo.vpdWriteHW = true;
1582 }
1583 }
1584+
1585+// Return the lists of records that should be copied to pnor.
1586+// The default lists to use are this object's record list and size.
1587+// No Alternate.
1588+void IpVpdFacade::getRecordLists(
1589+ const recordInfo* & o_primaryVpdRecords,
1590+ uint64_t & o_primaryRecSize,
1591+ const recordInfo* & o_altVpdRecords,
1592+ uint64_t & o_altRecSize)
1593+{
1594+ o_primaryVpdRecords = iv_vpdRecords;
1595+ o_primaryRecSize = iv_recSize;
1596+ o_altVpdRecords = NULL;
1597+ o_altRecSize = 0;
1598+}
1599+
1600diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H
1601index 5cc7bec..e4c4162 100644
1602--- a/src/usr/vpd/ipvpd.H
1603+++ b/src/usr/vpd/ipvpd.H
1604@@ -677,7 +677,24 @@ class IpVpdFacade
1605 errlHndl_t checkBufferSize( size_t i_bufferSize,
1606 size_t i_expectedSize,
1607 TARGETING::Target * i_target );
1608-
1609+ /**
1610+ * @brief This function returns a primary and an alternate list of records
1611+ * that should be copied to pnor. The Alternate list is optional.
1612+ *
1613+ * @param[out] o_primaryVpdRecords - Pointer to array of VPD Records to use
1614+ *
1615+ * @param[out] o_primaryRecSize - Size of o_primaryVpdRecords array
1616+ *
1617+ * @param[out] o_altVpdRecords - Pointer to array of VPD Records to use
1618+ *
1619+ * @param[out] o_altRecSize - Size of o_altVpdRecords array
1620+ *
1621+ */
1622+ virtual void getRecordLists(
1623+ const recordInfo* & o_primaryVpdRecords,
1624+ uint64_t & o_primaryRecSize,
1625+ const recordInfo* & o_altVpdRecords,
1626+ uint64_t & o_altRecSize);
1627
1628 protected: // Variables
1629
1630@@ -693,6 +710,8 @@ class IpVpdFacade
1631 */
1632 uint64_t iv_vpdMaxSections;
1633
1634+
1635+ public: // Variables
1636 /**
1637 * @brief Pointer to array of VPD Record information
1638 *
1639@@ -705,6 +724,7 @@ class IpVpdFacade
1640 */
1641 uint64_t iv_recSize;
1642
1643+ protected: // Variables
1644 /**
1645 * @brief Pointer to array of VPD Keyword information
1646 *
1647diff --git a/src/usr/vpd/pvpd.C b/src/usr/vpd/pvpd.C
1648new file mode 100644
1649index 0000000..ec62237
1650--- /dev/null
1651+++ b/src/usr/vpd/pvpd.C
1652@@ -0,0 +1,369 @@
1653+/* IBM_PROLOG_BEGIN_TAG */
1654+/* This is an automatically generated prolog. */
1655+/* */
1656+/* $Source: src/usr/vpd/pvpd.C $ */
1657+/* */
1658+/* OpenPOWER HostBoot Project */
1659+/* */
1660+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
1661+/* [+] International Business Machines Corp. */
1662+/* */
1663+/* */
1664+/* Licensed under the Apache License, Version 2.0 (the "License"); */
1665+/* you may not use this file except in compliance with the License. */
1666+/* You may obtain a copy of the License at */
1667+/* */
1668+/* http://www.apache.org/licenses/LICENSE-2.0 */
1669+/* */
1670+/* Unless required by applicable law or agreed to in writing, software */
1671+/* distributed under the License is distributed on an "AS IS" BASIS, */
1672+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
1673+/* implied. See the License for the specific language governing */
1674+/* permissions and limitations under the License. */
1675+/* */
1676+/* IBM_PROLOG_END_TAG */
1677+// ----------------------------------------------
1678+// Includes
1679+// ----------------------------------------------
1680+#include <string.h>
1681+#include <endian.h>
1682+#include <trace/interface.H>
1683+#include <errl/errlentry.H>
1684+#include <errl/errlmanager.H>
1685+#include <targeting/common/targetservice.H>
1686+#include <targeting/common/util.H>
1687+#include <targeting/common/utilFilter.H>
1688+#include <devicefw/driverif.H>
1689+#include <vfs/vfs.H>
1690+#include <vpd/vpdreasoncodes.H>
1691+#include <vpd/pvpdenums.H>
1692+#include <vpd/vpd_if.H>
1693+#include <i2c/eepromif.H>
1694+#include <config.h>
1695+#include "pvpd.H"
1696+#include "cvpd.H"
1697+#include "vpd.H"
1698+
1699+// ----------------------------------------------
1700+// Trace definitions
1701+// ----------------------------------------------
1702+extern trace_desc_t* g_trac_vpd;
1703+
1704+
1705+// ------------------------
1706+// Macros for unit testing
1707+//#define TRACUCOMP(args...) TRACFCOMP(args)
1708+#define TRACUCOMP(args...)
1709+//#define TRACSSCOMP(args...) TRACFCOMP(args)
1710+#define TRACSSCOMP(args...)
1711+
1712+namespace PVPD
1713+{
1714+ // ----------------------------------------------
1715+ // Globals
1716+ // ----------------------------------------------
1717+ mutex_t g_mutex = MUTEX_INITIALIZER;
1718+
1719+
1720+ /**
1721+ * @brief This function will perform the steps required to do a read from
1722+ * the Hostboot PVPD data.
1723+ *
1724+ * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
1725+ * driververif.H
1726+ *
1727+ * @param[in] i_target - Processor Target device
1728+ *
1729+ * @param [in/out] io_buffer - Pointer to the data that was read from
1730+ * the target device. This parameter, when set to NULL, will return
1731+ * the keyword size value in io_buflen.
1732+ *
1733+ * @param [in/out] io_buflen - Length of the buffer to be read or written
1734+ * to/from the target. This value should indicate the size of the
1735+ * io_buffer parameter that has been allocated. Being returned it
1736+ * will indicate the number of valid bytes in the buffer being
1737+ * returned. This parameter will contain the size of a keyword when
1738+ * the io_buffer parameter is passed in NULL.
1739+ *
1740+ * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
1741+ * usrif.H
1742+ *
1743+ * @param [in] i_args - This is an argument list for the device driver
1744+ * framework.
1745+ *
1746+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
1747+ * error log.
1748+ */
1749+ errlHndl_t pvpdRead ( DeviceFW::OperationType i_opType,
1750+ TARGETING::Target * i_target,
1751+ void * io_buffer,
1752+ size_t & io_buflen,
1753+ int64_t i_accessType,
1754+ va_list i_args )
1755+ {
1756+ errlHndl_t err = NULL;
1757+ IpVpdFacade::input_args_t args;
1758+ args.record = ((pvpdRecord)va_arg( i_args, uint64_t ));
1759+ args.keyword = ((pvpdKeyword)va_arg( i_args, uint64_t ));
1760+ args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));
1761+
1762+ TRACSSCOMP( g_trac_vpd,
1763+ ENTER_MRK"pvpdRead()" );
1764+
1765+ err = Singleton<PvpdFacade>::instance().read(i_target,
1766+ io_buffer,
1767+ io_buflen,
1768+ args);
1769+
1770+ return err;
1771+ }
1772+
1773+
1774+ /**
1775+ * @brief This function will perform the steps required to do a write to
1776+ * the Hostboot PVPD data.
1777+ *
1778+ * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
1779+ * driververif.H
1780+ *
1781+ * @param[in] i_target - Processor Target device
1782+ *
1783+ * @param [in/out] io_buffer - Pointer to the data that was read from
1784+ * the target device. It will also be used to contain data to
1785+ * be written to the device.
1786+ *
1787+ * @param [in/out] io_buflen - Length of the buffer to be read or written
1788+ * to/from the target. This value should indicate the size of the
1789+ * io_buffer parameter that has been allocated. Being returned it
1790+ * will indicate the number of valid bytes in the buffer being
1791+ * returned.
1792+ *
1793+ * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
1794+ * usrif.H
1795+ *
1796+ * @param [in] i_args - This is an argument list for the device driver
1797+ * framework.
1798+ *
1799+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
1800+ * error log.
1801+ */
1802+ errlHndl_t pvpdWrite ( DeviceFW::OperationType i_opType,
1803+ TARGETING::Target * i_target,
1804+ void * io_buffer,
1805+ size_t & io_buflen,
1806+ int64_t i_accessType,
1807+ va_list i_args )
1808+ {
1809+ errlHndl_t err = NULL;
1810+ IpVpdFacade::input_args_t args;
1811+ args.record = ((pvpdRecord)va_arg( i_args, uint64_t ));
1812+ args.keyword = ((pvpdKeyword)va_arg( i_args, uint64_t ));
1813+ args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t ));
1814+
1815+ TRACSSCOMP( g_trac_vpd,
1816+ ENTER_MRK"pvpdWrite()" );
1817+
1818+
1819+ err = Singleton<PvpdFacade>::instance().write(i_target,
1820+ io_buffer,
1821+ io_buflen,
1822+ args);
1823+
1824+ return err;
1825+ }
1826+
1827+ // Register with the routing code
1828+ DEVICE_REGISTER_ROUTE( DeviceFW::READ,
1829+ DeviceFW::PVPD,
1830+ TARGETING::TYPE_NODE,
1831+ pvpdRead );
1832+ DEVICE_REGISTER_ROUTE( DeviceFW::WRITE,
1833+ DeviceFW::PVPD,
1834+ TARGETING::TYPE_NODE,
1835+ pvpdWrite );
1836+
1837+}; // end namespace PVPD
1838+
1839+#if !defined(__HOSTBOOT_RUNTIME)
1840+// --------------------------------------------------------
1841+// Presence Detection
1842+//---------------------------------------------------------
1843+
1844+/**
1845+ * @brief Performs a presence detect operation on a Node card.
1846+ *
1847+ * There is no FSI presence detection, just Planar vpd detection.
1848+ * Presence is always returned as Success (unless the unlikely case of too
1849+ * small of a buffer passed). A problem with planar EEPROM is logged but
1850+ * not passed up so that the enclosure and everything inside is not
1851+ * deconfigured.
1852+ *
1853+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
1854+ * in driverif.H
1855+ * @param[in] i_target Presence detect target
1856+ * @param[in/out] io_buffer Read: Pointer to output data storage
1857+ * Write: Pointer to input data storage
1858+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1)
1859+ * Output: Success = 1, Failure = 0
1860+ * @param[in] i_accessType DeviceFW::AccessType enum (userif.H)
1861+ * @param[in] i_args This is an argument list for DD framework.
1862+ * In this function, there are no arguments.
1863+ * @return errlHndl_t
1864+ */
1865+errlHndl_t nodePresenceDetect(DeviceFW::OperationType i_opType,
1866+ TARGETING::Target* i_target,
1867+ void* io_buffer,
1868+ size_t& io_buflen,
1869+ int64_t i_accessType,
1870+ va_list i_args)
1871+{
1872+ errlHndl_t l_errl = NULL;
1873+ bool pvpd_present = true;
1874+
1875+ if (unlikely(io_buflen < sizeof(bool)))
1876+ {
1877+ TRACFCOMP(g_trac_vpd,
1878+ ERR_MRK "nodePresenceDetect> Invalid data length: %d",
1879+ io_buflen);
1880+ /*@
1881+ * @errortype
1882+ * @moduleid VPD::VPD_PVPD_PRESENCEDETECT
1883+ * @reasoncode VPD::VPD_INVALID_LENGTH
1884+ * @userdata1 Data Length
1885+ * @devdesc presenceDetect> Invalid data length (!= 1 bytes)
1886+ */
1887+ l_errl =
1888+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
1889+ VPD::VPD_PVPD_PRESENCEDETECT,
1890+ VPD::VPD_INVALID_LENGTH,
1891+ TO_UINT64(io_buflen),
1892+ true /*SW error*/);
1893+ io_buflen = 0;
1894+ return l_errl;
1895+ }
1896+
1897+#if defined(CONFIG_PVPD_READ_FROM_HW) && defined(CONFIG_PVPD_READ_FROM_PNOR)
1898+ pvpd_present = VPD::pvpdPresent( i_target );
1899+ if( pvpd_present )
1900+ {
1901+ // Check if the VPD data in the PNOR matches the SEEPROM
1902+ l_errl = VPD::ensureCacheIsInSync( i_target );
1903+ if( l_errl )
1904+ {
1905+ TRACFCOMP(g_trac_vpd,ERR_MRK "nodePresenceDetect>"
1906+ " Error during ensureCacheIsInSync (PVPD)" );
1907+ errlCommit( l_errl, FSI_COMP_ID );
1908+ }
1909+ }
1910+ else
1911+ {
1912+ TRACFCOMP(g_trac_vpd,
1913+ ERR_MRK "nodePresenceDetect> failed presence detect");
1914+
1915+ // Invalidate PVPD in the PNOR
1916+ l_errl = VPD::invalidatePnorCache(i_target);
1917+ if (l_errl)
1918+ {
1919+ TRACFCOMP( g_trac_vpd, "Error invalidating PVPD in PNOR" );
1920+ errlCommit( l_errl, VPD_COMP_ID );
1921+ }
1922+ pvpd_present = true;
1923+ }
1924+#endif
1925+
1926+ // Always return presence.
1927+ // A returned error deconfigures the node and stops the IPL.
1928+ memcpy(io_buffer, &pvpd_present, sizeof(pvpd_present));
1929+ io_buflen = sizeof(pvpd_present);
1930+
1931+ return NULL;
1932+}
1933+
1934+// Register as the presence detect for nodes.
1935+DEVICE_REGISTER_ROUTE(DeviceFW::READ,
1936+ DeviceFW::PRESENT,
1937+ TARGETING::TYPE_NODE,
1938+ nodePresenceDetect);
1939+#endif
1940+
1941+bool VPD::pvpdPresent( TARGETING::Target * i_target )
1942+{
1943+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"pvpdPresent()");
1944+#if(defined( CONFIG_PVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) )
1945+
1946+ return EEPROM::eepromPresence( i_target );
1947+
1948+#else
1949+ return Singleton<PvpdFacade>::instance().hasVpdPresent( i_target,
1950+ PVPD::OPFR,
1951+ PVPD::VP );
1952+#endif
1953+}
1954+
1955+
1956+//PVPD Class Functions
1957+/**
1958+ * @brief Constructor
1959+ * Planar VPD is included in the Centaur PNOR section.
1960+ * Including with Centaur vpd minimizes the number of PNOR sections.
1961+ */
1962+PvpdFacade::PvpdFacade() :
1963+IpVpdFacade(CVPD::SECTION_SIZE, // note use of CVPD
1964+ CVPD::MAX_SECTIONS, // note use of CVPD
1965+ PVPD::pvpdRecords,
1966+ (sizeof(PVPD::pvpdRecords)/sizeof(PVPD::pvpdRecords[0])),
1967+ PVPD::pvpdKeywords,
1968+ (sizeof(PVPD::pvpdKeywords)/sizeof(PVPD::pvpdKeywords[0])),
1969+ PNOR::CENTAUR_VPD, // note use of CVPD
1970+ PVPD::g_mutex,
1971+ VPD::VPD_WRITE_PLANAR)
1972+{
1973+ TRACUCOMP(g_trac_vpd, "PvpdFacade::PvpdFacade> " );
1974+
1975+#ifdef CONFIG_PVPD_READ_FROM_PNOR
1976+ iv_configInfo.vpdReadPNOR = true;
1977+#else
1978+ iv_configInfo.vpdReadPNOR = false;
1979+#endif
1980+#ifdef CONFIG_PVPD_READ_FROM_HW
1981+ iv_configInfo.vpdReadHW = true;
1982+#else
1983+ iv_configInfo.vpdReadHW = false;
1984+#endif
1985+#ifdef CONFIG_PVPD_WRITE_TO_PNOR
1986+ iv_configInfo.vpdWritePNOR = true;
1987+#else
1988+ iv_configInfo.vpdWritePNOR = false;
1989+#endif
1990+#ifdef CONFIG_PVPD_WRITE_TO_HW
1991+ iv_configInfo.vpdWriteHW = true;
1992+#else
1993+ iv_configInfo.vpdWriteHW = false;
1994+#endif
1995+}
1996+
1997+// Retrun lists of records that should be copied to pnor.
1998+void PvpdFacade::getRecordLists(
1999+ const recordInfo* & o_primaryVpdRecords,
2000+ uint64_t & o_primaryRecSize,
2001+ const recordInfo* & o_altVpdRecords,
2002+ uint64_t & o_altRecSize)
2003+{
2004+ // Always return this object's list
2005+ o_primaryVpdRecords = iv_vpdRecords;
2006+ o_primaryRecSize = iv_recSize;
2007+
2008+ // If the planar eeprom is being shared with a mem buf,
2009+ // then return the cvpd list as the alternative record list.
2010+ // At thip point, if the node is be processed, then the mem buffs
2011+ // might have not been discovered yet. If cvpd is being cached, then
2012+ // include the cvpd list as the altnative.
2013+#ifdef CONFIG_CVPD_READ_FROM_PNOR
2014+ o_altVpdRecords = Singleton<CvpdFacade>::instance().iv_vpdRecords;
2015+ o_altRecSize = Singleton<CvpdFacade>::instance().iv_recSize;
2016+#else
2017+ o_altVpdRecords = NULL;
2018+ o_altRecSize = 0;
2019+#endif
2020+}
2021+
2022diff --git a/src/usr/vpd/pvpd.H b/src/usr/vpd/pvpd.H
2023new file mode 100644
2024index 0000000..092dd45
2025--- /dev/null
2026+++ b/src/usr/vpd/pvpd.H
2027@@ -0,0 +1,149 @@
2028+/* IBM_PROLOG_BEGIN_TAG */
2029+/* This is an automatically generated prolog. */
2030+/* */
2031+/* $Source: src/usr/vpd/pvpd.H $ */
2032+/* */
2033+/* OpenPOWER HostBoot Project */
2034+/* */
2035+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
2036+/* [+] International Business Machines Corp. */
2037+/* */
2038+/* */
2039+/* Licensed under the Apache License, Version 2.0 (the "License"); */
2040+/* you may not use this file except in compliance with the License. */
2041+/* You may obtain a copy of the License at */
2042+/* */
2043+/* http://www.apache.org/licenses/LICENSE-2.0 */
2044+/* */
2045+/* Unless required by applicable law or agreed to in writing, software */
2046+/* distributed under the License is distributed on an "AS IS" BASIS, */
2047+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
2048+/* implied. See the License for the specific language governing */
2049+/* permissions and limitations under the License. */
2050+/* */
2051+/* IBM_PROLOG_END_TAG */
2052+#ifndef __PVPD_H
2053+#define __PVPD_H
2054+
2055+
2056+/**
2057+ * @file pvpd.H
2058+ *
2059+ * @brief Provides the interfaces for the PVPD device driver
2060+ *
2061+ */
2062+
2063+// ----------------------------------------------
2064+// Includes
2065+// ----------------------------------------------
2066+#include <errl/errlentry.H>
2067+#include <vpd/pvpdenums.H>
2068+
2069+#include "ipvpd.H"
2070+#include <config.h>
2071+
2072+namespace PVPD
2073+{
2074+
2075+ /**
2076+ * @brief Conversion of PVPD Records to corresponding character
2077+ * representation.
2078+ */
2079+ const IpVpdFacade::recordInfo pvpdRecords[] =
2080+ {
2081+ // -------------------------------------------------------------------
2082+ // NOTE: This list must remain an ordered list! There will be a
2083+ // testcase that checks this. When adding new entries to the
2084+ // list, be sure that the keyword in each entry (value 0)
2085+ // are in ascending order.
2086+ // -------------------------------------------------------------------
2087+ { VINI, "VINI" },
2088+ { OSYS, "OSYS" },
2089+ { OPFR, "OPFR" },
2090+ { VNDR, "VNDR" },
2091+ // -------------------------------------------------------------------
2092+ // DO NOT USE!! This is for test purposes ONLY!
2093+ { PVPD_TEST_RECORD, "TEST" },
2094+ // -------------------------------------------------------------------
2095+ };
2096+
2097+ /**
2098+ * @brief Conversion of PVPD Keywords to corresponding character
2099+ * representation.
2100+ */
2101+ const IpVpdFacade::keywordInfo pvpdKeywords[] =
2102+ {
2103+ // -------------------------------------------------------------------
2104+ // NOTE: This list must remain an ordered list! There will be a
2105+ // testcase that checks this. When adding new entries to
2106+ // the list, be sure that the keyword in each entry (value 0)
2107+ // are in ascending order.
2108+ // -------------------------------------------------------------------
2109+ { pdI, "#I" },
2110+ { B3, "B3" },
2111+ { B4, "B4" },
2112+ { B7, "B7" },
2113+ { CC, "CC" },
2114+ { CE, "CE" },
2115+ { CT, "CT" },
2116+ { DR, "DR" },
2117+ { ET, "ET" },
2118+ { FN, "FN" },
2119+ { HE, "HE" },
2120+ { HW, "HW" },
2121+ { IN, "IN" },
2122+ { MM, "MM" },
2123+ { PF, "PF" },
2124+ { PN, "PN" },
2125+ { RT, "RT" },
2126+ { SN, "SN" },
2127+ { SS, "SS" },
2128+ { VD, "VD" },
2129+ { VN, "VN" },
2130+ { VP, "VP" },
2131+ { VS, "VS" },
2132+ { VZ, "VZ" },
2133+
2134+ // -------------------------------------------------------------------
2135+ // DO NOT USE!! This is for test purposes ONLY!
2136+ { PVPD_TEST_KEYWORD, "XX" },
2137+ // -------------------------------------------------------------------
2138+
2139+ //Common ipvpd
2140+ { FULL_RECORD, "FL"},
2141+ };
2142+
2143+}; // end PVPD namespace
2144+
2145+class PvpdFacade: public IpVpdFacade
2146+{
2147+ public:
2148+
2149+ /**
2150+ * @brief Constructor
2151+ */
2152+ PvpdFacade( );
2153+
2154+ private:
2155+
2156+ /**
2157+ * @brief This function returns a primary and an alternate list of records
2158+ * that should be copied to pnor. The Alternate list is optional.
2159+ *
2160+ * @param[out] o_primaryVpdRecords - Pointer to array of VPD Records to use
2161+ *
2162+ * @param[out] o_primaryRecSize - Size of o_primaryVpdRecords array
2163+ *
2164+ * @param[out] o_altVpdRecords - Pointer to array of VPD Records to use
2165+ *
2166+ * @param[out] o_altRecSize - Size of o_altVpdRecords array
2167+ *
2168+ */
2169+ void getRecordLists(
2170+ const recordInfo* & o_primaryVpdRecords,
2171+ uint64_t & o_primaryRecSize,
2172+ const recordInfo* & o_altVpdRecords,
2173+ uint64_t & o_altRecSize);
2174+
2175+};
2176+#endif // __PVPD_H
2177diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C
2178index 9b4e1f8..3656696 100755
2179--- a/src/usr/vpd/vpd.C
2180+++ b/src/usr/vpd/vpd.C
2181@@ -34,10 +34,9 @@
2182 #include "vpd.H"
2183 #include "mvpd.H"
2184 #include "cvpd.H"
2185+#include "pvpd.H"
2186 #include "spd.H"
2187
2188-
2189-
2190 // ----------------------------------------------
2191 // Trace definitions
2192 // ----------------------------------------------
2193@@ -456,6 +455,13 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
2194 l_keywordPN = CVPD::VP;
2195 l_keywordSN = CVPD::VS;
2196 }
2197+ else if( l_type == TARGETING::TYPE_NODE )
2198+ {
2199+ l_ipvpd = &(Singleton<PvpdFacade>::instance());
2200+ l_record = PVPD::OPFR;
2201+ l_keywordPN = PVPD::VP;
2202+ l_keywordSN = PVPD::VS;
2203+ }
2204 else if( l_type == TARGETING::TYPE_DIMM )
2205 {
2206 // SPD does not have a singleton instance
2207@@ -487,7 +493,8 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
2208 do
2209 {
2210 // Make sure we are comparing the correct pn/sn for CVPD
2211- if( l_type == TARGETING::TYPE_MEMBUF )
2212+ if( ( l_type == TARGETING::TYPE_MEMBUF ) ||
2213+ ( l_type == TARGETING::TYPE_NODE ) )
2214 {
2215 bool l_zeroPN;
2216 l_err = l_ipvpd->cmpSeepromToZero( i_target,
2217@@ -523,6 +530,7 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
2218 // Compare the Part Numbers in PNOR/SEEPROM
2219 bool l_matchPN = false;
2220 if( ( l_type == TARGETING::TYPE_PROC ) ||
2221+ ( l_type == TARGETING::TYPE_NODE ) ||
2222 ( l_type == TARGETING::TYPE_MEMBUF ) )
2223 {
2224 l_err = l_ipvpd->cmpPnorToSeeprom( i_target,
2225@@ -577,7 +585,8 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
2226 HWAS::markTargetChanged(i_target);
2227
2228 // Load the PNOR data from the SEEPROM
2229- if( ( l_type == TARGETING::TYPE_PROC ) ||
2230+ if( ( l_type == TARGETING::TYPE_PROC ) ||
2231+ ( l_type == TARGETING::TYPE_NODE ) ||
2232 ( l_type == TARGETING::TYPE_MEMBUF ) )
2233 {
2234 l_err = l_ipvpd->loadPnor( i_target );
2235diff --git a/src/usr/vpd/vpd.H b/src/usr/vpd/vpd.H
2236index 9c39a7f..e6cada7 100644
2237--- a/src/usr/vpd/vpd.H
2238+++ b/src/usr/vpd/vpd.H
2239@@ -50,6 +50,7 @@ enum VPD_MSG_TYPE
2240 VPD_WRITE_DIMM = 0x00C1, //< DIMM SPD
2241 VPD_WRITE_PROC = 0x00C2, //< Processor MVPD
2242 VPD_WRITE_MEMBUF = 0x00C3, //< Centaur FRU VPD
2243+ VPD_WRITE_PLANAR = 0x00C4, //< Planar VPD
2244 };
2245
2246 /**
2247diff --git a/src/usr/vpd/vpd.mk b/src/usr/vpd/vpd.mk
2248index 9f85755..65d22e3 100644
2249--- a/src/usr/vpd/vpd.mk
2250+++ b/src/usr/vpd/vpd.mk
2251@@ -5,7 +5,9 @@
2252 #
2253 # OpenPOWER HostBoot Project
2254 #
2255-# COPYRIGHT International Business Machines Corp. 2013,2014
2256+# Contributors Listed Below - COPYRIGHT 2013,2015
2257+# [+] International Business Machines Corp.
2258+#
2259 #
2260 # Licensed under the Apache License, Version 2.0 (the "License");
2261 # you may not use this file except in compliance with the License.
2262@@ -24,5 +26,6 @@
2263 OBJS += ipvpd.o
2264 OBJS += mvpd.o
2265 OBJS += cvpd.o
2266+OBJS += pvpd.o
2267 OBJS += spd.o
2268 OBJS += errlud_vpd.o
2269--
22701.8.2.2
2271