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 
18*ba0ee002SMatt Spinler #include "pel_values.hpp"
19*ba0ee002SMatt Spinler 
20a906c940SMatt Spinler namespace openpower
21a906c940SMatt Spinler {
22a906c940SMatt Spinler namespace pels
23a906c940SMatt Spinler {
24a906c940SMatt Spinler namespace src
25a906c940SMatt Spinler {
26a906c940SMatt Spinler 
27a906c940SMatt Spinler FRUIdentity::FRUIdentity(Stream& pel)
28a906c940SMatt Spinler {
29a906c940SMatt Spinler     pel >> _type >> _size >> _flags;
30a906c940SMatt Spinler 
31*ba0ee002SMatt Spinler     if (hasPN() || hasMP())
32a906c940SMatt Spinler     {
33a906c940SMatt Spinler         pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size());
34a906c940SMatt Spinler     }
35a906c940SMatt Spinler 
36*ba0ee002SMatt Spinler     if (hasCCIN())
37a906c940SMatt Spinler     {
38a906c940SMatt Spinler         pel.read(_ccin.data(), _ccin.size());
39a906c940SMatt Spinler     }
40a906c940SMatt Spinler 
41*ba0ee002SMatt Spinler     if (hasSN())
42a906c940SMatt Spinler     {
43a906c940SMatt Spinler         pel.read(_sn.data(), _sn.size());
44a906c940SMatt Spinler     }
45a906c940SMatt Spinler }
46a906c940SMatt Spinler 
47a09354b7SMatt Spinler size_t FRUIdentity::flattenedSize() const
48a09354b7SMatt Spinler {
49a09354b7SMatt Spinler     size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags);
50a09354b7SMatt Spinler 
51a09354b7SMatt Spinler     if (hasPN() || hasMP())
52a09354b7SMatt Spinler     {
53a09354b7SMatt Spinler         size += _pnOrProcedureID.size();
54a09354b7SMatt Spinler     }
55a09354b7SMatt Spinler 
56a09354b7SMatt Spinler     if (hasCCIN())
57a09354b7SMatt Spinler     {
58a09354b7SMatt Spinler         size += _ccin.size();
59a09354b7SMatt Spinler     }
60a09354b7SMatt Spinler 
61a09354b7SMatt Spinler     if (hasSN())
62a09354b7SMatt Spinler     {
63a09354b7SMatt Spinler         size += _sn.size();
64a09354b7SMatt Spinler     }
65a09354b7SMatt Spinler 
66a09354b7SMatt Spinler     return size;
67a09354b7SMatt Spinler }
68a09354b7SMatt Spinler 
69*ba0ee002SMatt Spinler FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin,
70*ba0ee002SMatt Spinler                          const std::string& serialNumber)
71*ba0ee002SMatt Spinler {
72*ba0ee002SMatt Spinler     _type = substructureType;
73*ba0ee002SMatt Spinler     _flags = hardwareFRU;
74*ba0ee002SMatt Spinler 
75*ba0ee002SMatt Spinler     setPartNumber(partNumber);
76*ba0ee002SMatt Spinler     setCCIN(ccin);
77*ba0ee002SMatt Spinler     setSerialNumber(serialNumber);
78*ba0ee002SMatt Spinler 
79*ba0ee002SMatt Spinler     _size = flattenedSize();
80*ba0ee002SMatt Spinler }
81*ba0ee002SMatt Spinler 
82*ba0ee002SMatt Spinler FRUIdentity::FRUIdentity(MaintProcedure procedure)
83*ba0ee002SMatt Spinler {
84*ba0ee002SMatt Spinler     _type = substructureType;
85*ba0ee002SMatt Spinler     _flags = maintenanceProc;
86*ba0ee002SMatt Spinler 
87*ba0ee002SMatt Spinler     setMaintenanceProcedure(procedure);
88*ba0ee002SMatt Spinler 
89*ba0ee002SMatt Spinler     _size = flattenedSize();
90*ba0ee002SMatt Spinler }
91*ba0ee002SMatt Spinler 
92a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getPN() const
93a906c940SMatt Spinler {
94a906c940SMatt Spinler     if (hasPN())
95a906c940SMatt Spinler     {
96a906c940SMatt Spinler         // NULL terminated
97a906c940SMatt Spinler         std::string pn{_pnOrProcedureID.data()};
98a906c940SMatt Spinler         return pn;
99a906c940SMatt Spinler     }
100a906c940SMatt Spinler 
101a906c940SMatt Spinler     return std::nullopt;
102a906c940SMatt Spinler }
103a906c940SMatt Spinler 
104a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getMaintProc() const
105a906c940SMatt Spinler {
106a906c940SMatt Spinler     if (hasMP())
107a906c940SMatt Spinler     {
108a906c940SMatt Spinler         // NULL terminated
109a906c940SMatt Spinler         std::string mp{_pnOrProcedureID.data()};
110a906c940SMatt Spinler         return mp;
111a906c940SMatt Spinler     }
112a906c940SMatt Spinler 
113a906c940SMatt Spinler     return std::nullopt;
114a906c940SMatt Spinler }
115a906c940SMatt Spinler 
116a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getCCIN() const
117a906c940SMatt Spinler {
118a906c940SMatt Spinler     if (hasCCIN())
119a906c940SMatt Spinler     {
120a906c940SMatt Spinler         std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()};
121*ba0ee002SMatt Spinler 
122*ba0ee002SMatt Spinler         // Don't leave any NULLs in the string (not there usually)
123*ba0ee002SMatt Spinler         if (auto pos = ccin.find('\0'); pos != std::string::npos)
124*ba0ee002SMatt Spinler         {
125*ba0ee002SMatt Spinler             ccin.resize(pos);
126*ba0ee002SMatt Spinler         }
127a906c940SMatt Spinler         return ccin;
128a906c940SMatt Spinler     }
129a906c940SMatt Spinler 
130a906c940SMatt Spinler     return std::nullopt;
131a906c940SMatt Spinler }
132a906c940SMatt Spinler 
133a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getSN() const
134a906c940SMatt Spinler {
135a906c940SMatt Spinler     if (hasSN())
136a906c940SMatt Spinler     {
137a906c940SMatt Spinler         std::string sn{_sn.begin(), _sn.begin() + _sn.size()};
138*ba0ee002SMatt Spinler 
139*ba0ee002SMatt Spinler         // Don't leave any NULLs in the string (not there usually)
140*ba0ee002SMatt Spinler         if (auto pos = sn.find('\0'); pos != std::string::npos)
141*ba0ee002SMatt Spinler         {
142*ba0ee002SMatt Spinler             sn.resize(pos);
143*ba0ee002SMatt Spinler         }
144a906c940SMatt Spinler         return sn;
145a906c940SMatt Spinler     }
146a906c940SMatt Spinler 
147a906c940SMatt Spinler     return std::nullopt;
148a906c940SMatt Spinler }
149a906c940SMatt Spinler 
150724d0d8cSMatt Spinler void FRUIdentity::flatten(Stream& pel) const
151a906c940SMatt Spinler {
152a906c940SMatt Spinler     pel << _type << _size << _flags;
153a906c940SMatt Spinler 
154a906c940SMatt Spinler     if (hasPN() || hasMP())
155a906c940SMatt Spinler     {
156a906c940SMatt Spinler         pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size());
157a906c940SMatt Spinler     }
158a906c940SMatt Spinler 
159a906c940SMatt Spinler     if (hasCCIN())
160a906c940SMatt Spinler     {
161a906c940SMatt Spinler         pel.write(_ccin.data(), _ccin.size());
162a906c940SMatt Spinler     }
163a906c940SMatt Spinler 
164a906c940SMatt Spinler     if (hasSN())
165a906c940SMatt Spinler     {
166a906c940SMatt Spinler         pel.write(_sn.data(), _sn.size());
167a906c940SMatt Spinler     }
168a906c940SMatt Spinler }
169a906c940SMatt Spinler 
170*ba0ee002SMatt Spinler void FRUIdentity::setPartNumber(const std::string& partNumber)
171*ba0ee002SMatt Spinler {
172*ba0ee002SMatt Spinler     _flags |= pnSupplied;
173*ba0ee002SMatt Spinler     _flags &= ~maintProcSupplied;
174*ba0ee002SMatt Spinler 
175*ba0ee002SMatt Spinler     auto pn = partNumber;
176*ba0ee002SMatt Spinler 
177*ba0ee002SMatt Spinler     // Strip leading whitespace on this one.
178*ba0ee002SMatt Spinler     while (' ' == pn.front())
179*ba0ee002SMatt Spinler     {
180*ba0ee002SMatt Spinler         pn = pn.substr(1);
181*ba0ee002SMatt Spinler     }
182*ba0ee002SMatt Spinler 
183*ba0ee002SMatt Spinler     // Note: strncpy only writes NULLs if pn short
184*ba0ee002SMatt Spinler     strncpy(_pnOrProcedureID.data(), pn.c_str(), _pnOrProcedureID.size());
185*ba0ee002SMatt Spinler 
186*ba0ee002SMatt Spinler     // ensure null terminated
187*ba0ee002SMatt Spinler     _pnOrProcedureID.back() = 0;
188*ba0ee002SMatt Spinler }
189*ba0ee002SMatt Spinler 
190*ba0ee002SMatt Spinler void FRUIdentity::setCCIN(const std::string& ccin)
191*ba0ee002SMatt Spinler {
192*ba0ee002SMatt Spinler     _flags |= ccinSupplied;
193*ba0ee002SMatt Spinler 
194*ba0ee002SMatt Spinler     // Note: _ccin not null terminated, though strncpy writes NULLs if short
195*ba0ee002SMatt Spinler     strncpy(_ccin.data(), ccin.c_str(), _ccin.size());
196*ba0ee002SMatt Spinler }
197*ba0ee002SMatt Spinler 
198*ba0ee002SMatt Spinler void FRUIdentity::setSerialNumber(const std::string& serialNumber)
199*ba0ee002SMatt Spinler {
200*ba0ee002SMatt Spinler     _flags |= snSupplied;
201*ba0ee002SMatt Spinler 
202*ba0ee002SMatt Spinler     // Note: _sn not null terminated, though strncpy writes NULLs if short
203*ba0ee002SMatt Spinler     strncpy(_sn.data(), serialNumber.c_str(), _sn.size());
204*ba0ee002SMatt Spinler }
205*ba0ee002SMatt Spinler 
206*ba0ee002SMatt Spinler void FRUIdentity::setMaintenanceProcedure(MaintProcedure procedure)
207*ba0ee002SMatt Spinler {
208*ba0ee002SMatt Spinler     _flags |= maintProcSupplied;
209*ba0ee002SMatt Spinler     _flags &= ~pnSupplied;
210*ba0ee002SMatt Spinler 
211*ba0ee002SMatt Spinler     auto proc = pel_values::getMaintProcedure(procedure);
212*ba0ee002SMatt Spinler 
213*ba0ee002SMatt Spinler     strncpy(_pnOrProcedureID.data(), std::get<pel_values::mpNamePos>(*proc),
214*ba0ee002SMatt Spinler             _pnOrProcedureID.size());
215*ba0ee002SMatt Spinler 
216*ba0ee002SMatt Spinler     // ensure null terminated
217*ba0ee002SMatt Spinler     _pnOrProcedureID.back() = 0;
218*ba0ee002SMatt Spinler }
219*ba0ee002SMatt Spinler 
220a906c940SMatt Spinler } // namespace src
221a906c940SMatt Spinler } // namespace pels
222a906c940SMatt Spinler } // namespace openpower
223