blob: 8cf638277a7bd2b25c3933fc727afcf7cf389469 [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
31FRUIdentity::FRUIdentity(Stream& pel)
32{
33 pel >> _type >> _size >> _flags;
34
Matt Spinlerba0ee002020-03-13 11:24:14 -050035 if (hasPN() || hasMP())
Matt Spinlera906c942019-10-08 13:42:05 -050036 {
37 pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size());
38 }
39
Matt Spinlerba0ee002020-03-13 11:24:14 -050040 if (hasCCIN())
Matt Spinlera906c942019-10-08 13:42:05 -050041 {
42 pel.read(_ccin.data(), _ccin.size());
43 }
44
Matt Spinlerba0ee002020-03-13 11:24:14 -050045 if (hasSN())
Matt Spinlera906c942019-10-08 13:42:05 -050046 {
47 pel.read(_sn.data(), _sn.size());
48 }
49}
50
Matt Spinlera09354b2020-03-13 10:24:52 -050051size_t FRUIdentity::flattenedSize() const
52{
53 size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags);
54
55 if (hasPN() || hasMP())
56 {
57 size += _pnOrProcedureID.size();
58 }
59
60 if (hasCCIN())
61 {
62 size += _ccin.size();
63 }
64
65 if (hasSN())
66 {
67 size += _sn.size();
68 }
69
70 return size;
71}
72
Matt Spinlerba0ee002020-03-13 11:24:14 -050073FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin,
74 const std::string& serialNumber)
75{
76 _type = substructureType;
77 _flags = hardwareFRU;
78
79 setPartNumber(partNumber);
80 setCCIN(ccin);
81 setSerialNumber(serialNumber);
82
83 _size = flattenedSize();
84}
85
Matt Spinlera27e2e52020-04-09 11:06:11 -050086FRUIdentity::FRUIdentity(const std::string& procedureFromRegistry)
Matt Spinlerba0ee002020-03-13 11:24:14 -050087{
88 _type = substructureType;
89 _flags = maintenanceProc;
90
Matt Spinlera27e2e52020-04-09 11:06:11 -050091 setMaintenanceProcedure(procedureFromRegistry);
Matt Spinlerba0ee002020-03-13 11:24:14 -050092
93 _size = flattenedSize();
94}
95
Matt Spinlera906c942019-10-08 13:42:05 -050096std::optional<std::string> FRUIdentity::getPN() const
97{
98 if (hasPN())
99 {
100 // NULL terminated
101 std::string pn{_pnOrProcedureID.data()};
102 return pn;
103 }
104
105 return std::nullopt;
106}
107
108std::optional<std::string> FRUIdentity::getMaintProc() const
109{
110 if (hasMP())
111 {
112 // NULL terminated
113 std::string mp{_pnOrProcedureID.data()};
114 return mp;
115 }
116
117 return std::nullopt;
118}
119
120std::optional<std::string> FRUIdentity::getCCIN() const
121{
122 if (hasCCIN())
123 {
124 std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500125
126 // Don't leave any NULLs in the string (not there usually)
127 if (auto pos = ccin.find('\0'); pos != std::string::npos)
128 {
129 ccin.resize(pos);
130 }
Matt Spinlera906c942019-10-08 13:42:05 -0500131 return ccin;
132 }
133
134 return std::nullopt;
135}
136
137std::optional<std::string> FRUIdentity::getSN() const
138{
139 if (hasSN())
140 {
141 std::string sn{_sn.begin(), _sn.begin() + _sn.size()};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500142
143 // Don't leave any NULLs in the string (not there usually)
144 if (auto pos = sn.find('\0'); pos != std::string::npos)
145 {
146 sn.resize(pos);
147 }
Matt Spinlera906c942019-10-08 13:42:05 -0500148 return sn;
149 }
150
151 return std::nullopt;
152}
153
Matt Spinler724d0d82019-11-06 10:05:36 -0600154void FRUIdentity::flatten(Stream& pel) const
Matt Spinlera906c942019-10-08 13:42:05 -0500155{
156 pel << _type << _size << _flags;
157
158 if (hasPN() || hasMP())
159 {
160 pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size());
161 }
162
163 if (hasCCIN())
164 {
165 pel.write(_ccin.data(), _ccin.size());
166 }
167
168 if (hasSN())
169 {
170 pel.write(_sn.data(), _sn.size());
171 }
172}
173
Matt Spinlerba0ee002020-03-13 11:24:14 -0500174void FRUIdentity::setPartNumber(const std::string& partNumber)
175{
176 _flags |= pnSupplied;
177 _flags &= ~maintProcSupplied;
178
179 auto pn = partNumber;
180
181 // Strip leading whitespace on this one.
182 while (' ' == pn.front())
183 {
184 pn = pn.substr(1);
185 }
186
187 // Note: strncpy only writes NULLs if pn short
188 strncpy(_pnOrProcedureID.data(), pn.c_str(), _pnOrProcedureID.size());
189
190 // ensure null terminated
191 _pnOrProcedureID.back() = 0;
192}
193
194void FRUIdentity::setCCIN(const std::string& ccin)
195{
196 _flags |= ccinSupplied;
197
198 // Note: _ccin not null terminated, though strncpy writes NULLs if short
199 strncpy(_ccin.data(), ccin.c_str(), _ccin.size());
200}
201
202void FRUIdentity::setSerialNumber(const std::string& serialNumber)
203{
204 _flags |= snSupplied;
205
206 // Note: _sn not null terminated, though strncpy writes NULLs if short
207 strncpy(_sn.data(), serialNumber.c_str(), _sn.size());
208}
209
Matt Spinlera27e2e52020-04-09 11:06:11 -0500210void FRUIdentity::setMaintenanceProcedure(
211 const std::string& procedureFromRegistry)
Matt Spinlerba0ee002020-03-13 11:24:14 -0500212{
213 _flags |= maintProcSupplied;
214 _flags &= ~pnSupplied;
215
Matt Spinlera27e2e52020-04-09 11:06:11 -0500216 if (pel_values::maintenanceProcedures.count(procedureFromRegistry))
217 {
218 strncpy(
219 _pnOrProcedureID.data(),
220 pel_values::maintenanceProcedures.at(procedureFromRegistry).c_str(),
Matt Spinlerba0ee002020-03-13 11:24:14 -0500221 _pnOrProcedureID.size());
Matt Spinlera27e2e52020-04-09 11:06:11 -0500222 }
223 else
224 {
225 log<level::ERR>("Invalid maintenance procedure",
226 entry("PROCEDURE=%s", procedureFromRegistry.c_str()));
227 strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
228 }
Matt Spinlerba0ee002020-03-13 11:24:14 -0500229
230 // ensure null terminated
231 _pnOrProcedureID.back() = 0;
232}
233
Matt Spinlera906c942019-10-08 13:42:05 -0500234} // namespace src
235} // namespace pels
236} // namespace openpower