blob: dfc08bde51bb194bf7435703376cd75ac09ce654 [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 Spinler6c9662c2019-10-09 11:27:20 -050016#include "callout.hpp"
17
Arya K Padman5bc26532024-04-10 06:19:25 -050018#include <phosphor-logging/lg2.hpp>
19
20#include <map>
Matt Spinler6c9662c2019-10-09 11:27:20 -050021
22namespace openpower
23{
24namespace pels
25{
26namespace src
27{
28
Matt Spinler0a5d10c2020-03-13 12:54:02 -050029constexpr size_t locationCodeMaxSize = 80;
30
Matt Spinler6c9662c2019-10-09 11:27:20 -050031Callout::Callout(Stream& pel)
32{
33 pel >> _size >> _flags >> _priority >> _locationCodeSize;
34
35 if (_locationCodeSize)
36 {
37 _locationCode.resize(_locationCodeSize);
38 pel >> _locationCode;
39 }
40
41 size_t currentSize = 4 + _locationCodeSize;
42
43 // Read in the substructures until the end of this structure.
44 // Any stream overflows will throw an exception up to the SRC constructor
45 while (_size > currentSize)
46 {
47 // Peek the type
48 uint16_t type = 0;
49 pel >> type;
50 pel.offset(pel.offset() - 2);
51
52 switch (type)
53 {
54 case FRUIdentity::substructureType:
55 {
56 _fruIdentity = std::make_unique<FRUIdentity>(pel);
57 currentSize += _fruIdentity->flattenedSize();
58 break;
59 }
60 case PCEIdentity::substructureType:
61 {
62 _pceIdentity = std::make_unique<PCEIdentity>(pel);
63 currentSize += _pceIdentity->flattenedSize();
64 break;
65 }
66 case MRU::substructureType:
67 {
68 _mru = std::make_unique<MRU>(pel);
69 currentSize += _mru->flattenedSize();
70 break;
71 }
72 default:
Arya K Padman5bc26532024-04-10 06:19:25 -050073 lg2::error("Invalid Callout subsection type {CALLOUT_TYPE}",
74 "CALLOUT_TYPE", lg2::hex, type);
Matt Spinler6c9662c2019-10-09 11:27:20 -050075 throw std::runtime_error("Invalid Callout subsection type");
76 break;
77 }
78 }
79}
80
Matt Spinler0a5d10c2020-03-13 12:54:02 -050081Callout::Callout(CalloutPriority priority, const std::string& locationCode,
82 const std::string& partNumber, const std::string& ccin,
Matt Spinler5ab39972020-08-13 13:02:28 -050083 const std::string& serialNumber) :
84 Callout(priority, locationCode, partNumber, ccin, serialNumber,
85 std::vector<MRU::MRUCallout>{})
Patrick Williams2544b412022-10-04 08:41:06 -050086{}
Matt Spinler5ab39972020-08-13 13:02:28 -050087
88Callout::Callout(CalloutPriority priority, const std::string& locationCode,
89 const std::string& partNumber, const std::string& ccin,
90 const std::string& serialNumber,
91 const std::vector<MRU::MRUCallout>& mrus)
Matt Spinler0a5d10c2020-03-13 12:54:02 -050092{
93 _flags = calloutType | fruIdentIncluded;
94
95 _priority = static_cast<uint8_t>(priority);
96
97 setLocationCode(locationCode);
98
Patrick Williams2544b412022-10-04 08:41:06 -050099 _fruIdentity = std::make_unique<FRUIdentity>(partNumber, ccin,
100 serialNumber);
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500101
Matt Spinler5ab39972020-08-13 13:02:28 -0500102 if (!mrus.empty())
103 {
104 _flags |= mruIncluded;
105 _mru = std::make_unique<MRU>(mrus);
106 }
107
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500108 _size = flattenedSize();
109}
110
Matt Spinler468aab52020-08-13 11:04:31 -0500111Callout::Callout(CalloutPriority priority, const std::string& procedure,
112 CalloutValueType type)
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500113{
114 _flags = calloutType | fruIdentIncluded;
115
116 _priority = static_cast<uint8_t>(priority);
117
118 _locationCodeSize = 0;
119
Matt Spinler468aab52020-08-13 11:04:31 -0500120 _fruIdentity = std::make_unique<FRUIdentity>(procedure, type);
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500121
122 _size = flattenedSize();
123}
124
Matt Spinler468aab52020-08-13 11:04:31 -0500125Callout::Callout(CalloutPriority priority, const std::string& symbolicFRU,
126 CalloutValueType type, const std::string& locationCode,
127 bool trustedLocationCode)
Matt Spinlera86ec992020-04-09 12:42:07 -0500128{
129 _flags = calloutType | fruIdentIncluded;
130
131 _priority = static_cast<uint8_t>(priority);
132
133 setLocationCode(locationCode);
134
Patrick Williams2544b412022-10-04 08:41:06 -0500135 _fruIdentity = std::make_unique<FRUIdentity>(symbolicFRU, type,
136 trustedLocationCode);
Matt Spinlera86ec992020-04-09 12:42:07 -0500137
138 _size = flattenedSize();
139}
140
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500141void Callout::setLocationCode(const std::string& locationCode)
142{
143 if (locationCode.empty())
144 {
145 _locationCodeSize = 0;
146 return;
147 }
148
149 std::copy(locationCode.begin(), locationCode.end(),
150 std::back_inserter(_locationCode));
151
152 if (_locationCode.size() < locationCodeMaxSize)
153 {
154 // Add a NULL, and then pad to a 4B boundary
155 _locationCode.push_back('\0');
156
157 while (_locationCode.size() % 4)
158 {
159 _locationCode.push_back('\0');
160 }
161 }
162 else
163 {
164 // Too big - truncate it and ensure it ends in a NULL.
165 _locationCode.resize(locationCodeMaxSize);
166 _locationCode.back() = '\0';
167 }
168
169 _locationCodeSize = _locationCode.size();
170}
171
172size_t Callout::flattenedSize() const
Matt Spinler6c9662c2019-10-09 11:27:20 -0500173{
174 size_t size = sizeof(_size) + sizeof(_flags) + sizeof(_priority) +
175 sizeof(_locationCodeSize) + _locationCodeSize;
176
177 size += _fruIdentity ? _fruIdentity->flattenedSize() : 0;
178 size += _pceIdentity ? _pceIdentity->flattenedSize() : 0;
179 size += _mru ? _mru->flattenedSize() : 0;
180
181 return size;
182}
183
Matt Spinler724d0d82019-11-06 10:05:36 -0600184void Callout::flatten(Stream& pel) const
Matt Spinler6c9662c2019-10-09 11:27:20 -0500185{
186 pel << _size << _flags << _priority << _locationCodeSize;
187
188 if (_locationCodeSize)
189 {
190 pel << _locationCode;
191 }
192
193 if (_fruIdentity)
194 {
195 _fruIdentity->flatten(pel);
196 }
197
198 if (_pceIdentity)
199 {
200 _pceIdentity->flatten(pel);
201 }
202 if (_mru)
203 {
204 _mru->flatten(pel);
205 }
206}
207
Matt Spinler4efed0e2024-02-26 11:16:07 -0600208bool Callout::operator==(const Callout& right) const
209{
210 if ((_locationCodeSize != 0) || (right.locationCodeSize() != 0))
211 {
212 return locationCode() == right.locationCode();
213 }
214
215 if (!_fruIdentity || !right.fruIdentity())
216 {
217 return false;
218 }
219
220 auto myProc = _fruIdentity->getMaintProc();
221 auto otherProc = right.fruIdentity()->getMaintProc();
222 if (myProc)
223 {
224 if (otherProc)
225 {
226 return *myProc == *otherProc;
227 }
228 return false;
229 }
230
231 auto myPN = _fruIdentity->getPN();
232 auto otherPN = right.fruIdentity()->getPN();
233 if (myPN && otherPN)
234 {
235 return *myPN == *otherPN;
236 }
237
238 return false;
239}
240
241bool Callout::operator>(const Callout& right) const
242{
243 // Treat all of the mediums the same
244 const std::map<std::uint8_t, int> priorities = {
245 {'H', 10}, {'M', 9}, {'A', 9}, {'B', 9}, {'C', 9}, {'L', 8}};
246
247 if (!priorities.contains(priority()) ||
248 !priorities.contains(right.priority()))
249 {
250 return false;
251 }
252
253 return priorities.at(priority()) > priorities.at(right.priority());
254}
255
Matt Spinler6c9662c2019-10-09 11:27:20 -0500256} // namespace src
257} // namespace pels
258} // namespace openpower