1711d51d8SMatt Spinler /**
2711d51d8SMatt Spinler * Copyright © 2019 IBM Corporation
3711d51d8SMatt Spinler *
4711d51d8SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License");
5711d51d8SMatt Spinler * you may not use this file except in compliance with the License.
6711d51d8SMatt Spinler * You may obtain a copy of the License at
7711d51d8SMatt Spinler *
8711d51d8SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0
9711d51d8SMatt Spinler *
10711d51d8SMatt Spinler * Unless required by applicable law or agreed to in writing, software
11711d51d8SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS,
12711d51d8SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711d51d8SMatt Spinler * See the License for the specific language governing permissions and
14711d51d8SMatt Spinler * limitations under the License.
15711d51d8SMatt Spinler */
16a906c940SMatt Spinler #include "fru_identity.hpp"
17a906c940SMatt Spinler
18ba0ee002SMatt Spinler #include "pel_values.hpp"
19ba0ee002SMatt Spinler
20*5bc26533SArya K Padman #include <phosphor-logging/lg2.hpp>
21a27e2e50SMatt Spinler
221aa90d49SJayanth Othayoth #include <format>
231aa90d49SJayanth Othayoth
24a906c940SMatt Spinler namespace openpower
25a906c940SMatt Spinler {
26a906c940SMatt Spinler namespace pels
27a906c940SMatt Spinler {
28a906c940SMatt Spinler namespace src
29a906c940SMatt Spinler {
30a906c940SMatt Spinler
3118f4b6e8SMatt Spinler namespace
3218f4b6e8SMatt Spinler {
3318f4b6e8SMatt Spinler
3418f4b6e8SMatt Spinler /**
3518f4b6e8SMatt Spinler * @brief Fills in the std::array from the string value
3618f4b6e8SMatt Spinler *
3718f4b6e8SMatt Spinler * If the string is shorter than the array, it will be padded with
3818f4b6e8SMatt Spinler * '\0's.
3918f4b6e8SMatt Spinler *
4018f4b6e8SMatt Spinler * @param[in] source - The string to fill in the array with
4118f4b6e8SMatt Spinler * @param[out] target - The input object that supports [] and size()
4218f4b6e8SMatt Spinler */
4318f4b6e8SMatt Spinler template <typename T>
fillArray(const std::string & source,T & target)4418f4b6e8SMatt Spinler void fillArray(const std::string& source, T& target)
4518f4b6e8SMatt Spinler {
4618f4b6e8SMatt Spinler for (size_t i = 0; i < target.size(); i++)
4718f4b6e8SMatt Spinler {
4818f4b6e8SMatt Spinler target[i] = (source.size() > i) ? source[i] : '\0';
4918f4b6e8SMatt Spinler }
5018f4b6e8SMatt Spinler }
5118f4b6e8SMatt Spinler
52d26fa3e7SPatrick Williams } // namespace
5318f4b6e8SMatt Spinler
FRUIdentity(Stream & pel)54a906c940SMatt Spinler FRUIdentity::FRUIdentity(Stream& pel)
55a906c940SMatt Spinler {
56a906c940SMatt Spinler pel >> _type >> _size >> _flags;
57a906c940SMatt Spinler
58ba0ee002SMatt Spinler if (hasPN() || hasMP())
59a906c940SMatt Spinler {
60a906c940SMatt Spinler pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size());
61a906c940SMatt Spinler }
62a906c940SMatt Spinler
63ba0ee002SMatt Spinler if (hasCCIN())
64a906c940SMatt Spinler {
65a906c940SMatt Spinler pel.read(_ccin.data(), _ccin.size());
66a906c940SMatt Spinler }
67a906c940SMatt Spinler
68ba0ee002SMatt Spinler if (hasSN())
69a906c940SMatt Spinler {
70a906c940SMatt Spinler pel.read(_sn.data(), _sn.size());
71a906c940SMatt Spinler }
72a906c940SMatt Spinler }
73a906c940SMatt Spinler
flattenedSize() const74a09354b7SMatt Spinler size_t FRUIdentity::flattenedSize() const
75a09354b7SMatt Spinler {
76a09354b7SMatt Spinler size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags);
77a09354b7SMatt Spinler
78a09354b7SMatt Spinler if (hasPN() || hasMP())
79a09354b7SMatt Spinler {
80a09354b7SMatt Spinler size += _pnOrProcedureID.size();
81a09354b7SMatt Spinler }
82a09354b7SMatt Spinler
83a09354b7SMatt Spinler if (hasCCIN())
84a09354b7SMatt Spinler {
85a09354b7SMatt Spinler size += _ccin.size();
86a09354b7SMatt Spinler }
87a09354b7SMatt Spinler
88a09354b7SMatt Spinler if (hasSN())
89a09354b7SMatt Spinler {
90a09354b7SMatt Spinler size += _sn.size();
91a09354b7SMatt Spinler }
92a09354b7SMatt Spinler
93a09354b7SMatt Spinler return size;
94a09354b7SMatt Spinler }
95a09354b7SMatt Spinler
FRUIdentity(const std::string & partNumber,const std::string & ccin,const std::string & serialNumber)96ba0ee002SMatt Spinler FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin,
97ba0ee002SMatt Spinler const std::string& serialNumber)
98ba0ee002SMatt Spinler {
99ba0ee002SMatt Spinler _type = substructureType;
100ba0ee002SMatt Spinler _flags = hardwareFRU;
101ba0ee002SMatt Spinler
102ba0ee002SMatt Spinler setPartNumber(partNumber);
103ba0ee002SMatt Spinler setCCIN(ccin);
104ba0ee002SMatt Spinler setSerialNumber(serialNumber);
105ba0ee002SMatt Spinler
106ba0ee002SMatt Spinler _size = flattenedSize();
107ba0ee002SMatt Spinler }
108ba0ee002SMatt Spinler
FRUIdentity(const std::string & procedure,CalloutValueType type)109468aab5fSMatt Spinler FRUIdentity::FRUIdentity(const std::string& procedure, CalloutValueType type)
110ba0ee002SMatt Spinler {
111ba0ee002SMatt Spinler _type = substructureType;
112ba0ee002SMatt Spinler _flags = maintenanceProc;
113ba0ee002SMatt Spinler
114468aab5fSMatt Spinler setMaintenanceProcedure(procedure, type);
115ba0ee002SMatt Spinler
116ba0ee002SMatt Spinler _size = flattenedSize();
117ba0ee002SMatt Spinler }
118ba0ee002SMatt Spinler
FRUIdentity(const std::string & fru,CalloutValueType type,bool trustedLocationCode)119468aab5fSMatt Spinler FRUIdentity::FRUIdentity(const std::string& fru, CalloutValueType type,
1202b6dfa00SMatt Spinler bool trustedLocationCode)
1212b6dfa00SMatt Spinler {
1222b6dfa00SMatt Spinler _type = substructureType;
1232b6dfa00SMatt Spinler _flags = (trustedLocationCode) ? symbolicFRUTrustedLocCode : symbolicFRU;
1242b6dfa00SMatt Spinler
125468aab5fSMatt Spinler setSymbolicFRU(fru, type);
1262b6dfa00SMatt Spinler
1272b6dfa00SMatt Spinler _size = flattenedSize();
1282b6dfa00SMatt Spinler }
1292b6dfa00SMatt Spinler
getPN() const130a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getPN() const
131a906c940SMatt Spinler {
132a906c940SMatt Spinler if (hasPN())
133a906c940SMatt Spinler {
134a906c940SMatt Spinler // NULL terminated
135a906c940SMatt Spinler std::string pn{_pnOrProcedureID.data()};
136a906c940SMatt Spinler return pn;
137a906c940SMatt Spinler }
138a906c940SMatt Spinler
139a906c940SMatt Spinler return std::nullopt;
140a906c940SMatt Spinler }
141a906c940SMatt Spinler
getMaintProc() const142a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getMaintProc() const
143a906c940SMatt Spinler {
144a906c940SMatt Spinler if (hasMP())
145a906c940SMatt Spinler {
146a906c940SMatt Spinler // NULL terminated
147a906c940SMatt Spinler std::string mp{_pnOrProcedureID.data()};
148a906c940SMatt Spinler return mp;
149a906c940SMatt Spinler }
150a906c940SMatt Spinler
151a906c940SMatt Spinler return std::nullopt;
152a906c940SMatt Spinler }
153a906c940SMatt Spinler
getCCIN() const154a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getCCIN() const
155a906c940SMatt Spinler {
156a906c940SMatt Spinler if (hasCCIN())
157a906c940SMatt Spinler {
158a906c940SMatt Spinler std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()};
159ba0ee002SMatt Spinler
160ba0ee002SMatt Spinler // Don't leave any NULLs in the string (not there usually)
161ba0ee002SMatt Spinler if (auto pos = ccin.find('\0'); pos != std::string::npos)
162ba0ee002SMatt Spinler {
163ba0ee002SMatt Spinler ccin.resize(pos);
164ba0ee002SMatt Spinler }
165a906c940SMatt Spinler return ccin;
166a906c940SMatt Spinler }
167a906c940SMatt Spinler
168a906c940SMatt Spinler return std::nullopt;
169a906c940SMatt Spinler }
170a906c940SMatt Spinler
getSN() const171a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getSN() const
172a906c940SMatt Spinler {
173a906c940SMatt Spinler if (hasSN())
174a906c940SMatt Spinler {
175a906c940SMatt Spinler std::string sn{_sn.begin(), _sn.begin() + _sn.size()};
176ba0ee002SMatt Spinler
177ba0ee002SMatt Spinler // Don't leave any NULLs in the string (not there usually)
178ba0ee002SMatt Spinler if (auto pos = sn.find('\0'); pos != std::string::npos)
179ba0ee002SMatt Spinler {
180ba0ee002SMatt Spinler sn.resize(pos);
181ba0ee002SMatt Spinler }
182a906c940SMatt Spinler return sn;
183a906c940SMatt Spinler }
184a906c940SMatt Spinler
185a906c940SMatt Spinler return std::nullopt;
186a906c940SMatt Spinler }
187a906c940SMatt Spinler
flatten(Stream & pel) const188724d0d8cSMatt Spinler void FRUIdentity::flatten(Stream& pel) const
189a906c940SMatt Spinler {
190a906c940SMatt Spinler pel << _type << _size << _flags;
191a906c940SMatt Spinler
192a906c940SMatt Spinler if (hasPN() || hasMP())
193a906c940SMatt Spinler {
194a906c940SMatt Spinler pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size());
195a906c940SMatt Spinler }
196a906c940SMatt Spinler
197a906c940SMatt Spinler if (hasCCIN())
198a906c940SMatt Spinler {
199a906c940SMatt Spinler pel.write(_ccin.data(), _ccin.size());
200a906c940SMatt Spinler }
201a906c940SMatt Spinler
202a906c940SMatt Spinler if (hasSN())
203a906c940SMatt Spinler {
204a906c940SMatt Spinler pel.write(_sn.data(), _sn.size());
205a906c940SMatt Spinler }
206a906c940SMatt Spinler }
207a906c940SMatt Spinler
setPartNumber(const std::string & partNumber)208ba0ee002SMatt Spinler void FRUIdentity::setPartNumber(const std::string& partNumber)
209ba0ee002SMatt Spinler {
210ba0ee002SMatt Spinler _flags |= pnSupplied;
211ba0ee002SMatt Spinler _flags &= ~maintProcSupplied;
212ba0ee002SMatt Spinler
213ba0ee002SMatt Spinler auto pn = partNumber;
214ba0ee002SMatt Spinler
215ba0ee002SMatt Spinler // Strip leading whitespace on this one.
216ba0ee002SMatt Spinler while (' ' == pn.front())
217ba0ee002SMatt Spinler {
218ba0ee002SMatt Spinler pn = pn.substr(1);
219ba0ee002SMatt Spinler }
220ba0ee002SMatt Spinler
22118f4b6e8SMatt Spinler fillArray(pn, _pnOrProcedureID);
222ba0ee002SMatt Spinler
223ba0ee002SMatt Spinler // ensure null terminated
224ba0ee002SMatt Spinler _pnOrProcedureID.back() = 0;
225ba0ee002SMatt Spinler }
226ba0ee002SMatt Spinler
setCCIN(const std::string & ccin)227ba0ee002SMatt Spinler void FRUIdentity::setCCIN(const std::string& ccin)
228ba0ee002SMatt Spinler {
229ba0ee002SMatt Spinler _flags |= ccinSupplied;
230ba0ee002SMatt Spinler
23118f4b6e8SMatt Spinler fillArray(ccin, _ccin);
232ba0ee002SMatt Spinler }
233ba0ee002SMatt Spinler
setSerialNumber(const std::string & serialNumber)234ba0ee002SMatt Spinler void FRUIdentity::setSerialNumber(const std::string& serialNumber)
235ba0ee002SMatt Spinler {
236ba0ee002SMatt Spinler _flags |= snSupplied;
237ba0ee002SMatt Spinler
23818f4b6e8SMatt Spinler fillArray(serialNumber, _sn);
239ba0ee002SMatt Spinler }
240ba0ee002SMatt Spinler
setMaintenanceProcedure(const std::string & procedure,CalloutValueType type)241468aab5fSMatt Spinler void FRUIdentity::setMaintenanceProcedure(const std::string& procedure,
242468aab5fSMatt Spinler CalloutValueType type)
243ba0ee002SMatt Spinler {
244ba0ee002SMatt Spinler _flags |= maintProcSupplied;
245ba0ee002SMatt Spinler _flags &= ~pnSupplied;
246ba0ee002SMatt Spinler
247468aab5fSMatt Spinler if (type == CalloutValueType::registryName)
248a27e2e50SMatt Spinler {
249468aab5fSMatt Spinler if (pel_values::maintenanceProcedures.count(procedure))
250468aab5fSMatt Spinler {
251468aab5fSMatt Spinler fillArray(pel_values::maintenanceProcedures.at(procedure),
25218f4b6e8SMatt Spinler _pnOrProcedureID);
253a27e2e50SMatt Spinler }
254a27e2e50SMatt Spinler else
255a27e2e50SMatt Spinler {
256*5bc26533SArya K Padman lg2::error("Invalid maintenance procedure {PROCEDURE}", "PROCEDURE",
257*5bc26533SArya K Padman procedure);
258468aab5fSMatt Spinler strncpy(_pnOrProcedureID.data(), "INVALID",
259468aab5fSMatt Spinler _pnOrProcedureID.size());
260468aab5fSMatt Spinler }
261468aab5fSMatt Spinler }
262468aab5fSMatt Spinler else
263468aab5fSMatt Spinler {
264468aab5fSMatt Spinler fillArray(procedure, _pnOrProcedureID);
265a27e2e50SMatt Spinler }
266ba0ee002SMatt Spinler
267ba0ee002SMatt Spinler // ensure null terminated
268ba0ee002SMatt Spinler _pnOrProcedureID.back() = 0;
269ba0ee002SMatt Spinler }
270ba0ee002SMatt Spinler
setSymbolicFRU(const std::string & symbolicFRU,CalloutValueType type)271468aab5fSMatt Spinler void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRU,
272468aab5fSMatt Spinler CalloutValueType type)
2732b6dfa00SMatt Spinler {
2742b6dfa00SMatt Spinler // Treat this has a HW callout.
2752b6dfa00SMatt Spinler _flags |= pnSupplied;
2762b6dfa00SMatt Spinler _flags &= ~maintProcSupplied;
2772b6dfa00SMatt Spinler
278468aab5fSMatt Spinler if (type == CalloutValueType::registryName)
2792b6dfa00SMatt Spinler {
280468aab5fSMatt Spinler if (pel_values::symbolicFRUs.count(symbolicFRU))
281468aab5fSMatt Spinler {
282468aab5fSMatt Spinler fillArray(pel_values::symbolicFRUs.at(symbolicFRU),
28318f4b6e8SMatt Spinler _pnOrProcedureID);
2842b6dfa00SMatt Spinler }
2852b6dfa00SMatt Spinler else
2862b6dfa00SMatt Spinler {
287*5bc26533SArya K Padman lg2::error("Invalid symbolic FRU {FRU}", "FRU", symbolicFRU);
288468aab5fSMatt Spinler strncpy(_pnOrProcedureID.data(), "INVALID",
289468aab5fSMatt Spinler _pnOrProcedureID.size());
290468aab5fSMatt Spinler }
291468aab5fSMatt Spinler }
292468aab5fSMatt Spinler else
293468aab5fSMatt Spinler {
294468aab5fSMatt Spinler fillArray(symbolicFRU, _pnOrProcedureID);
2952b6dfa00SMatt Spinler }
2962b6dfa00SMatt Spinler
2972b6dfa00SMatt Spinler // ensure null terminated
2982b6dfa00SMatt Spinler _pnOrProcedureID.back() = 0;
2992b6dfa00SMatt Spinler }
3002b6dfa00SMatt Spinler
301a906c940SMatt Spinler } // namespace src
302a906c940SMatt Spinler } // namespace pels
303a906c940SMatt Spinler } // namespace openpower
304