blob: f54d77ef0e299daad41cdaa7ce106907ce3f1ee0 [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
Matt Spinler7f1b9052022-03-22 09:18:58 -050018#include <phosphor-logging/log.hpp>
Matt Spinler6c9662c2019-10-09 11:27:20 -050019
20namespace openpower
21{
22namespace pels
23{
24namespace src
25{
26
Matt Spinler7f1b9052022-03-22 09:18:58 -050027using namespace phosphor::logging;
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:
Matt Spinler7f1b9052022-03-22 09:18:58 -050073 log<level::ERR>("Invalid Callout subsection type",
74 entry("CALLOUT_TYPE=0x%X", 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>{})
86{
87}
88
89Callout::Callout(CalloutPriority priority, const std::string& locationCode,
90 const std::string& partNumber, const std::string& ccin,
91 const std::string& serialNumber,
92 const std::vector<MRU::MRUCallout>& mrus)
Matt Spinler0a5d10c2020-03-13 12:54:02 -050093{
94 _flags = calloutType | fruIdentIncluded;
95
96 _priority = static_cast<uint8_t>(priority);
97
98 setLocationCode(locationCode);
99
100 _fruIdentity =
101 std::make_unique<FRUIdentity>(partNumber, ccin, serialNumber);
102
Matt Spinler5ab39972020-08-13 13:02:28 -0500103 if (!mrus.empty())
104 {
105 _flags |= mruIncluded;
106 _mru = std::make_unique<MRU>(mrus);
107 }
108
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500109 _size = flattenedSize();
110}
111
Matt Spinler468aab52020-08-13 11:04:31 -0500112Callout::Callout(CalloutPriority priority, const std::string& procedure,
113 CalloutValueType type)
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500114{
115 _flags = calloutType | fruIdentIncluded;
116
117 _priority = static_cast<uint8_t>(priority);
118
119 _locationCodeSize = 0;
120
Matt Spinler468aab52020-08-13 11:04:31 -0500121 _fruIdentity = std::make_unique<FRUIdentity>(procedure, type);
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500122
123 _size = flattenedSize();
124}
125
Matt Spinler468aab52020-08-13 11:04:31 -0500126Callout::Callout(CalloutPriority priority, const std::string& symbolicFRU,
127 CalloutValueType type, const std::string& locationCode,
128 bool trustedLocationCode)
Matt Spinlera86ec992020-04-09 12:42:07 -0500129{
130 _flags = calloutType | fruIdentIncluded;
131
132 _priority = static_cast<uint8_t>(priority);
133
134 setLocationCode(locationCode);
135
Matt Spinler468aab52020-08-13 11:04:31 -0500136 _fruIdentity =
137 std::make_unique<FRUIdentity>(symbolicFRU, type, trustedLocationCode);
Matt Spinlera86ec992020-04-09 12:42:07 -0500138
139 _size = flattenedSize();
140}
141
Matt Spinler0a5d10c2020-03-13 12:54:02 -0500142void Callout::setLocationCode(const std::string& locationCode)
143{
144 if (locationCode.empty())
145 {
146 _locationCodeSize = 0;
147 return;
148 }
149
150 std::copy(locationCode.begin(), locationCode.end(),
151 std::back_inserter(_locationCode));
152
153 if (_locationCode.size() < locationCodeMaxSize)
154 {
155 // Add a NULL, and then pad to a 4B boundary
156 _locationCode.push_back('\0');
157
158 while (_locationCode.size() % 4)
159 {
160 _locationCode.push_back('\0');
161 }
162 }
163 else
164 {
165 // Too big - truncate it and ensure it ends in a NULL.
166 _locationCode.resize(locationCodeMaxSize);
167 _locationCode.back() = '\0';
168 }
169
170 _locationCodeSize = _locationCode.size();
171}
172
173size_t Callout::flattenedSize() const
Matt Spinler6c9662c2019-10-09 11:27:20 -0500174{
175 size_t size = sizeof(_size) + sizeof(_flags) + sizeof(_priority) +
176 sizeof(_locationCodeSize) + _locationCodeSize;
177
178 size += _fruIdentity ? _fruIdentity->flattenedSize() : 0;
179 size += _pceIdentity ? _pceIdentity->flattenedSize() : 0;
180 size += _mru ? _mru->flattenedSize() : 0;
181
182 return size;
183}
184
Matt Spinler724d0d82019-11-06 10:05:36 -0600185void Callout::flatten(Stream& pel) const
Matt Spinler6c9662c2019-10-09 11:27:20 -0500186{
187 pel << _size << _flags << _priority << _locationCodeSize;
188
189 if (_locationCodeSize)
190 {
191 pel << _locationCode;
192 }
193
194 if (_fruIdentity)
195 {
196 _fruIdentity->flatten(pel);
197 }
198
199 if (_pceIdentity)
200 {
201 _pceIdentity->flatten(pel);
202 }
203 if (_mru)
204 {
205 _mru->flatten(pel);
206 }
207}
208
209} // namespace src
210} // namespace pels
211} // namespace openpower