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 
20a27e2e50SMatt Spinler #include <phosphor-logging/log.hpp>
21a27e2e50SMatt Spinler 
22a27e2e50SMatt Spinler using namespace phosphor::logging;
23a27e2e50SMatt Spinler 
24a906c940SMatt Spinler namespace openpower
25a906c940SMatt Spinler {
26a906c940SMatt Spinler namespace pels
27a906c940SMatt Spinler {
28a906c940SMatt Spinler namespace src
29a906c940SMatt Spinler {
30a906c940SMatt Spinler 
31a906c940SMatt Spinler FRUIdentity::FRUIdentity(Stream& pel)
32a906c940SMatt Spinler {
33a906c940SMatt Spinler     pel >> _type >> _size >> _flags;
34a906c940SMatt Spinler 
35ba0ee002SMatt Spinler     if (hasPN() || hasMP())
36a906c940SMatt Spinler     {
37a906c940SMatt Spinler         pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size());
38a906c940SMatt Spinler     }
39a906c940SMatt Spinler 
40ba0ee002SMatt Spinler     if (hasCCIN())
41a906c940SMatt Spinler     {
42a906c940SMatt Spinler         pel.read(_ccin.data(), _ccin.size());
43a906c940SMatt Spinler     }
44a906c940SMatt Spinler 
45ba0ee002SMatt Spinler     if (hasSN())
46a906c940SMatt Spinler     {
47a906c940SMatt Spinler         pel.read(_sn.data(), _sn.size());
48a906c940SMatt Spinler     }
49a906c940SMatt Spinler }
50a906c940SMatt Spinler 
51a09354b7SMatt Spinler size_t FRUIdentity::flattenedSize() const
52a09354b7SMatt Spinler {
53a09354b7SMatt Spinler     size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags);
54a09354b7SMatt Spinler 
55a09354b7SMatt Spinler     if (hasPN() || hasMP())
56a09354b7SMatt Spinler     {
57a09354b7SMatt Spinler         size += _pnOrProcedureID.size();
58a09354b7SMatt Spinler     }
59a09354b7SMatt Spinler 
60a09354b7SMatt Spinler     if (hasCCIN())
61a09354b7SMatt Spinler     {
62a09354b7SMatt Spinler         size += _ccin.size();
63a09354b7SMatt Spinler     }
64a09354b7SMatt Spinler 
65a09354b7SMatt Spinler     if (hasSN())
66a09354b7SMatt Spinler     {
67a09354b7SMatt Spinler         size += _sn.size();
68a09354b7SMatt Spinler     }
69a09354b7SMatt Spinler 
70a09354b7SMatt Spinler     return size;
71a09354b7SMatt Spinler }
72a09354b7SMatt Spinler 
73ba0ee002SMatt Spinler FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin,
74ba0ee002SMatt Spinler                          const std::string& serialNumber)
75ba0ee002SMatt Spinler {
76ba0ee002SMatt Spinler     _type = substructureType;
77ba0ee002SMatt Spinler     _flags = hardwareFRU;
78ba0ee002SMatt Spinler 
79ba0ee002SMatt Spinler     setPartNumber(partNumber);
80ba0ee002SMatt Spinler     setCCIN(ccin);
81ba0ee002SMatt Spinler     setSerialNumber(serialNumber);
82ba0ee002SMatt Spinler 
83ba0ee002SMatt Spinler     _size = flattenedSize();
84ba0ee002SMatt Spinler }
85ba0ee002SMatt Spinler 
86a27e2e50SMatt Spinler FRUIdentity::FRUIdentity(const std::string& procedureFromRegistry)
87ba0ee002SMatt Spinler {
88ba0ee002SMatt Spinler     _type = substructureType;
89ba0ee002SMatt Spinler     _flags = maintenanceProc;
90ba0ee002SMatt Spinler 
91a27e2e50SMatt Spinler     setMaintenanceProcedure(procedureFromRegistry);
92ba0ee002SMatt Spinler 
93ba0ee002SMatt Spinler     _size = flattenedSize();
94ba0ee002SMatt Spinler }
95ba0ee002SMatt Spinler 
96*2b6dfa00SMatt Spinler FRUIdentity::FRUIdentity(const std::string& symbolicFRUFromRegistry,
97*2b6dfa00SMatt Spinler                          bool trustedLocationCode)
98*2b6dfa00SMatt Spinler {
99*2b6dfa00SMatt Spinler     _type = substructureType;
100*2b6dfa00SMatt Spinler     _flags = (trustedLocationCode) ? symbolicFRUTrustedLocCode : symbolicFRU;
101*2b6dfa00SMatt Spinler 
102*2b6dfa00SMatt Spinler     setSymbolicFRU(symbolicFRUFromRegistry);
103*2b6dfa00SMatt Spinler 
104*2b6dfa00SMatt Spinler     _size = flattenedSize();
105*2b6dfa00SMatt Spinler }
106*2b6dfa00SMatt Spinler 
107a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getPN() const
108a906c940SMatt Spinler {
109a906c940SMatt Spinler     if (hasPN())
110a906c940SMatt Spinler     {
111a906c940SMatt Spinler         // NULL terminated
112a906c940SMatt Spinler         std::string pn{_pnOrProcedureID.data()};
113a906c940SMatt Spinler         return pn;
114a906c940SMatt Spinler     }
115a906c940SMatt Spinler 
116a906c940SMatt Spinler     return std::nullopt;
117a906c940SMatt Spinler }
118a906c940SMatt Spinler 
119a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getMaintProc() const
120a906c940SMatt Spinler {
121a906c940SMatt Spinler     if (hasMP())
122a906c940SMatt Spinler     {
123a906c940SMatt Spinler         // NULL terminated
124a906c940SMatt Spinler         std::string mp{_pnOrProcedureID.data()};
125a906c940SMatt Spinler         return mp;
126a906c940SMatt Spinler     }
127a906c940SMatt Spinler 
128a906c940SMatt Spinler     return std::nullopt;
129a906c940SMatt Spinler }
130a906c940SMatt Spinler 
131a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getCCIN() const
132a906c940SMatt Spinler {
133a906c940SMatt Spinler     if (hasCCIN())
134a906c940SMatt Spinler     {
135a906c940SMatt Spinler         std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()};
136ba0ee002SMatt Spinler 
137ba0ee002SMatt Spinler         // Don't leave any NULLs in the string (not there usually)
138ba0ee002SMatt Spinler         if (auto pos = ccin.find('\0'); pos != std::string::npos)
139ba0ee002SMatt Spinler         {
140ba0ee002SMatt Spinler             ccin.resize(pos);
141ba0ee002SMatt Spinler         }
142a906c940SMatt Spinler         return ccin;
143a906c940SMatt Spinler     }
144a906c940SMatt Spinler 
145a906c940SMatt Spinler     return std::nullopt;
146a906c940SMatt Spinler }
147a906c940SMatt Spinler 
148a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getSN() const
149a906c940SMatt Spinler {
150a906c940SMatt Spinler     if (hasSN())
151a906c940SMatt Spinler     {
152a906c940SMatt Spinler         std::string sn{_sn.begin(), _sn.begin() + _sn.size()};
153ba0ee002SMatt Spinler 
154ba0ee002SMatt Spinler         // Don't leave any NULLs in the string (not there usually)
155ba0ee002SMatt Spinler         if (auto pos = sn.find('\0'); pos != std::string::npos)
156ba0ee002SMatt Spinler         {
157ba0ee002SMatt Spinler             sn.resize(pos);
158ba0ee002SMatt Spinler         }
159a906c940SMatt Spinler         return sn;
160a906c940SMatt Spinler     }
161a906c940SMatt Spinler 
162a906c940SMatt Spinler     return std::nullopt;
163a906c940SMatt Spinler }
164a906c940SMatt Spinler 
165724d0d8cSMatt Spinler void FRUIdentity::flatten(Stream& pel) const
166a906c940SMatt Spinler {
167a906c940SMatt Spinler     pel << _type << _size << _flags;
168a906c940SMatt Spinler 
169a906c940SMatt Spinler     if (hasPN() || hasMP())
170a906c940SMatt Spinler     {
171a906c940SMatt Spinler         pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size());
172a906c940SMatt Spinler     }
173a906c940SMatt Spinler 
174a906c940SMatt Spinler     if (hasCCIN())
175a906c940SMatt Spinler     {
176a906c940SMatt Spinler         pel.write(_ccin.data(), _ccin.size());
177a906c940SMatt Spinler     }
178a906c940SMatt Spinler 
179a906c940SMatt Spinler     if (hasSN())
180a906c940SMatt Spinler     {
181a906c940SMatt Spinler         pel.write(_sn.data(), _sn.size());
182a906c940SMatt Spinler     }
183a906c940SMatt Spinler }
184a906c940SMatt Spinler 
185ba0ee002SMatt Spinler void FRUIdentity::setPartNumber(const std::string& partNumber)
186ba0ee002SMatt Spinler {
187ba0ee002SMatt Spinler     _flags |= pnSupplied;
188ba0ee002SMatt Spinler     _flags &= ~maintProcSupplied;
189ba0ee002SMatt Spinler 
190ba0ee002SMatt Spinler     auto pn = partNumber;
191ba0ee002SMatt Spinler 
192ba0ee002SMatt Spinler     // Strip leading whitespace on this one.
193ba0ee002SMatt Spinler     while (' ' == pn.front())
194ba0ee002SMatt Spinler     {
195ba0ee002SMatt Spinler         pn = pn.substr(1);
196ba0ee002SMatt Spinler     }
197ba0ee002SMatt Spinler 
198ba0ee002SMatt Spinler     // Note: strncpy only writes NULLs if pn short
199ba0ee002SMatt Spinler     strncpy(_pnOrProcedureID.data(), pn.c_str(), _pnOrProcedureID.size());
200ba0ee002SMatt Spinler 
201ba0ee002SMatt Spinler     // ensure null terminated
202ba0ee002SMatt Spinler     _pnOrProcedureID.back() = 0;
203ba0ee002SMatt Spinler }
204ba0ee002SMatt Spinler 
205ba0ee002SMatt Spinler void FRUIdentity::setCCIN(const std::string& ccin)
206ba0ee002SMatt Spinler {
207ba0ee002SMatt Spinler     _flags |= ccinSupplied;
208ba0ee002SMatt Spinler 
209ba0ee002SMatt Spinler     // Note: _ccin not null terminated, though strncpy writes NULLs if short
210ba0ee002SMatt Spinler     strncpy(_ccin.data(), ccin.c_str(), _ccin.size());
211ba0ee002SMatt Spinler }
212ba0ee002SMatt Spinler 
213ba0ee002SMatt Spinler void FRUIdentity::setSerialNumber(const std::string& serialNumber)
214ba0ee002SMatt Spinler {
215ba0ee002SMatt Spinler     _flags |= snSupplied;
216ba0ee002SMatt Spinler 
217ba0ee002SMatt Spinler     // Note: _sn not null terminated, though strncpy writes NULLs if short
218ba0ee002SMatt Spinler     strncpy(_sn.data(), serialNumber.c_str(), _sn.size());
219ba0ee002SMatt Spinler }
220ba0ee002SMatt Spinler 
221a27e2e50SMatt Spinler void FRUIdentity::setMaintenanceProcedure(
222a27e2e50SMatt Spinler     const std::string& procedureFromRegistry)
223ba0ee002SMatt Spinler {
224ba0ee002SMatt Spinler     _flags |= maintProcSupplied;
225ba0ee002SMatt Spinler     _flags &= ~pnSupplied;
226ba0ee002SMatt Spinler 
227a27e2e50SMatt Spinler     if (pel_values::maintenanceProcedures.count(procedureFromRegistry))
228a27e2e50SMatt Spinler     {
229a27e2e50SMatt Spinler         strncpy(
230a27e2e50SMatt Spinler             _pnOrProcedureID.data(),
231a27e2e50SMatt Spinler             pel_values::maintenanceProcedures.at(procedureFromRegistry).c_str(),
232ba0ee002SMatt Spinler             _pnOrProcedureID.size());
233a27e2e50SMatt Spinler     }
234a27e2e50SMatt Spinler     else
235a27e2e50SMatt Spinler     {
236a27e2e50SMatt Spinler         log<level::ERR>("Invalid maintenance procedure",
237a27e2e50SMatt Spinler                         entry("PROCEDURE=%s", procedureFromRegistry.c_str()));
238a27e2e50SMatt Spinler         strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
239a27e2e50SMatt Spinler     }
240ba0ee002SMatt Spinler 
241ba0ee002SMatt Spinler     // ensure null terminated
242ba0ee002SMatt Spinler     _pnOrProcedureID.back() = 0;
243ba0ee002SMatt Spinler }
244ba0ee002SMatt Spinler 
245*2b6dfa00SMatt Spinler void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRUFromRegistry)
246*2b6dfa00SMatt Spinler {
247*2b6dfa00SMatt Spinler 
248*2b6dfa00SMatt Spinler     // Treat this has a HW callout.
249*2b6dfa00SMatt Spinler     _flags |= pnSupplied;
250*2b6dfa00SMatt Spinler     _flags &= ~maintProcSupplied;
251*2b6dfa00SMatt Spinler 
252*2b6dfa00SMatt Spinler     if (pel_values::symbolicFRUs.count(symbolicFRUFromRegistry))
253*2b6dfa00SMatt Spinler     {
254*2b6dfa00SMatt Spinler         strncpy(_pnOrProcedureID.data(),
255*2b6dfa00SMatt Spinler                 pel_values::symbolicFRUs.at(symbolicFRUFromRegistry).c_str(),
256*2b6dfa00SMatt Spinler                 _pnOrProcedureID.size());
257*2b6dfa00SMatt Spinler     }
258*2b6dfa00SMatt Spinler     else
259*2b6dfa00SMatt Spinler     {
260*2b6dfa00SMatt Spinler         log<level::ERR>("Invalid symbolic FRU",
261*2b6dfa00SMatt Spinler                         entry("FRU=%s", symbolicFRUFromRegistry.c_str()));
262*2b6dfa00SMatt Spinler         strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
263*2b6dfa00SMatt Spinler     }
264*2b6dfa00SMatt Spinler 
265*2b6dfa00SMatt Spinler     // ensure null terminated
266*2b6dfa00SMatt Spinler     _pnOrProcedureID.back() = 0;
267*2b6dfa00SMatt Spinler }
268*2b6dfa00SMatt Spinler 
269a906c940SMatt Spinler } // namespace src
270a906c940SMatt Spinler } // namespace pels
271a906c940SMatt Spinler } // namespace openpower
272