blob: 83dca55fc9ec7ed2f3cca95c6b04b90ce1570dde [file] [log] [blame]
Bill Hoffaffe83702015-03-30 21:37:20 -05001From 5bda70dc5e135261f5393858959056b44332885b Mon Sep 17 00:00:00 2001
2From: Bill Hoffa <wghoffa@us.ibm.com>
3Date: Mon, 30 Mar 2015 15:11:28 -0500
4Subject: [PATCH 6/7] Add PNOR Version Information to IPMI Fru Inventory
5
6Change-Id: Ib49fe67e9c6631b2b7ea0005e692c9aea6d84057
7RTC:123353
8(cherry picked from commit 90f8e938932e867283e28cade6741b6bf968602c)
9---
10 src/usr/ipmi/ipmifruinv.C | 207 +++++++++++++++++++++
11 src/usr/ipmi/ipmifruinvprvt.H | 47 +++++
12 .../targeting/common/xmltohb/attribute_types.xml | 8 +
13 src/usr/targeting/common/xmltohb/target_types.xml | 1 +
14 4 files changed, 263 insertions(+)
15
16diff --git a/src/usr/ipmi/ipmifruinv.C b/src/usr/ipmi/ipmifruinv.C
17index c6c7a30..b376ebf 100644
18--- a/src/usr/ipmi/ipmifruinv.C
19+++ b/src/usr/ipmi/ipmifruinv.C
20@@ -36,6 +36,7 @@
21 #include "ipmifru.H"
22 #include "ipmifruinvprvt.H"
23 #include <stdio.h>
24+#include <pnor/pnorif.H>
25
26 extern trace_desc_t * g_trac_ipmi;
27
28@@ -83,6 +84,10 @@ IpmiFruInv *IpmiFruInv::Factory(TARGETING::TargetHandleList i_targets,
29 // @todo-RTC:117702
30 l_fru = new backplaneIpmiFruInv(l_target, i_targets, i_updateData);
31 break;
32+ case TARGETING::TYPE_SYS:
33+ // Use sys target for setting System Firmware Info
34+ l_fru = new systemFwIpmiFruInv(l_target);
35+ break;
36 default:
37 assert(false,
38 "IpmiFruInv::Factory: No support for target type given: [%08x]",
39@@ -926,6 +931,199 @@ errlHndl_t backplaneIpmiFruInv::addVpdData(std::vector<uint8_t> &io_data,
40 return l_errl;
41 }
42
43+//##############################################################################
44+systemFwIpmiFruInv::systemFwIpmiFruInv( TARGETING::TargetHandle_t i_target )
45+ :IpmiFruInv(i_target)
46+{
47+
48+};
49+
50+errlHndl_t systemFwIpmiFruInv::buildInternalUseArea(std::vector<uint8_t>
51+ &io_data)
52+{
53+ //This section not needed for proc type
54+ return IpmiFruInv::buildEmptyArea(io_data);
55+}
56+
57+errlHndl_t systemFwIpmiFruInv::buildChassisInfoArea(std::vector<uint8_t>
58+ &io_data)
59+{
60+ //This section not needed for system firmware type
61+ return IpmiFruInv::buildEmptyArea(io_data);
62+}
63+
64+errlHndl_t systemFwIpmiFruInv::buildBoardInfoArea(std::vector<uint8_t> &io_data)
65+{
66+ //This section not needed for system firmware type
67+ return IpmiFruInv::buildEmptyArea(io_data);
68+}
69+
70+errlHndl_t systemFwIpmiFruInv::buildProductInfoArea(std::vector<uint8_t>
71+ &io_data)
72+{
73+ errlHndl_t l_errl = NULL;
74+
75+ do {
76+ //Set formatting data that goes at the beginning of the record
77+ preFormatProcessing(io_data, true);
78+
79+ uint8_t l_data[] = {IPMIFRUINV::TYPELENGTH_BYTE_ASCII + 3,'I','B','M',
80+ IPMIFRUINV::TYPELENGTH_BYTE_ASCII + 18, 'O','p','e',
81+ 'n','P','O','W','E','R',' ','F','i','r','m','w','a',
82+ 'r','e', IPMIFRUINV::TYPELENGTH_BYTE_NULL};
83+
84+ io_data.insert( io_data.end(),
85+ &l_data[0],
86+ &l_data[0] + (uint8_t(sizeof(l_data) / sizeof(uint8_t))));
87+
88+ //Get PNOR Version Here
89+ PNOR::SectionInfo_t l_pnorInfo;
90+ l_errl = getSectionInfo( PNOR::VERSION , l_pnorInfo);
91+ if (l_errl) { break; }
92+
93+ uint8_t* l_versionData = reinterpret_cast<uint8_t*>( l_pnorInfo.vaddr );
94+ //Total Bytes in PNOR Version String
95+ uint8_t l_numBytes = 0;
96+ uint8_t l_curOffset = 0;
97+
98+ //Total Number of fields needed to print PNOR Version String
99+ uint8_t l_numFields = 0;
100+ bool l_clearStandardFields = true;
101+
102+ //First determine number of bytes in PNOR Version string
103+ // with the caveat there is a max record size allowed, so
104+ // the string will be cut off if too long
105+ //Also, remove whitespace/newline chars
106+ while ((l_numBytes < IPMIFRUINV::MAX_RECORD_SIZE -
107+ (uint8_t(sizeof(l_data) / sizeof(uint8_t))) -
108+ IPMIFRUINV::COMMON_HEADER_FORMAT_SIZE - 8)
109+ && (((char)(l_versionData[l_numBytes])) != '\0'))
110+ {
111+
112+ if (((char)(l_versionData[l_numBytes])) == '\n')
113+ {
114+
115+ if (l_numBytes > l_curOffset)
116+ {
117+ //Add on size of this field to the data buffer
118+ io_data.push_back(
119+ IPMIFRUINV::TYPELENGTH_BYTE_ASCII
120+ + (l_numBytes-l_curOffset));
121+
122+ io_data.insert(io_data.end(),
123+ &l_versionData[0]+(l_curOffset),
124+ &l_versionData[0]+(l_numBytes));
125+ }
126+
127+ //Null data for standard fields needs to be indicated once after
128+ // the first segment of data is displayed to match the
129+ // ipmi fru spec
130+ if (l_clearStandardFields)
131+ {
132+ //Add Empty Asset Tag
133+ io_data.push_back(uint8_t(0));
134+ //FRU File ID - Empty
135+ io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
136+ io_data.push_back(uint8_t(0)); // Empty FRU File ID bytes
137+ l_clearStandardFields = false;
138+ }
139+
140+ //Increment past the newline char
141+ l_curOffset = l_numBytes + 1;
142+ }
143+ l_numBytes++;
144+ }
145+
146+ if (l_curOffset == 0)
147+ {
148+ //Calculate the number of fields required to display this data
149+ // given only MAX_ASCII_FIELD_SIZE bytes can be in any one given
150+ // IPMI fru inventory field
151+ l_numFields = l_numBytes / IPMIFRUINV::MAX_ASCII_FIELD_SIZE;
152+ if (l_numBytes % IPMIFRUINV::MAX_ASCII_FIELD_SIZE)
153+ {
154+ l_numFields += 1;
155+ }
156+
157+ //Count by number of fields, adding the data to the buffer as
158+ // we go.
159+ for (uint8_t i=0; i < l_numFields; i++)
160+ {
161+ //Determine the data size for this particular field
162+ uint8_t l_dataSize=IPMIFRUINV::MAX_ASCII_FIELD_SIZE;
163+ if (i == l_numFields - 1)
164+ {
165+ l_dataSize = l_numBytes -
166+ (i * IPMIFRUINV::MAX_ASCII_FIELD_SIZE);
167+ }
168+
169+ //Add on size of this field to the data buffer
170+ io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_ASCII
171+ + l_dataSize);
172+
173+ //Insert this segment of version string data
174+ io_data.insert(io_data.end(),
175+ &l_versionData[0]+(i * IPMIFRUINV::MAX_ASCII_FIELD_SIZE),
176+ &l_versionData[0]+(i * IPMIFRUINV::MAX_ASCII_FIELD_SIZE)
177+ +l_dataSize);
178+
179+ //Null data for standard fields needs to be indicated once after
180+ // the first segment of data is displayed to match the
181+ // ipmi fru spec
182+ if (l_clearStandardFields)
183+ {
184+ //Add Empty Asset Tag
185+ io_data.push_back(uint8_t(0));
186+ //FRU File ID - Empty
187+ io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
188+ //io_data.push_back(uint8_t(0)); // Empty FRU File ID bytes
189+ l_clearStandardFields = false;
190+ }
191+
192+ }
193+ }
194+ else
195+ {
196+ if (l_numBytes > l_curOffset)
197+ {
198+ io_data.push_back( IPMIFRUINV::TYPELENGTH_BYTE_ASCII
199+ + (l_numBytes-l_curOffset));
200+
201+ io_data.insert(io_data.end(),
202+ &l_versionData[0]+(l_curOffset),
203+ &l_versionData[0]+(l_numBytes));
204+ }
205+
206+ }
207+
208+ if (l_clearStandardFields)
209+ {
210+ //Add Asset Tag
211+ io_data.push_back(uint8_t(0)); //No Asset Tag needed - O bytes
212+ //FRU File ID - Empty
213+ io_data.push_back(IPMIFRUINV::TYPELENGTH_BYTE_NULL);
214+ //io_data.push_back(uint8_t(0)); // Empty FRU File ID bytes
215+ }
216+
217+ io_data.push_back(IPMIFRUINV::END_OF_CUSTOM_FIELDS);
218+
219+ //Finalize section formatting
220+ postFormatProcessing(io_data);
221+
222+ } while(0);
223+
224+ return l_errl;
225+}
226+
227+errlHndl_t systemFwIpmiFruInv::buildMultiRecordInfoArea(std::vector<uint8_t>
228+ &io_data)
229+{
230+ //This section not needed for system firmware type
231+ return IpmiFruInv::buildEmptyArea(io_data);
232+}
233+
234+
235+
236 void IpmiFruInv::addEcidData(const TARGETING::TargetHandle_t& i_target,
237 const TARGETING::ATTR_ECID_type& i_ecidInfo,
238 std::vector<uint8_t> &io_data)
239@@ -993,6 +1191,15 @@ void IPMIFRUINV::setData(bool i_updateData)
240 IPMIFRUINV::gatherClearData(pSys, frusToClear);
241 }
242
243+ //Get System FW FRU_ID if available
244+ uint32_t l_systemFwFruId;
245+ bool hasSystemFwFruId =
246+ pSys->tryGetAttr<TARGETING::ATTR_BMC_FRU_ID>(l_systemFwFruId);
247+ if (hasSystemFwFruId)
248+ {
249+ l_potentialFrus.push_back(std::make_pair(pSys, l_systemFwFruId));
250+ }
251+
252 // Find list of all target types that may need a fru inv. record set
253 IPMIFRUINV::gatherSetData(pSys, frusToClear,
254 l_potentialFrus, i_updateData);
255diff --git a/src/usr/ipmi/ipmifruinvprvt.H b/src/usr/ipmi/ipmifruinvprvt.H
256index 2573a84..468a47f 100644
257--- a/src/usr/ipmi/ipmifruinvprvt.H
258+++ b/src/usr/ipmi/ipmifruinvprvt.H
259@@ -42,6 +42,8 @@ namespace IPMIFRUINV
260 COMMON_HEADER_FORMAT_SIZE = 8, //size in bytes
261 DEFAULT_CHASSIS_TYPE = 0x05,
262 DEFAULT_FRU_OFFSET = 0,
263+ MAX_ASCII_FIELD_SIZE = 0x3F, //size in bytes
264+ MAX_RECORD_SIZE = 0xFF, //size in bytes
265 };
266 };
267
268@@ -460,4 +462,49 @@ class backplaneIpmiFruInv : public IpmiFruInv
269
270 };
271
272+//Child class for building up System Firwmare Fru Inventory Record Data
273+class systemFwIpmiFruInv : public IpmiFruInv
274+{
275+
276+ public:
277+ /**
278+ * @brief Constructor
279+ *
280+ * @param[in] TargetHandle_t, Handle to target for which
281+ * to get relevant IPMI FRU Data from
282+ */
283+ systemFwIpmiFruInv( TARGETING::TargetHandle_t i_target);
284+
285+ /**
286+ * @brief Builds the Internal Use Area Data Section
287+ * @param[in/out] data, The container to put internal use area data in
288+ */
289+ errlHndl_t buildInternalUseArea(std::vector<uint8_t> &io_data);
290+
291+ /**
292+ * @brief Builds the Chassis Info Area Data Section
293+ * @param[in/out] data, The container to put chassis info area data in
294+ */
295+ errlHndl_t buildChassisInfoArea(std::vector<uint8_t> &io_data);
296+
297+ /**
298+ * @brief Builds the Board Info Area Data Section
299+ * @param[in/out] data, The container to put board info area data in
300+ */
301+ errlHndl_t buildBoardInfoArea(std::vector<uint8_t> &io_data);
302+
303+ /**
304+ * @brief Builds the Product Info Area Data Section
305+ * @param[in/out] data, The container to put product info area data in
306+ */
307+ errlHndl_t buildProductInfoArea(std::vector<uint8_t> &io_data);
308+
309+ /**
310+ * @brief Builds the MultiRecord Info Area Data Section
311+ * @param[in/out] data, The container to put multirecord info area data in
312+ */
313+ errlHndl_t buildMultiRecordInfoArea(std::vector<uint8_t> &io_data);
314+
315+};
316+
317 #endif
318diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
319index c961ebe..bbf02dd 100644
320--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
321+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
322@@ -11425,6 +11425,14 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript
323 </attribute>
324
325 <attribute>
326+ <id>BMC_FRU_ID</id>
327+ <description>BMC FRU ID attribute for node class</description>
328+ <simpleType><uint32_t><default>0</default></uint32_t></simpleType>
329+ <persistency>non-volatile</persistency>
330+ <readable/>
331+</attribute>
332+
333+<attribute>
334 <id>PLCK_IPL_ATTR_OVERRIDES_EXIST</id>
335 <description>
336 Set to 1 by HWSV to indicate that attribute overrides exist in a PLCK IPL
337diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml
338index 6dc4e58..b4b9a30 100644
339--- a/src/usr/targeting/common/xmltohb/target_types.xml
340+++ b/src/usr/targeting/common/xmltohb/target_types.xml
341@@ -305,6 +305,7 @@
342 <attribute><id>MNFG_TH_CEN_L4_CACHE_CES</id></attribute>
343 <attribute><id>OPT_MEMMAP_GROUP_POLICY</id></attribute>
344 <attribute><id>FRU_ID</id></attribute>
345+ <attribute><id>BMC_FRU_ID</id></attribute>
346 </targetType>
347
348 <targetType>
349--
3501.8.2.2
351