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 */
166c9662c9SMatt Spinler #include "callout.hpp"
176c9662c9SMatt Spinler
185bc26533SArya K Padman #include <phosphor-logging/lg2.hpp>
195bc26533SArya K Padman
205bc26533SArya K Padman #include <map>
216c9662c9SMatt Spinler
226c9662c9SMatt Spinler namespace openpower
236c9662c9SMatt Spinler {
246c9662c9SMatt Spinler namespace pels
256c9662c9SMatt Spinler {
266c9662c9SMatt Spinler namespace src
276c9662c9SMatt Spinler {
286c9662c9SMatt Spinler
290a5d10ceSMatt Spinler constexpr size_t locationCodeMaxSize = 80;
300a5d10ceSMatt Spinler
Callout(Stream & pel)316c9662c9SMatt Spinler Callout::Callout(Stream& pel)
326c9662c9SMatt Spinler {
336c9662c9SMatt Spinler pel >> _size >> _flags >> _priority >> _locationCodeSize;
346c9662c9SMatt Spinler
356c9662c9SMatt Spinler if (_locationCodeSize)
366c9662c9SMatt Spinler {
376c9662c9SMatt Spinler _locationCode.resize(_locationCodeSize);
386c9662c9SMatt Spinler pel >> _locationCode;
396c9662c9SMatt Spinler }
406c9662c9SMatt Spinler
416c9662c9SMatt Spinler size_t currentSize = 4 + _locationCodeSize;
426c9662c9SMatt Spinler
436c9662c9SMatt Spinler // Read in the substructures until the end of this structure.
446c9662c9SMatt Spinler // Any stream overflows will throw an exception up to the SRC constructor
456c9662c9SMatt Spinler while (_size > currentSize)
466c9662c9SMatt Spinler {
476c9662c9SMatt Spinler // Peek the type
486c9662c9SMatt Spinler uint16_t type = 0;
496c9662c9SMatt Spinler pel >> type;
506c9662c9SMatt Spinler pel.offset(pel.offset() - 2);
516c9662c9SMatt Spinler
526c9662c9SMatt Spinler switch (type)
536c9662c9SMatt Spinler {
546c9662c9SMatt Spinler case FRUIdentity::substructureType:
556c9662c9SMatt Spinler {
566c9662c9SMatt Spinler _fruIdentity = std::make_unique<FRUIdentity>(pel);
576c9662c9SMatt Spinler currentSize += _fruIdentity->flattenedSize();
586c9662c9SMatt Spinler break;
596c9662c9SMatt Spinler }
606c9662c9SMatt Spinler case PCEIdentity::substructureType:
616c9662c9SMatt Spinler {
626c9662c9SMatt Spinler _pceIdentity = std::make_unique<PCEIdentity>(pel);
636c9662c9SMatt Spinler currentSize += _pceIdentity->flattenedSize();
646c9662c9SMatt Spinler break;
656c9662c9SMatt Spinler }
666c9662c9SMatt Spinler case MRU::substructureType:
676c9662c9SMatt Spinler {
686c9662c9SMatt Spinler _mru = std::make_unique<MRU>(pel);
696c9662c9SMatt Spinler currentSize += _mru->flattenedSize();
706c9662c9SMatt Spinler break;
716c9662c9SMatt Spinler }
726c9662c9SMatt Spinler default:
735bc26533SArya K Padman lg2::error("Invalid Callout subsection type {CALLOUT_TYPE}",
745bc26533SArya K Padman "CALLOUT_TYPE", lg2::hex, type);
756c9662c9SMatt Spinler throw std::runtime_error("Invalid Callout subsection type");
766c9662c9SMatt Spinler break;
776c9662c9SMatt Spinler }
786c9662c9SMatt Spinler }
796c9662c9SMatt Spinler }
806c9662c9SMatt Spinler
Callout(CalloutPriority priority,const std::string & locationCode,const std::string & partNumber,const std::string & ccin,const std::string & serialNumber)810a5d10ceSMatt Spinler Callout::Callout(CalloutPriority priority, const std::string& locationCode,
820a5d10ceSMatt Spinler const std::string& partNumber, const std::string& ccin,
835ab39978SMatt Spinler const std::string& serialNumber) :
845ab39978SMatt Spinler Callout(priority, locationCode, partNumber, ccin, serialNumber,
855ab39978SMatt Spinler std::vector<MRU::MRUCallout>{})
862544b419SPatrick Williams {}
875ab39978SMatt Spinler
Callout(CalloutPriority priority,const std::string & locationCode,const std::string & partNumber,const std::string & ccin,const std::string & serialNumber,const std::vector<MRU::MRUCallout> & mrus)885ab39978SMatt Spinler Callout::Callout(CalloutPriority priority, const std::string& locationCode,
895ab39978SMatt Spinler const std::string& partNumber, const std::string& ccin,
905ab39978SMatt Spinler const std::string& serialNumber,
915ab39978SMatt Spinler const std::vector<MRU::MRUCallout>& mrus)
920a5d10ceSMatt Spinler {
930a5d10ceSMatt Spinler _flags = calloutType | fruIdentIncluded;
940a5d10ceSMatt Spinler
950a5d10ceSMatt Spinler _priority = static_cast<uint8_t>(priority);
960a5d10ceSMatt Spinler
970a5d10ceSMatt Spinler setLocationCode(locationCode);
980a5d10ceSMatt Spinler
99*075c7923SPatrick Williams _fruIdentity =
100*075c7923SPatrick Williams std::make_unique<FRUIdentity>(partNumber, ccin, serialNumber);
1010a5d10ceSMatt Spinler
1025ab39978SMatt Spinler if (!mrus.empty())
1035ab39978SMatt Spinler {
1045ab39978SMatt Spinler _flags |= mruIncluded;
1055ab39978SMatt Spinler _mru = std::make_unique<MRU>(mrus);
1065ab39978SMatt Spinler }
1075ab39978SMatt Spinler
1080a5d10ceSMatt Spinler _size = flattenedSize();
1090a5d10ceSMatt Spinler }
1100a5d10ceSMatt Spinler
Callout(CalloutPriority priority,const std::string & procedure,CalloutValueType type)111468aab5fSMatt Spinler Callout::Callout(CalloutPriority priority, const std::string& procedure,
112468aab5fSMatt Spinler CalloutValueType type)
1130a5d10ceSMatt Spinler {
1140a5d10ceSMatt Spinler _flags = calloutType | fruIdentIncluded;
1150a5d10ceSMatt Spinler
1160a5d10ceSMatt Spinler _priority = static_cast<uint8_t>(priority);
1170a5d10ceSMatt Spinler
1180a5d10ceSMatt Spinler _locationCodeSize = 0;
1190a5d10ceSMatt Spinler
120468aab5fSMatt Spinler _fruIdentity = std::make_unique<FRUIdentity>(procedure, type);
1210a5d10ceSMatt Spinler
1220a5d10ceSMatt Spinler _size = flattenedSize();
1230a5d10ceSMatt Spinler }
1240a5d10ceSMatt Spinler
Callout(CalloutPriority priority,const std::string & symbolicFRU,CalloutValueType type,const std::string & locationCode,bool trustedLocationCode)125468aab5fSMatt Spinler Callout::Callout(CalloutPriority priority, const std::string& symbolicFRU,
126468aab5fSMatt Spinler CalloutValueType type, const std::string& locationCode,
127468aab5fSMatt Spinler bool trustedLocationCode)
128a86ec996SMatt Spinler {
129a86ec996SMatt Spinler _flags = calloutType | fruIdentIncluded;
130a86ec996SMatt Spinler
131a86ec996SMatt Spinler _priority = static_cast<uint8_t>(priority);
132a86ec996SMatt Spinler
133a86ec996SMatt Spinler setLocationCode(locationCode);
134a86ec996SMatt Spinler
135*075c7923SPatrick Williams _fruIdentity =
136*075c7923SPatrick Williams std::make_unique<FRUIdentity>(symbolicFRU, type, trustedLocationCode);
137a86ec996SMatt Spinler
138a86ec996SMatt Spinler _size = flattenedSize();
139a86ec996SMatt Spinler }
140a86ec996SMatt Spinler
setLocationCode(const std::string & locationCode)1410a5d10ceSMatt Spinler void Callout::setLocationCode(const std::string& locationCode)
1420a5d10ceSMatt Spinler {
1430a5d10ceSMatt Spinler if (locationCode.empty())
1440a5d10ceSMatt Spinler {
1450a5d10ceSMatt Spinler _locationCodeSize = 0;
1460a5d10ceSMatt Spinler return;
1470a5d10ceSMatt Spinler }
1480a5d10ceSMatt Spinler
1490a5d10ceSMatt Spinler std::copy(locationCode.begin(), locationCode.end(),
1500a5d10ceSMatt Spinler std::back_inserter(_locationCode));
1510a5d10ceSMatt Spinler
1520a5d10ceSMatt Spinler if (_locationCode.size() < locationCodeMaxSize)
1530a5d10ceSMatt Spinler {
1540a5d10ceSMatt Spinler // Add a NULL, and then pad to a 4B boundary
1550a5d10ceSMatt Spinler _locationCode.push_back('\0');
1560a5d10ceSMatt Spinler
1570a5d10ceSMatt Spinler while (_locationCode.size() % 4)
1580a5d10ceSMatt Spinler {
1590a5d10ceSMatt Spinler _locationCode.push_back('\0');
1600a5d10ceSMatt Spinler }
1610a5d10ceSMatt Spinler }
1620a5d10ceSMatt Spinler else
1630a5d10ceSMatt Spinler {
1640a5d10ceSMatt Spinler // Too big - truncate it and ensure it ends in a NULL.
1650a5d10ceSMatt Spinler _locationCode.resize(locationCodeMaxSize);
1660a5d10ceSMatt Spinler _locationCode.back() = '\0';
1670a5d10ceSMatt Spinler }
1680a5d10ceSMatt Spinler
1690a5d10ceSMatt Spinler _locationCodeSize = _locationCode.size();
1700a5d10ceSMatt Spinler }
1710a5d10ceSMatt Spinler
flattenedSize() const1720a5d10ceSMatt Spinler size_t Callout::flattenedSize() const
1736c9662c9SMatt Spinler {
1746c9662c9SMatt Spinler size_t size = sizeof(_size) + sizeof(_flags) + sizeof(_priority) +
1756c9662c9SMatt Spinler sizeof(_locationCodeSize) + _locationCodeSize;
1766c9662c9SMatt Spinler
1776c9662c9SMatt Spinler size += _fruIdentity ? _fruIdentity->flattenedSize() : 0;
1786c9662c9SMatt Spinler size += _pceIdentity ? _pceIdentity->flattenedSize() : 0;
1796c9662c9SMatt Spinler size += _mru ? _mru->flattenedSize() : 0;
1806c9662c9SMatt Spinler
1816c9662c9SMatt Spinler return size;
1826c9662c9SMatt Spinler }
1836c9662c9SMatt Spinler
flatten(Stream & pel) const184724d0d8cSMatt Spinler void Callout::flatten(Stream& pel) const
1856c9662c9SMatt Spinler {
1866c9662c9SMatt Spinler pel << _size << _flags << _priority << _locationCodeSize;
1876c9662c9SMatt Spinler
1886c9662c9SMatt Spinler if (_locationCodeSize)
1896c9662c9SMatt Spinler {
1906c9662c9SMatt Spinler pel << _locationCode;
1916c9662c9SMatt Spinler }
1926c9662c9SMatt Spinler
1936c9662c9SMatt Spinler if (_fruIdentity)
1946c9662c9SMatt Spinler {
1956c9662c9SMatt Spinler _fruIdentity->flatten(pel);
1966c9662c9SMatt Spinler }
1976c9662c9SMatt Spinler
1986c9662c9SMatt Spinler if (_pceIdentity)
1996c9662c9SMatt Spinler {
2006c9662c9SMatt Spinler _pceIdentity->flatten(pel);
2016c9662c9SMatt Spinler }
2026c9662c9SMatt Spinler if (_mru)
2036c9662c9SMatt Spinler {
2046c9662c9SMatt Spinler _mru->flatten(pel);
2056c9662c9SMatt Spinler }
2066c9662c9SMatt Spinler }
2076c9662c9SMatt Spinler
operator ==(const Callout & right) const2084efed0efSMatt Spinler bool Callout::operator==(const Callout& right) const
2094efed0efSMatt Spinler {
2104efed0efSMatt Spinler if ((_locationCodeSize != 0) || (right.locationCodeSize() != 0))
2114efed0efSMatt Spinler {
2124efed0efSMatt Spinler return locationCode() == right.locationCode();
2134efed0efSMatt Spinler }
2144efed0efSMatt Spinler
2154efed0efSMatt Spinler if (!_fruIdentity || !right.fruIdentity())
2164efed0efSMatt Spinler {
2174efed0efSMatt Spinler return false;
2184efed0efSMatt Spinler }
2194efed0efSMatt Spinler
2204efed0efSMatt Spinler auto myProc = _fruIdentity->getMaintProc();
2214efed0efSMatt Spinler auto otherProc = right.fruIdentity()->getMaintProc();
2224efed0efSMatt Spinler if (myProc)
2234efed0efSMatt Spinler {
2244efed0efSMatt Spinler if (otherProc)
2254efed0efSMatt Spinler {
2264efed0efSMatt Spinler return *myProc == *otherProc;
2274efed0efSMatt Spinler }
2284efed0efSMatt Spinler return false;
2294efed0efSMatt Spinler }
2304efed0efSMatt Spinler
2314efed0efSMatt Spinler auto myPN = _fruIdentity->getPN();
2324efed0efSMatt Spinler auto otherPN = right.fruIdentity()->getPN();
2334efed0efSMatt Spinler if (myPN && otherPN)
2344efed0efSMatt Spinler {
2354efed0efSMatt Spinler return *myPN == *otherPN;
2364efed0efSMatt Spinler }
2374efed0efSMatt Spinler
2384efed0efSMatt Spinler return false;
2394efed0efSMatt Spinler }
2404efed0efSMatt Spinler
operator >(const Callout & right) const2414efed0efSMatt Spinler bool Callout::operator>(const Callout& right) const
2424efed0efSMatt Spinler {
2434efed0efSMatt Spinler // Treat all of the mediums the same
2444efed0efSMatt Spinler const std::map<std::uint8_t, int> priorities = {
2454efed0efSMatt Spinler {'H', 10}, {'M', 9}, {'A', 9}, {'B', 9}, {'C', 9}, {'L', 8}};
2464efed0efSMatt Spinler
2474efed0efSMatt Spinler if (!priorities.contains(priority()) ||
2484efed0efSMatt Spinler !priorities.contains(right.priority()))
2494efed0efSMatt Spinler {
2504efed0efSMatt Spinler return false;
2514efed0efSMatt Spinler }
2524efed0efSMatt Spinler
2534efed0efSMatt Spinler return priorities.at(priority()) > priorities.at(right.priority());
2544efed0efSMatt Spinler }
2554efed0efSMatt Spinler
2566c9662c9SMatt Spinler } // namespace src
2576c9662c9SMatt Spinler } // namespace pels
2586c9662c9SMatt Spinler } // namespace openpower
259