blob: f76382b5844881c448d0025816e7747259599eca [file] [log] [blame]
Alexander Hansen40fb5492025-10-28 17:56:12 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2019 IBM Corporation
3
Matt Spinler6c9662c2019-10-09 11:27:20 -05004#include "callout.hpp"
5
Arya K Padman5bc26532024-04-10 06:19:25 -05006#include <phosphor-logging/lg2.hpp>
7
8#include <map>
Matt Spinler6c9662c2019-10-09 11:27:20 -05009
10namespace openpower
11{
12namespace pels
13{
14namespace src
15{
16
Matt Spinler0a5d10c2020-03-13 12:54:02 -050017constexpr size_t locationCodeMaxSize = 80;
18
Matt Spinler6c9662c2019-10-09 11:27:20 -050019Callout::Callout(Stream& pel)
20{
21 pel >> _size >> _flags >> _priority >> _locationCodeSize;
22
23 if (_locationCodeSize)
24 {
25 _locationCode.resize(_locationCodeSize);
26 pel >> _locationCode;
27 }
28
29 size_t currentSize = 4 + _locationCodeSize;
30
31 // Read in the substructures until the end of this structure.
32 // Any stream overflows will throw an exception up to the SRC constructor
33 while (_size > currentSize)
34 {
35 // Peek the type
36 uint16_t type = 0;
37 pel >> type;
38 pel.offset(pel.offset() - 2);
39
40 switch (type)
41 {
42 case FRUIdentity::substructureType:
43 {
44 _fruIdentity = std::make_unique<FRUIdentity>(pel);
45 currentSize += _fruIdentity->flattenedSize();
46 break;
47 }
48 case PCEIdentity::substructureType:
49 {
50 _pceIdentity = std::make_unique<PCEIdentity>(pel);
51 currentSize += _pceIdentity->flattenedSize();
52 break;
53 }
54 case MRU::substructureType:
55 {
56 _mru = std::make_unique<MRU>(pel);
57 currentSize += _mru->flattenedSize();
58 break;
59 }
60 default:
Arya K Padman5bc26532024-04-10 06:19:25 -050061 lg2::error("Invalid Callout subsection type {CALLOUT_TYPE}",
62 "CALLOUT_TYPE", lg2::hex, type);
Matt Spinler6c9662c2019-10-09 11:27:20 -050063 throw std::runtime_error("Invalid Callout subsection type");
64 break;
65 }
66 }
67}
68
Matt Spinler0a5d10c2020-03-13 12:54:02 -050069Callout::Callout(CalloutPriority priority, const std::string& locationCode,
70 const std::string& partNumber, const std::string& ccin,
Matt Spinler5ab39972020-08-13 13:02:28 -050071 const std::string& serialNumber) :
72 Callout(priority, locationCode, partNumber, ccin, serialNumber,
73 std::vector<MRU::MRUCallout>{})
Patrick Williams2544b412022-10-04 08:41:06 -050074{}
Matt Spinler5ab39972020-08-13 13:02:28 -050075
76Callout::Callout(CalloutPriority priority, const std::string& locationCode,
77 const std::string& partNumber, const std::string& ccin,
78 const std::string& serialNumber,
79 const std::vector<MRU::MRUCallout>& mrus)
Matt Spinler0a5d10c2020-03-13 12:54:02 -050080{
81 _flags = calloutType | fruIdentIncluded;
82
83 _priority = static_cast<uint8_t>(priority);
84
85 setLocationCode(locationCode);
86
Patrick Williams075c7922024-08-16 15:19:49 -040087 _fruIdentity =
88 std::make_unique<FRUIdentity>(partNumber, ccin, serialNumber);
Matt Spinler0a5d10c2020-03-13 12:54:02 -050089
Matt Spinler5ab39972020-08-13 13:02:28 -050090 if (!mrus.empty())
91 {
92 _flags |= mruIncluded;
93 _mru = std::make_unique<MRU>(mrus);
94 }
95
Matt Spinler0a5d10c2020-03-13 12:54:02 -050096 _size = flattenedSize();
97}
98
Matt Spinler468aab52020-08-13 11:04:31 -050099Callout::Callout(CalloutPriority priority, const std::string& procedure,
100 CalloutValueType type)
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500101{
102 _flags = calloutType | fruIdentIncluded;
103
104 _priority = static_cast<uint8_t>(priority);
105
106 _locationCodeSize = 0;
107
Matt Spinler468aab52020-08-13 11:04:31 -0500108 _fruIdentity = std::make_unique<FRUIdentity>(procedure, type);
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500109
110 _size = flattenedSize();
111}
112
Matt Spinler468aab52020-08-13 11:04:31 -0500113Callout::Callout(CalloutPriority priority, const std::string& symbolicFRU,
114 CalloutValueType type, const std::string& locationCode,
115 bool trustedLocationCode)
Matt Spinlera86ec992020-04-09 12:42:07 -0500116{
117 _flags = calloutType | fruIdentIncluded;
118
119 _priority = static_cast<uint8_t>(priority);
120
121 setLocationCode(locationCode);
122
Patrick Williams075c7922024-08-16 15:19:49 -0400123 _fruIdentity =
124 std::make_unique<FRUIdentity>(symbolicFRU, type, trustedLocationCode);
Matt Spinlera86ec992020-04-09 12:42:07 -0500125
126 _size = flattenedSize();
127}
128
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500129void Callout::setLocationCode(const std::string& locationCode)
130{
131 if (locationCode.empty())
132 {
133 _locationCodeSize = 0;
134 return;
135 }
136
137 std::copy(locationCode.begin(), locationCode.end(),
138 std::back_inserter(_locationCode));
139
140 if (_locationCode.size() < locationCodeMaxSize)
141 {
142 // Add a NULL, and then pad to a 4B boundary
143 _locationCode.push_back('\0');
144
145 while (_locationCode.size() % 4)
146 {
147 _locationCode.push_back('\0');
148 }
149 }
150 else
151 {
152 // Too big - truncate it and ensure it ends in a NULL.
153 _locationCode.resize(locationCodeMaxSize);
154 _locationCode.back() = '\0';
155 }
156
157 _locationCodeSize = _locationCode.size();
158}
159
160size_t Callout::flattenedSize() const
Matt Spinler6c9662c2019-10-09 11:27:20 -0500161{
162 size_t size = sizeof(_size) + sizeof(_flags) + sizeof(_priority) +
163 sizeof(_locationCodeSize) + _locationCodeSize;
164
165 size += _fruIdentity ? _fruIdentity->flattenedSize() : 0;
166 size += _pceIdentity ? _pceIdentity->flattenedSize() : 0;
167 size += _mru ? _mru->flattenedSize() : 0;
168
169 return size;
170}
171
Matt Spinler724d0d82019-11-06 10:05:36 -0600172void Callout::flatten(Stream& pel) const
Matt Spinler6c9662c2019-10-09 11:27:20 -0500173{
174 pel << _size << _flags << _priority << _locationCodeSize;
175
176 if (_locationCodeSize)
177 {
178 pel << _locationCode;
179 }
180
181 if (_fruIdentity)
182 {
183 _fruIdentity->flatten(pel);
184 }
185
186 if (_pceIdentity)
187 {
188 _pceIdentity->flatten(pel);
189 }
190 if (_mru)
191 {
192 _mru->flatten(pel);
193 }
194}
195
Matt Spinler4efed0e2024-02-26 11:16:07 -0600196bool Callout::operator==(const Callout& right) const
197{
198 if ((_locationCodeSize != 0) || (right.locationCodeSize() != 0))
199 {
200 return locationCode() == right.locationCode();
201 }
202
203 if (!_fruIdentity || !right.fruIdentity())
204 {
205 return false;
206 }
207
208 auto myProc = _fruIdentity->getMaintProc();
209 auto otherProc = right.fruIdentity()->getMaintProc();
210 if (myProc)
211 {
212 if (otherProc)
213 {
214 return *myProc == *otherProc;
215 }
216 return false;
217 }
218
219 auto myPN = _fruIdentity->getPN();
220 auto otherPN = right.fruIdentity()->getPN();
221 if (myPN && otherPN)
222 {
223 return *myPN == *otherPN;
224 }
225
226 return false;
227}
228
229bool Callout::operator>(const Callout& right) const
230{
231 // Treat all of the mediums the same
232 const std::map<std::uint8_t, int> priorities = {
233 {'H', 10}, {'M', 9}, {'A', 9}, {'B', 9}, {'C', 9}, {'L', 8}};
234
235 if (!priorities.contains(priority()) ||
236 !priorities.contains(right.priority()))
237 {
238 return false;
239 }
240
241 return priorities.at(priority()) > priorities.at(right.priority());
242}
243
Matt Spinler6c9662c2019-10-09 11:27:20 -0500244} // namespace src
245} // namespace pels
246} // namespace openpower