xref: /openbmc/phosphor-logging/extensions/openpower-pels/callout.cpp (revision 075c79237505ea3b810a461f5f514e4d520a0c44)
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