blob: 6d062372082bea86119380f072e343463f7b99e6 [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlera906c942019-10-08 13:42:05 -050016#include "fru_identity.hpp"
17
Matt Spinlerba0ee002020-03-13 11:24:14 -050018#include "pel_values.hpp"
19
Matt Spinlera27e2e52020-04-09 11:06:11 -050020#include <phosphor-logging/log.hpp>
21
22using namespace phosphor::logging;
23
Matt Spinlera906c942019-10-08 13:42:05 -050024namespace openpower
25{
26namespace pels
27{
28namespace src
29{
30
Matt Spinler18f4b6e2020-05-21 11:36:24 -050031namespace
32{
33
34/**
35 * @brief Fills in the std::array from the string value
36 *
37 * If the string is shorter than the array, it will be padded with
38 * '\0's.
39 *
40 * @param[in] source - The string to fill in the array with
41 * @param[out] target - The input object that supports [] and size()
42 */
43template <typename T>
44void fillArray(const std::string& source, T& target)
45{
46 for (size_t i = 0; i < target.size(); i++)
47 {
48 target[i] = (source.size() > i) ? source[i] : '\0';
49 }
50}
51
52}; // namespace
53
Matt Spinlera906c942019-10-08 13:42:05 -050054FRUIdentity::FRUIdentity(Stream& pel)
55{
56 pel >> _type >> _size >> _flags;
57
Matt Spinlerba0ee002020-03-13 11:24:14 -050058 if (hasPN() || hasMP())
Matt Spinlera906c942019-10-08 13:42:05 -050059 {
60 pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size());
61 }
62
Matt Spinlerba0ee002020-03-13 11:24:14 -050063 if (hasCCIN())
Matt Spinlera906c942019-10-08 13:42:05 -050064 {
65 pel.read(_ccin.data(), _ccin.size());
66 }
67
Matt Spinlerba0ee002020-03-13 11:24:14 -050068 if (hasSN())
Matt Spinlera906c942019-10-08 13:42:05 -050069 {
70 pel.read(_sn.data(), _sn.size());
71 }
72}
73
Matt Spinlera09354b2020-03-13 10:24:52 -050074size_t FRUIdentity::flattenedSize() const
75{
76 size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags);
77
78 if (hasPN() || hasMP())
79 {
80 size += _pnOrProcedureID.size();
81 }
82
83 if (hasCCIN())
84 {
85 size += _ccin.size();
86 }
87
88 if (hasSN())
89 {
90 size += _sn.size();
91 }
92
93 return size;
94}
95
Matt Spinlerba0ee002020-03-13 11:24:14 -050096FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin,
97 const std::string& serialNumber)
98{
99 _type = substructureType;
100 _flags = hardwareFRU;
101
102 setPartNumber(partNumber);
103 setCCIN(ccin);
104 setSerialNumber(serialNumber);
105
106 _size = flattenedSize();
107}
108
Matt Spinlera27e2e52020-04-09 11:06:11 -0500109FRUIdentity::FRUIdentity(const std::string& procedureFromRegistry)
Matt Spinlerba0ee002020-03-13 11:24:14 -0500110{
111 _type = substructureType;
112 _flags = maintenanceProc;
113
Matt Spinlera27e2e52020-04-09 11:06:11 -0500114 setMaintenanceProcedure(procedureFromRegistry);
Matt Spinlerba0ee002020-03-13 11:24:14 -0500115
116 _size = flattenedSize();
117}
118
Matt Spinler2b6dfa02020-04-09 11:39:05 -0500119FRUIdentity::FRUIdentity(const std::string& symbolicFRUFromRegistry,
120 bool trustedLocationCode)
121{
122 _type = substructureType;
123 _flags = (trustedLocationCode) ? symbolicFRUTrustedLocCode : symbolicFRU;
124
125 setSymbolicFRU(symbolicFRUFromRegistry);
126
127 _size = flattenedSize();
128}
129
Matt Spinlera906c942019-10-08 13:42:05 -0500130std::optional<std::string> FRUIdentity::getPN() const
131{
132 if (hasPN())
133 {
134 // NULL terminated
135 std::string pn{_pnOrProcedureID.data()};
136 return pn;
137 }
138
139 return std::nullopt;
140}
141
142std::optional<std::string> FRUIdentity::getMaintProc() const
143{
144 if (hasMP())
145 {
146 // NULL terminated
147 std::string mp{_pnOrProcedureID.data()};
148 return mp;
149 }
150
151 return std::nullopt;
152}
153
154std::optional<std::string> FRUIdentity::getCCIN() const
155{
156 if (hasCCIN())
157 {
158 std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500159
160 // Don't leave any NULLs in the string (not there usually)
161 if (auto pos = ccin.find('\0'); pos != std::string::npos)
162 {
163 ccin.resize(pos);
164 }
Matt Spinlera906c942019-10-08 13:42:05 -0500165 return ccin;
166 }
167
168 return std::nullopt;
169}
170
171std::optional<std::string> FRUIdentity::getSN() const
172{
173 if (hasSN())
174 {
175 std::string sn{_sn.begin(), _sn.begin() + _sn.size()};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500176
177 // Don't leave any NULLs in the string (not there usually)
178 if (auto pos = sn.find('\0'); pos != std::string::npos)
179 {
180 sn.resize(pos);
181 }
Matt Spinlera906c942019-10-08 13:42:05 -0500182 return sn;
183 }
184
185 return std::nullopt;
186}
187
Matt Spinler724d0d82019-11-06 10:05:36 -0600188void FRUIdentity::flatten(Stream& pel) const
Matt Spinlera906c942019-10-08 13:42:05 -0500189{
190 pel << _type << _size << _flags;
191
192 if (hasPN() || hasMP())
193 {
194 pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size());
195 }
196
197 if (hasCCIN())
198 {
199 pel.write(_ccin.data(), _ccin.size());
200 }
201
202 if (hasSN())
203 {
204 pel.write(_sn.data(), _sn.size());
205 }
206}
207
Matt Spinlerba0ee002020-03-13 11:24:14 -0500208void FRUIdentity::setPartNumber(const std::string& partNumber)
209{
210 _flags |= pnSupplied;
211 _flags &= ~maintProcSupplied;
212
213 auto pn = partNumber;
214
215 // Strip leading whitespace on this one.
216 while (' ' == pn.front())
217 {
218 pn = pn.substr(1);
219 }
220
Matt Spinler18f4b6e2020-05-21 11:36:24 -0500221 fillArray(pn, _pnOrProcedureID);
Matt Spinlerba0ee002020-03-13 11:24:14 -0500222
223 // ensure null terminated
224 _pnOrProcedureID.back() = 0;
225}
226
227void FRUIdentity::setCCIN(const std::string& ccin)
228{
229 _flags |= ccinSupplied;
230
Matt Spinler18f4b6e2020-05-21 11:36:24 -0500231 fillArray(ccin, _ccin);
Matt Spinlerba0ee002020-03-13 11:24:14 -0500232}
233
234void FRUIdentity::setSerialNumber(const std::string& serialNumber)
235{
236 _flags |= snSupplied;
237
Matt Spinler18f4b6e2020-05-21 11:36:24 -0500238 fillArray(serialNumber, _sn);
Matt Spinlerba0ee002020-03-13 11:24:14 -0500239}
240
Matt Spinlera27e2e52020-04-09 11:06:11 -0500241void FRUIdentity::setMaintenanceProcedure(
242 const std::string& procedureFromRegistry)
Matt Spinlerba0ee002020-03-13 11:24:14 -0500243{
244 _flags |= maintProcSupplied;
245 _flags &= ~pnSupplied;
246
Matt Spinlera27e2e52020-04-09 11:06:11 -0500247 if (pel_values::maintenanceProcedures.count(procedureFromRegistry))
248 {
Matt Spinler18f4b6e2020-05-21 11:36:24 -0500249 fillArray(pel_values::maintenanceProcedures.at(procedureFromRegistry),
250 _pnOrProcedureID);
Matt Spinlera27e2e52020-04-09 11:06:11 -0500251 }
252 else
253 {
254 log<level::ERR>("Invalid maintenance procedure",
255 entry("PROCEDURE=%s", procedureFromRegistry.c_str()));
256 strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
257 }
Matt Spinlerba0ee002020-03-13 11:24:14 -0500258
259 // ensure null terminated
260 _pnOrProcedureID.back() = 0;
261}
262
Matt Spinler2b6dfa02020-04-09 11:39:05 -0500263void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRUFromRegistry)
264{
265
266 // Treat this has a HW callout.
267 _flags |= pnSupplied;
268 _flags &= ~maintProcSupplied;
269
270 if (pel_values::symbolicFRUs.count(symbolicFRUFromRegistry))
271 {
Matt Spinler18f4b6e2020-05-21 11:36:24 -0500272 fillArray(pel_values::symbolicFRUs.at(symbolicFRUFromRegistry),
273 _pnOrProcedureID);
Matt Spinler2b6dfa02020-04-09 11:39:05 -0500274 }
275 else
276 {
277 log<level::ERR>("Invalid symbolic FRU",
278 entry("FRU=%s", symbolicFRUFromRegistry.c_str()));
279 strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
280 }
281
282 // ensure null terminated
283 _pnOrProcedureID.back() = 0;
284}
285
Matt Spinlera906c942019-10-08 13:42:05 -0500286} // namespace src
287} // namespace pels
288} // namespace openpower