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 */
16f9bae185SMatt Spinler #include "src.hpp"
17f9bae185SMatt Spinler
18717de428SMatt Spinler #include "device_callouts.hpp"
190f717e10SHarisuddin Mohamed Isa #include "json_utils.hpp"
200f717e10SHarisuddin Mohamed Isa #include "paths.hpp"
210f717e10SHarisuddin Mohamed Isa #include "pel_values.hpp"
22c8d6cc61SHarisuddin Mohamed Isa #ifdef PELTOOL
23c8d6cc61SHarisuddin Mohamed Isa #include <Python.h>
240f717e10SHarisuddin Mohamed Isa
25c8d6cc61SHarisuddin Mohamed Isa #include <nlohmann/json.hpp>
262544b419SPatrick Williams
27c8d6cc61SHarisuddin Mohamed Isa #include <sstream>
28c8d6cc61SHarisuddin Mohamed Isa #endif
290bacc8efSMatt Spinler #include <phosphor-logging/lg2.hpp>
30f9bae185SMatt Spinler
311aa90d49SJayanth Othayoth #include <format>
321aa90d49SJayanth Othayoth
33f9bae185SMatt Spinler namespace openpower
34f9bae185SMatt Spinler {
35f9bae185SMatt Spinler namespace pels
36f9bae185SMatt Spinler {
370f717e10SHarisuddin Mohamed Isa namespace pv = openpower::pels::pel_values;
380f717e10SHarisuddin Mohamed Isa namespace rg = openpower::pels::message;
3985f61a63SMatt Spinler using namespace std::string_literals;
40f9bae185SMatt Spinler
41075e5bafSMatt Spinler constexpr size_t ccinSize = 4;
42075e5bafSMatt Spinler
43c8d6cc61SHarisuddin Mohamed Isa #ifdef PELTOOL
44516935a5SSumit Kumar using orderedJSON = nlohmann::ordered_json;
45c8d6cc61SHarisuddin Mohamed Isa
pyDecRef(PyObject * pyObj)46c8d6cc61SHarisuddin Mohamed Isa void pyDecRef(PyObject* pyObj)
47c8d6cc61SHarisuddin Mohamed Isa {
48c8d6cc61SHarisuddin Mohamed Isa Py_XDECREF(pyObj);
49c8d6cc61SHarisuddin Mohamed Isa }
50c8d6cc61SHarisuddin Mohamed Isa
51c8d6cc61SHarisuddin Mohamed Isa /**
52c8d6cc61SHarisuddin Mohamed Isa * @brief Returns a JSON string to append to SRC section.
53c8d6cc61SHarisuddin Mohamed Isa *
54c8d6cc61SHarisuddin Mohamed Isa * The returning string will contain a JSON object, but without
55c8d6cc61SHarisuddin Mohamed Isa * the outer {}. If the input JSON isn't a JSON object (dict), then
56c8d6cc61SHarisuddin Mohamed Isa * one will be created with the input added to a 'SRC Details' key.
57c8d6cc61SHarisuddin Mohamed Isa *
58c8d6cc61SHarisuddin Mohamed Isa * @param[in] json - The JSON to convert to a string
59c8d6cc61SHarisuddin Mohamed Isa *
60c8d6cc61SHarisuddin Mohamed Isa * @return std::string - The JSON string
61c8d6cc61SHarisuddin Mohamed Isa */
prettyJSON(const orderedJSON & json)62516935a5SSumit Kumar std::string prettyJSON(const orderedJSON& json)
63c8d6cc61SHarisuddin Mohamed Isa {
64516935a5SSumit Kumar orderedJSON output;
65c8d6cc61SHarisuddin Mohamed Isa if (!json.is_object())
66c8d6cc61SHarisuddin Mohamed Isa {
67c8d6cc61SHarisuddin Mohamed Isa output["SRC Details"] = json;
68c8d6cc61SHarisuddin Mohamed Isa }
69c8d6cc61SHarisuddin Mohamed Isa else
70c8d6cc61SHarisuddin Mohamed Isa {
71c8d6cc61SHarisuddin Mohamed Isa for (const auto& [key, value] : json.items())
72c8d6cc61SHarisuddin Mohamed Isa {
7369c1827aSHarisuddin Mohamed Isa output["SRC Details"][key] = value;
74c8d6cc61SHarisuddin Mohamed Isa }
75c8d6cc61SHarisuddin Mohamed Isa }
76c8d6cc61SHarisuddin Mohamed Isa
77c8d6cc61SHarisuddin Mohamed Isa // Let nlohmann do the pretty printing.
78c8d6cc61SHarisuddin Mohamed Isa std::stringstream stream;
79c8d6cc61SHarisuddin Mohamed Isa stream << std::setw(4) << output;
80c8d6cc61SHarisuddin Mohamed Isa
81c8d6cc61SHarisuddin Mohamed Isa auto jsonString = stream.str();
82c8d6cc61SHarisuddin Mohamed Isa
83c8d6cc61SHarisuddin Mohamed Isa // Now it looks like:
84c8d6cc61SHarisuddin Mohamed Isa // {
85c8d6cc61SHarisuddin Mohamed Isa // "Key": "Value",
86c8d6cc61SHarisuddin Mohamed Isa // ...
87c8d6cc61SHarisuddin Mohamed Isa // }
88c8d6cc61SHarisuddin Mohamed Isa
89c8d6cc61SHarisuddin Mohamed Isa // Replace the { and the following newline, and the } and its
90c8d6cc61SHarisuddin Mohamed Isa // preceeding newline.
91c8d6cc61SHarisuddin Mohamed Isa jsonString.erase(0, 2);
92c8d6cc61SHarisuddin Mohamed Isa
93c8d6cc61SHarisuddin Mohamed Isa auto pos = jsonString.find_last_of('}');
94c8d6cc61SHarisuddin Mohamed Isa jsonString.erase(pos - 1);
95c8d6cc61SHarisuddin Mohamed Isa
96c8d6cc61SHarisuddin Mohamed Isa return jsonString;
97c8d6cc61SHarisuddin Mohamed Isa }
98c8d6cc61SHarisuddin Mohamed Isa
99c8d6cc61SHarisuddin Mohamed Isa /**
100c8d6cc61SHarisuddin Mohamed Isa * @brief Call Python modules to parse the data into a JSON string
101c8d6cc61SHarisuddin Mohamed Isa *
102c8d6cc61SHarisuddin Mohamed Isa * The module to call is based on the Creator Subsystem ID under the namespace
103c8d6cc61SHarisuddin Mohamed Isa * "srcparsers". For example: "srcparsers.xsrc.xsrc" where "x" is the Creator
104c8d6cc61SHarisuddin Mohamed Isa * Subsystem ID in ASCII lowercase.
105c8d6cc61SHarisuddin Mohamed Isa *
106c8d6cc61SHarisuddin Mohamed Isa * All modules must provide the following:
107c8d6cc61SHarisuddin Mohamed Isa * Function: parseSRCToJson
108c8d6cc61SHarisuddin Mohamed Isa * Argument list:
109c8d6cc61SHarisuddin Mohamed Isa * 1. (str) ASCII string (Hex Word 1)
110c8d6cc61SHarisuddin Mohamed Isa * 2. (str) Hex Word 2
111c8d6cc61SHarisuddin Mohamed Isa * 3. (str) Hex Word 3
112c8d6cc61SHarisuddin Mohamed Isa * 4. (str) Hex Word 4
113c8d6cc61SHarisuddin Mohamed Isa * 5. (str) Hex Word 5
114c8d6cc61SHarisuddin Mohamed Isa * 6. (str) Hex Word 6
115c8d6cc61SHarisuddin Mohamed Isa * 7. (str) Hex Word 7
116c8d6cc61SHarisuddin Mohamed Isa * 8. (str) Hex Word 8
117c8d6cc61SHarisuddin Mohamed Isa * 9. (str) Hex Word 9
118c8d6cc61SHarisuddin Mohamed Isa *-Return data:
119c8d6cc61SHarisuddin Mohamed Isa * 1. (str) JSON string
120c8d6cc61SHarisuddin Mohamed Isa *
121c8d6cc61SHarisuddin Mohamed Isa * @param[in] hexwords - Vector of strings of Hexwords 1-9
122c8d6cc61SHarisuddin Mohamed Isa * @param[in] creatorID - The creatorID from the Private Header section
123c8d6cc61SHarisuddin Mohamed Isa * @return std::optional<std::string> - The JSON string if it could be created,
124c8d6cc61SHarisuddin Mohamed Isa * else std::nullopt
125c8d6cc61SHarisuddin Mohamed Isa */
getPythonJSON(std::vector<std::string> & hexwords,uint8_t creatorID)126c8d6cc61SHarisuddin Mohamed Isa std::optional<std::string> getPythonJSON(std::vector<std::string>& hexwords,
127c8d6cc61SHarisuddin Mohamed Isa uint8_t creatorID)
128c8d6cc61SHarisuddin Mohamed Isa {
129be952d2eSMatt Spinler PyObject *pName, *pModule, *eType, *eValue, *eTraceback;
130c8d6cc61SHarisuddin Mohamed Isa std::string pErrStr;
131c8d6cc61SHarisuddin Mohamed Isa std::string module = getNumberString("%c", tolower(creatorID)) + "src";
132c8d6cc61SHarisuddin Mohamed Isa pName = PyUnicode_FromString(
133c8d6cc61SHarisuddin Mohamed Isa std::string("srcparsers." + module + "." + module).c_str());
134c8d6cc61SHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> modNamePtr(pName, &pyDecRef);
135c8d6cc61SHarisuddin Mohamed Isa pModule = PyImport_Import(pName);
136c8d6cc61SHarisuddin Mohamed Isa if (pModule == NULL)
137c8d6cc61SHarisuddin Mohamed Isa {
138c8d6cc61SHarisuddin Mohamed Isa pErrStr = "No error string found";
139c8d6cc61SHarisuddin Mohamed Isa PyErr_Fetch(&eType, &eValue, &eTraceback);
14069c1827aSHarisuddin Mohamed Isa if (eType)
14169c1827aSHarisuddin Mohamed Isa {
14269c1827aSHarisuddin Mohamed Isa Py_XDECREF(eType);
14369c1827aSHarisuddin Mohamed Isa }
14469c1827aSHarisuddin Mohamed Isa if (eTraceback)
14569c1827aSHarisuddin Mohamed Isa {
14669c1827aSHarisuddin Mohamed Isa Py_XDECREF(eTraceback);
14769c1827aSHarisuddin Mohamed Isa }
148c8d6cc61SHarisuddin Mohamed Isa if (eValue)
149c8d6cc61SHarisuddin Mohamed Isa {
150c8d6cc61SHarisuddin Mohamed Isa PyObject* pStr = PyObject_Str(eValue);
15169c1827aSHarisuddin Mohamed Isa Py_XDECREF(eValue);
152c8d6cc61SHarisuddin Mohamed Isa if (pStr)
153c8d6cc61SHarisuddin Mohamed Isa {
154c8d6cc61SHarisuddin Mohamed Isa pErrStr = PyUnicode_AsUTF8(pStr);
155c8d6cc61SHarisuddin Mohamed Isa Py_XDECREF(pStr);
156c8d6cc61SHarisuddin Mohamed Isa }
157c8d6cc61SHarisuddin Mohamed Isa }
15869c1827aSHarisuddin Mohamed Isa }
159c8d6cc61SHarisuddin Mohamed Isa else
160c8d6cc61SHarisuddin Mohamed Isa {
161075c7923SPatrick Williams std::unique_ptr<PyObject, decltype(&pyDecRef)> modPtr(
162075c7923SPatrick Williams pModule, &pyDecRef);
16369c1827aSHarisuddin Mohamed Isa std::string funcToCall = "parseSRCToJson";
164be952d2eSMatt Spinler PyObject* pKey = PyUnicode_FromString(funcToCall.c_str());
16569c1827aSHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> keyPtr(pKey, &pyDecRef);
166be952d2eSMatt Spinler PyObject* pDict = PyModule_GetDict(pModule);
16769c1827aSHarisuddin Mohamed Isa Py_INCREF(pDict);
16869c1827aSHarisuddin Mohamed Isa if (!PyDict_Contains(pDict, pKey))
16969c1827aSHarisuddin Mohamed Isa {
17069c1827aSHarisuddin Mohamed Isa Py_DECREF(pDict);
1710bacc8efSMatt Spinler lg2::error(
1720bacc8efSMatt Spinler "Python module error. Function missing: {FUNC}, SRC = {SRC}, module = {MODULE}",
1730bacc8efSMatt Spinler "FUNC", funcToCall, "SRC", hexwords.front(), "MODULE", module);
17469c1827aSHarisuddin Mohamed Isa return std::nullopt;
17569c1827aSHarisuddin Mohamed Isa }
176be952d2eSMatt Spinler PyObject* pFunc = PyDict_GetItemString(pDict, funcToCall.c_str());
17769c1827aSHarisuddin Mohamed Isa Py_DECREF(pDict);
17869c1827aSHarisuddin Mohamed Isa Py_INCREF(pFunc);
179c8d6cc61SHarisuddin Mohamed Isa if (PyCallable_Check(pFunc))
180c8d6cc61SHarisuddin Mohamed Isa {
181be952d2eSMatt Spinler PyObject* pArgs = PyTuple_New(9);
182075c7923SPatrick Williams std::unique_ptr<PyObject, decltype(&pyDecRef)> argPtr(
183075c7923SPatrick Williams pArgs, &pyDecRef);
184c8d6cc61SHarisuddin Mohamed Isa for (size_t i = 0; i < 9; i++)
185c8d6cc61SHarisuddin Mohamed Isa {
186c1984039SMatt Spinler std::string arg{"00000000"};
187c8d6cc61SHarisuddin Mohamed Isa if (i < hexwords.size())
188c8d6cc61SHarisuddin Mohamed Isa {
189c1984039SMatt Spinler arg = hexwords[i];
190c8d6cc61SHarisuddin Mohamed Isa }
191c1984039SMatt Spinler PyTuple_SetItem(pArgs, i, Py_BuildValue("s", arg.c_str()));
192c8d6cc61SHarisuddin Mohamed Isa }
193be952d2eSMatt Spinler PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
19469c1827aSHarisuddin Mohamed Isa Py_DECREF(pFunc);
195c8d6cc61SHarisuddin Mohamed Isa if (pResult)
196c8d6cc61SHarisuddin Mohamed Isa {
19769c1827aSHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> resPtr(
19869c1827aSHarisuddin Mohamed Isa pResult, &pyDecRef);
199075c7923SPatrick Williams PyObject* pBytes =
200075c7923SPatrick Williams PyUnicode_AsEncodedString(pResult, "utf-8", "~E~");
201c8d6cc61SHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> pyBytePtr(
202c8d6cc61SHarisuddin Mohamed Isa pBytes, &pyDecRef);
203c8d6cc61SHarisuddin Mohamed Isa const char* output = PyBytes_AS_STRING(pBytes);
204c8d6cc61SHarisuddin Mohamed Isa try
205c8d6cc61SHarisuddin Mohamed Isa {
206bb1c1d5cSMatt Spinler orderedJSON json = orderedJSON::parse(output);
20769c1827aSHarisuddin Mohamed Isa if ((json.is_object() && !json.empty()) ||
20869c1827aSHarisuddin Mohamed Isa (json.is_array() && json.size() > 0) ||
20969c1827aSHarisuddin Mohamed Isa (json.is_string() && json != ""))
21069c1827aSHarisuddin Mohamed Isa {
211c8d6cc61SHarisuddin Mohamed Isa return prettyJSON(json);
212c8d6cc61SHarisuddin Mohamed Isa }
21369c1827aSHarisuddin Mohamed Isa }
21466491c61SPatrick Williams catch (const std::exception& e)
215c8d6cc61SHarisuddin Mohamed Isa {
2160bacc8efSMatt Spinler lg2::error(
2170bacc8efSMatt Spinler "Bad JSON from parser. Error = {ERROR}, SRC = {SRC}, module = {MODULE}",
2180bacc8efSMatt Spinler "ERROR", e, "SRC", hexwords.front(), "MODULE", module);
219c8d6cc61SHarisuddin Mohamed Isa return std::nullopt;
220c8d6cc61SHarisuddin Mohamed Isa }
221c8d6cc61SHarisuddin Mohamed Isa }
222c8d6cc61SHarisuddin Mohamed Isa else
223c8d6cc61SHarisuddin Mohamed Isa {
224c8d6cc61SHarisuddin Mohamed Isa pErrStr = "No error string found";
225c8d6cc61SHarisuddin Mohamed Isa PyErr_Fetch(&eType, &eValue, &eTraceback);
22669c1827aSHarisuddin Mohamed Isa if (eType)
22769c1827aSHarisuddin Mohamed Isa {
22869c1827aSHarisuddin Mohamed Isa Py_XDECREF(eType);
22969c1827aSHarisuddin Mohamed Isa }
23069c1827aSHarisuddin Mohamed Isa if (eTraceback)
23169c1827aSHarisuddin Mohamed Isa {
23269c1827aSHarisuddin Mohamed Isa Py_XDECREF(eTraceback);
23369c1827aSHarisuddin Mohamed Isa }
234c8d6cc61SHarisuddin Mohamed Isa if (eValue)
235c8d6cc61SHarisuddin Mohamed Isa {
236c8d6cc61SHarisuddin Mohamed Isa PyObject* pStr = PyObject_Str(eValue);
23769c1827aSHarisuddin Mohamed Isa Py_XDECREF(eValue);
238c8d6cc61SHarisuddin Mohamed Isa if (pStr)
239c8d6cc61SHarisuddin Mohamed Isa {
240c8d6cc61SHarisuddin Mohamed Isa pErrStr = PyUnicode_AsUTF8(pStr);
241c8d6cc61SHarisuddin Mohamed Isa Py_XDECREF(pStr);
242c8d6cc61SHarisuddin Mohamed Isa }
243c8d6cc61SHarisuddin Mohamed Isa }
244c8d6cc61SHarisuddin Mohamed Isa }
245c8d6cc61SHarisuddin Mohamed Isa }
24669c1827aSHarisuddin Mohamed Isa }
247c8d6cc61SHarisuddin Mohamed Isa if (!pErrStr.empty())
248c8d6cc61SHarisuddin Mohamed Isa {
2490bacc8efSMatt Spinler lg2::debug("Python exception thrown by parser. Error = {ERROR}, "
2500bacc8efSMatt Spinler "SRC = {SRC}, module = {MODULE}",
2510bacc8efSMatt Spinler "ERROR", pErrStr, "SRC", hexwords.front(), "MODULE", module);
252c8d6cc61SHarisuddin Mohamed Isa }
253c8d6cc61SHarisuddin Mohamed Isa return std::nullopt;
254c8d6cc61SHarisuddin Mohamed Isa }
255c8d6cc61SHarisuddin Mohamed Isa #endif
256c8d6cc61SHarisuddin Mohamed Isa
unflatten(Stream & stream)257f9bae185SMatt Spinler void SRC::unflatten(Stream& stream)
258f9bae185SMatt Spinler {
259f9bae185SMatt Spinler stream >> _header >> _version >> _flags >> _reserved1B >> _wordCount >>
260f9bae185SMatt Spinler _reserved2B >> _size;
261f9bae185SMatt Spinler
262f9bae185SMatt Spinler for (auto& word : _hexData)
263f9bae185SMatt Spinler {
264f9bae185SMatt Spinler stream >> word;
265f9bae185SMatt Spinler }
266f9bae185SMatt Spinler
267f9bae185SMatt Spinler _asciiString = std::make_unique<src::AsciiString>(stream);
268f9bae185SMatt Spinler
269f9bae185SMatt Spinler if (hasAdditionalSections())
270f9bae185SMatt Spinler {
271f9bae185SMatt Spinler // The callouts section is currently the only extra subsection type
272f9bae185SMatt Spinler _callouts = std::make_unique<src::Callouts>(stream);
273f9bae185SMatt Spinler }
274f9bae185SMatt Spinler }
275f9bae185SMatt Spinler
flatten(Stream & stream) const2760688545bSMatt Spinler void SRC::flatten(Stream& stream) const
277f9bae185SMatt Spinler {
278f9bae185SMatt Spinler stream << _header << _version << _flags << _reserved1B << _wordCount
279f9bae185SMatt Spinler << _reserved2B << _size;
280f9bae185SMatt Spinler
281f9bae185SMatt Spinler for (auto& word : _hexData)
282f9bae185SMatt Spinler {
283f9bae185SMatt Spinler stream << word;
284f9bae185SMatt Spinler }
285f9bae185SMatt Spinler
286f9bae185SMatt Spinler _asciiString->flatten(stream);
287f9bae185SMatt Spinler
288f9bae185SMatt Spinler if (_callouts)
289f9bae185SMatt Spinler {
290f9bae185SMatt Spinler _callouts->flatten(stream);
291f9bae185SMatt Spinler }
292f9bae185SMatt Spinler }
293f9bae185SMatt Spinler
SRC(Stream & pel)294f9bae185SMatt Spinler SRC::SRC(Stream& pel)
295f9bae185SMatt Spinler {
296f9bae185SMatt Spinler try
297f9bae185SMatt Spinler {
298f9bae185SMatt Spinler unflatten(pel);
299f9bae185SMatt Spinler validate();
300f9bae185SMatt Spinler }
301f9bae185SMatt Spinler catch (const std::exception& e)
302f9bae185SMatt Spinler {
3030bacc8efSMatt Spinler lg2::error("Cannot unflatten SRC, error = {ERROR}", "ERROR", e);
304f9bae185SMatt Spinler _valid = false;
305f9bae185SMatt Spinler }
306f9bae185SMatt Spinler }
307f9bae185SMatt Spinler
SRC(const message::Entry & regEntry,const AdditionalData & additionalData,const nlohmann::json & jsonCallouts,const DataInterfaceBase & dataIface)308075e5bafSMatt Spinler SRC::SRC(const message::Entry& regEntry, const AdditionalData& additionalData,
3095a90a95bSMatt Spinler const nlohmann::json& jsonCallouts, const DataInterfaceBase& dataIface)
310bd716f00SMatt Spinler {
311bd716f00SMatt Spinler _header.id = static_cast<uint16_t>(SectionID::primarySRC);
312bd716f00SMatt Spinler _header.version = srcSectionVersion;
313bd716f00SMatt Spinler _header.subType = srcSectionSubtype;
314bd716f00SMatt Spinler _header.componentID = regEntry.componentID;
315bd716f00SMatt Spinler
316bd716f00SMatt Spinler _version = srcVersion;
317bd716f00SMatt Spinler
318bd716f00SMatt Spinler _flags = 0;
319f3702bb3SVijay Lobo
320bd716f00SMatt Spinler _reserved1B = 0;
321bd716f00SMatt Spinler
322bd716f00SMatt Spinler _wordCount = numSRCHexDataWords + 1;
323bd716f00SMatt Spinler
324bd716f00SMatt Spinler _reserved2B = 0;
325bd716f00SMatt Spinler
326bd716f00SMatt Spinler // There are multiple fields encoded in the hex data words.
327bd716f00SMatt Spinler std::for_each(_hexData.begin(), _hexData.end(),
328bd716f00SMatt Spinler [](auto& word) { word = 0; });
3297c619181SMatt Spinler
3307c619181SMatt Spinler // Hex Word 2 Nibbles:
3317c619181SMatt Spinler // MIGVEPFF
3327c619181SMatt Spinler // M: Partition dump status = 0
3337c619181SMatt Spinler // I: System boot state = TODO
3347c619181SMatt Spinler // G: Partition Boot type = 0
3359d43a727SSumit Kumar // V: BMC dump status
3367c619181SMatt Spinler // E: Platform boot mode = 0 (side = temporary, speed = fast)
3379d43a727SSumit Kumar // P: Platform dump status
3387c619181SMatt Spinler // FF: SRC format, set below
3397c619181SMatt Spinler
340875b6c7bSVijay Lobo setProgressCode(dataIface);
341bd716f00SMatt Spinler setBMCFormat();
342bd716f00SMatt Spinler setBMCPosition();
343075e5bafSMatt Spinler setMotherboardCCIN(dataIface);
344075e5bafSMatt Spinler
345da5b76b2SMatt Spinler if (regEntry.src.checkstopFlag)
346da5b76b2SMatt Spinler {
347da5b76b2SMatt Spinler setErrorStatusFlag(ErrorStatusFlags::hwCheckstop);
348da5b76b2SMatt Spinler }
349da5b76b2SMatt Spinler
3503fe93e96SMatt Spinler if (regEntry.src.deconfigFlag)
3513fe93e96SMatt Spinler {
3523fe93e96SMatt Spinler setErrorStatusFlag(ErrorStatusFlags::deconfigured);
3533fe93e96SMatt Spinler }
3543fe93e96SMatt Spinler
355bd716f00SMatt Spinler // Fill in the last 4 words from the AdditionalData property contents.
356bd716f00SMatt Spinler setUserDefinedHexWords(regEntry, additionalData);
357bd716f00SMatt Spinler
358bd716f00SMatt Spinler _asciiString = std::make_unique<src::AsciiString>(regEntry);
359bd716f00SMatt Spinler
36050bfa69aSSumit Kumar // Check for additional data - PEL_SUBSYSTEM
36150bfa69aSSumit Kumar auto ss = additionalData.getValue("PEL_SUBSYSTEM");
36250bfa69aSSumit Kumar if (ss)
36350bfa69aSSumit Kumar {
36450bfa69aSSumit Kumar auto eventSubsystem = std::stoul(*ss, NULL, 16);
365075c7923SPatrick Williams std::string subsystem =
366075c7923SPatrick Williams pv::getValue(eventSubsystem, pel_values::subsystemValues);
36750bfa69aSSumit Kumar if (subsystem == "invalid")
36850bfa69aSSumit Kumar {
3690bacc8efSMatt Spinler lg2::warning("SRC: Invalid SubSystem value: {VAL}", "VAL", lg2::hex,
3700bacc8efSMatt Spinler eventSubsystem);
37150bfa69aSSumit Kumar }
37250bfa69aSSumit Kumar else
37350bfa69aSSumit Kumar {
37450bfa69aSSumit Kumar _asciiString->setByte(2, eventSubsystem);
37550bfa69aSSumit Kumar }
37650bfa69aSSumit Kumar }
37750bfa69aSSumit Kumar
3785a90a95bSMatt Spinler addCallouts(regEntry, additionalData, jsonCallouts, dataIface);
379bd716f00SMatt Spinler
380bd716f00SMatt Spinler _size = baseSRCSize;
381bd716f00SMatt Spinler _size += _callouts ? _callouts->flattenedSize() : 0;
382bd716f00SMatt Spinler _header.size = Section::flattenedSize() + _size;
383bd716f00SMatt Spinler
384bd716f00SMatt Spinler _valid = true;
385bd716f00SMatt Spinler }
386bd716f00SMatt Spinler
setUserDefinedHexWords(const message::Entry & regEntry,const AdditionalData & ad)387bd716f00SMatt Spinler void SRC::setUserDefinedHexWords(const message::Entry& regEntry,
388bd716f00SMatt Spinler const AdditionalData& ad)
389bd716f00SMatt Spinler {
390bd716f00SMatt Spinler if (!regEntry.src.hexwordADFields)
391bd716f00SMatt Spinler {
392bd716f00SMatt Spinler return;
393bd716f00SMatt Spinler }
394bd716f00SMatt Spinler
3951a1b0dfbSHarisuddin Mohamed Isa // Save the AdditionalData value corresponding to the first element of
3961a1b0dfbSHarisuddin Mohamed Isa // adName tuple into _hexData[wordNum].
397bd716f00SMatt Spinler for (const auto& [wordNum, adName] : *regEntry.src.hexwordADFields)
398bd716f00SMatt Spinler {
399bd716f00SMatt Spinler // Can only set words 6 - 9
400bd716f00SMatt Spinler if (!isUserDefinedWord(wordNum))
401bd716f00SMatt Spinler {
402075c7923SPatrick Williams std::string msg =
403075c7923SPatrick Williams "SRC user data word out of range: " + std::to_string(wordNum);
40485f61a63SMatt Spinler addDebugData(msg);
405bd716f00SMatt Spinler continue;
406bd716f00SMatt Spinler }
407bd716f00SMatt Spinler
4081a1b0dfbSHarisuddin Mohamed Isa auto value = ad.getValue(std::get<0>(adName));
409bd716f00SMatt Spinler if (value)
410bd716f00SMatt Spinler {
411bd716f00SMatt Spinler _hexData[getWordIndexFromWordNum(wordNum)] =
412bd716f00SMatt Spinler std::strtoul(value.value().c_str(), nullptr, 0);
413bd716f00SMatt Spinler }
414bd716f00SMatt Spinler else
415bd716f00SMatt Spinler {
4161a1b0dfbSHarisuddin Mohamed Isa std::string msg = "Source for user data SRC word not found: " +
4171a1b0dfbSHarisuddin Mohamed Isa std::get<0>(adName);
41885f61a63SMatt Spinler addDebugData(msg);
419bd716f00SMatt Spinler }
420bd716f00SMatt Spinler }
421bd716f00SMatt Spinler }
422bd716f00SMatt Spinler
setMotherboardCCIN(const DataInterfaceBase & dataIface)423075e5bafSMatt Spinler void SRC::setMotherboardCCIN(const DataInterfaceBase& dataIface)
424075e5bafSMatt Spinler {
425075e5bafSMatt Spinler uint32_t ccin = 0;
426075e5bafSMatt Spinler auto ccinString = dataIface.getMotherboardCCIN();
427075e5bafSMatt Spinler
428075e5bafSMatt Spinler try
429075e5bafSMatt Spinler {
430075e5bafSMatt Spinler if (ccinString.size() == ccinSize)
431075e5bafSMatt Spinler {
432075e5bafSMatt Spinler ccin = std::stoi(ccinString, 0, 16);
433075e5bafSMatt Spinler }
434075e5bafSMatt Spinler }
43566491c61SPatrick Williams catch (const std::exception& e)
436075e5bafSMatt Spinler {
4370bacc8efSMatt Spinler lg2::warning("Could not convert motherboard CCIN {CCIN} to a number",
4380bacc8efSMatt Spinler "CCIN", ccinString);
439075e5bafSMatt Spinler return;
440075e5bafSMatt Spinler }
441075e5bafSMatt Spinler
442075e5bafSMatt Spinler // Set the first 2 bytes
443075e5bafSMatt Spinler _hexData[1] |= ccin << 16;
444075e5bafSMatt Spinler }
445075e5bafSMatt Spinler
validate()446f9bae185SMatt Spinler void SRC::validate()
447f9bae185SMatt Spinler {
448f9bae185SMatt Spinler bool failed = false;
449f9bae185SMatt Spinler
450f9bae185SMatt Spinler if ((header().id != static_cast<uint16_t>(SectionID::primarySRC)) &&
451f9bae185SMatt Spinler (header().id != static_cast<uint16_t>(SectionID::secondarySRC)))
452f9bae185SMatt Spinler {
4530bacc8efSMatt Spinler lg2::error("Invalid SRC section ID: {ID}", "ID", lg2::hex, header().id);
454f9bae185SMatt Spinler failed = true;
455f9bae185SMatt Spinler }
456f9bae185SMatt Spinler
457f9bae185SMatt Spinler // Check the version in the SRC, not in the header
458bd716f00SMatt Spinler if (_version != srcVersion)
459f9bae185SMatt Spinler {
4600bacc8efSMatt Spinler lg2::error("Invalid SRC version: {VERSION}", "VERSION", lg2::hex,
4610bacc8efSMatt Spinler header().version);
462f9bae185SMatt Spinler failed = true;
463f9bae185SMatt Spinler }
464f9bae185SMatt Spinler
465f9bae185SMatt Spinler _valid = failed ? false : true;
466f9bae185SMatt Spinler }
467f9bae185SMatt Spinler
isBMCSRC() const468075e5bafSMatt Spinler bool SRC::isBMCSRC() const
469075e5bafSMatt Spinler {
470075e5bafSMatt Spinler auto as = asciiString();
471075e5bafSMatt Spinler if (as.length() >= 2)
472075e5bafSMatt Spinler {
473075e5bafSMatt Spinler uint8_t errorType = strtoul(as.substr(0, 2).c_str(), nullptr, 16);
474075e5bafSMatt Spinler return (errorType == static_cast<uint8_t>(SRCType::bmcError) ||
475075e5bafSMatt Spinler errorType == static_cast<uint8_t>(SRCType::powerError));
476075e5bafSMatt Spinler }
477075e5bafSMatt Spinler return false;
478075e5bafSMatt Spinler }
479075e5bafSMatt Spinler
isHostbootSRC() const4804deed972SMatt Spinler bool SRC::isHostbootSRC() const
4814deed972SMatt Spinler {
4824deed972SMatt Spinler auto as = asciiString();
4834deed972SMatt Spinler if (as.length() >= 2)
4844deed972SMatt Spinler {
4854deed972SMatt Spinler uint8_t errorType = strtoul(as.substr(0, 2).c_str(), nullptr, 16);
4864deed972SMatt Spinler return errorType == static_cast<uint8_t>(SRCType::hostbootError);
4874deed972SMatt Spinler }
4884deed972SMatt Spinler return false;
4894deed972SMatt Spinler }
4904deed972SMatt Spinler
getErrorDetails(message::Registry & registry,DetailLevel type,bool toCache) const491075c7923SPatrick Williams std::optional<std::string> SRC::getErrorDetails(
492075c7923SPatrick Williams message::Registry& registry, DetailLevel type, bool toCache) const
4930f717e10SHarisuddin Mohamed Isa {
4940f717e10SHarisuddin Mohamed Isa const std::string jsonIndent(indentLevel, 0x20);
4950f717e10SHarisuddin Mohamed Isa std::string errorOut;
496075e5bafSMatt Spinler if (isBMCSRC())
4970f717e10SHarisuddin Mohamed Isa {
4980f717e10SHarisuddin Mohamed Isa auto entry = registry.lookup("0x" + asciiString().substr(4, 4),
4990f717e10SHarisuddin Mohamed Isa rg::LookupType::reasonCode, toCache);
5000f717e10SHarisuddin Mohamed Isa if (entry)
5010f717e10SHarisuddin Mohamed Isa {
5020f717e10SHarisuddin Mohamed Isa errorOut.append(jsonIndent + "\"Error Details\": {\n");
5030f717e10SHarisuddin Mohamed Isa auto errorMsg = getErrorMessage(*entry);
5040f717e10SHarisuddin Mohamed Isa if (errorMsg)
5050f717e10SHarisuddin Mohamed Isa {
5060f717e10SHarisuddin Mohamed Isa if (type == DetailLevel::message)
5070f717e10SHarisuddin Mohamed Isa {
5080f717e10SHarisuddin Mohamed Isa return errorMsg.value();
5090f717e10SHarisuddin Mohamed Isa }
5100f717e10SHarisuddin Mohamed Isa else
5110f717e10SHarisuddin Mohamed Isa {
5120f717e10SHarisuddin Mohamed Isa jsonInsert(errorOut, "Message", errorMsg.value(), 2);
5130f717e10SHarisuddin Mohamed Isa }
5140f717e10SHarisuddin Mohamed Isa }
5150f717e10SHarisuddin Mohamed Isa if (entry->src.hexwordADFields)
5160f717e10SHarisuddin Mohamed Isa {
5171a1b0dfbSHarisuddin Mohamed Isa std::map<size_t, std::tuple<std::string, std::string>>
5181a1b0dfbSHarisuddin Mohamed Isa adFields = entry->src.hexwordADFields.value();
5190f717e10SHarisuddin Mohamed Isa for (const auto& hexwordMap : adFields)
5200f717e10SHarisuddin Mohamed Isa {
521e8db29b3SZane Shelley auto srcValue = getNumberString(
5221a1b0dfbSHarisuddin Mohamed Isa "0x%X",
523e8db29b3SZane Shelley _hexData[getWordIndexFromWordNum(hexwordMap.first)]);
524e8db29b3SZane Shelley
525e8db29b3SZane Shelley auto srcKey = std::get<0>(hexwordMap.second);
526e8db29b3SZane Shelley auto srcDesc = std::get<1>(hexwordMap.second);
527e8db29b3SZane Shelley
528e8db29b3SZane Shelley // Only include this hex word in the error details if the
529e8db29b3SZane Shelley // description exists.
530e8db29b3SZane Shelley if (!srcDesc.empty())
531e8db29b3SZane Shelley {
532e8db29b3SZane Shelley std::vector<std::string> valueDescr;
533e8db29b3SZane Shelley valueDescr.push_back(srcValue);
534e8db29b3SZane Shelley valueDescr.push_back(srcDesc);
535e8db29b3SZane Shelley jsonInsertArray(errorOut, srcKey, valueDescr, 2);
536e8db29b3SZane Shelley }
5370f717e10SHarisuddin Mohamed Isa }
5380f717e10SHarisuddin Mohamed Isa }
5390f717e10SHarisuddin Mohamed Isa errorOut.erase(errorOut.size() - 2);
5400f717e10SHarisuddin Mohamed Isa errorOut.append("\n");
5410f717e10SHarisuddin Mohamed Isa errorOut.append(jsonIndent + "},\n");
5420f717e10SHarisuddin Mohamed Isa return errorOut;
5430f717e10SHarisuddin Mohamed Isa }
5440f717e10SHarisuddin Mohamed Isa }
5450f717e10SHarisuddin Mohamed Isa return std::nullopt;
5460f717e10SHarisuddin Mohamed Isa }
5470f717e10SHarisuddin Mohamed Isa
getErrorMessage(const message::Entry & regEntry) const54825291157SPatrick Williams std::optional<std::string> SRC::getErrorMessage(
54925291157SPatrick Williams const message::Entry& regEntry) const
5500f717e10SHarisuddin Mohamed Isa {
5510f717e10SHarisuddin Mohamed Isa try
5520f717e10SHarisuddin Mohamed Isa {
5530f717e10SHarisuddin Mohamed Isa if (regEntry.doc.messageArgSources)
5540f717e10SHarisuddin Mohamed Isa {
5550f717e10SHarisuddin Mohamed Isa std::vector<uint32_t> argSourceVals;
5560f717e10SHarisuddin Mohamed Isa std::string message;
5570f717e10SHarisuddin Mohamed Isa const auto& argValues = regEntry.doc.messageArgSources.value();
5580f717e10SHarisuddin Mohamed Isa for (size_t i = 0; i < argValues.size(); ++i)
5590f717e10SHarisuddin Mohamed Isa {
5600f717e10SHarisuddin Mohamed Isa argSourceVals.push_back(_hexData[getWordIndexFromWordNum(
5610f717e10SHarisuddin Mohamed Isa argValues[i].back() - '0')]);
5620f717e10SHarisuddin Mohamed Isa }
5630230abb4SPatrick Williams
5640230abb4SPatrick Williams auto it = std::begin(regEntry.doc.message);
5650230abb4SPatrick Williams auto it_end = std::end(regEntry.doc.message);
5660230abb4SPatrick Williams
5670230abb4SPatrick Williams while (it != it_end)
5680f717e10SHarisuddin Mohamed Isa {
5690230abb4SPatrick Williams if (*it == '%')
5700f717e10SHarisuddin Mohamed Isa {
5710230abb4SPatrick Williams ++it;
5720230abb4SPatrick Williams
5730230abb4SPatrick Williams size_t wordIndex = *it - '0';
5740230abb4SPatrick Williams if (isdigit(*it) && wordIndex >= 1 &&
5750f717e10SHarisuddin Mohamed Isa static_cast<uint16_t>(wordIndex) <=
5760f717e10SHarisuddin Mohamed Isa argSourceVals.size())
5770f717e10SHarisuddin Mohamed Isa {
5780f717e10SHarisuddin Mohamed Isa message.append(getNumberString(
57939936e34SZane Shelley "0x%08X", argSourceVals[wordIndex - 1]));
5800f717e10SHarisuddin Mohamed Isa }
5810f717e10SHarisuddin Mohamed Isa else
5820f717e10SHarisuddin Mohamed Isa {
5830230abb4SPatrick Williams message.append("%" + std::string(1, *it));
5840f717e10SHarisuddin Mohamed Isa }
5850f717e10SHarisuddin Mohamed Isa }
5860f717e10SHarisuddin Mohamed Isa else
5870f717e10SHarisuddin Mohamed Isa {
5880230abb4SPatrick Williams message.push_back(*it);
5890f717e10SHarisuddin Mohamed Isa }
5900230abb4SPatrick Williams ++it;
5910f717e10SHarisuddin Mohamed Isa }
5920230abb4SPatrick Williams
5930f717e10SHarisuddin Mohamed Isa return message;
5940f717e10SHarisuddin Mohamed Isa }
5950f717e10SHarisuddin Mohamed Isa else
5960f717e10SHarisuddin Mohamed Isa {
5970f717e10SHarisuddin Mohamed Isa return regEntry.doc.message;
5980f717e10SHarisuddin Mohamed Isa }
5990f717e10SHarisuddin Mohamed Isa }
6000f717e10SHarisuddin Mohamed Isa catch (const std::exception& e)
6010f717e10SHarisuddin Mohamed Isa {
6020bacc8efSMatt Spinler lg2::error(
6030bacc8efSMatt Spinler "Cannot get error message from registry entry, error = {ERROR}",
6040bacc8efSMatt Spinler "ERROR", e);
6050f717e10SHarisuddin Mohamed Isa }
6060f717e10SHarisuddin Mohamed Isa return std::nullopt;
6070f717e10SHarisuddin Mohamed Isa }
6080f717e10SHarisuddin Mohamed Isa
getCallouts() const6090f717e10SHarisuddin Mohamed Isa std::optional<std::string> SRC::getCallouts() const
6100f717e10SHarisuddin Mohamed Isa {
6110f717e10SHarisuddin Mohamed Isa if (!_callouts)
6120f717e10SHarisuddin Mohamed Isa {
6130f717e10SHarisuddin Mohamed Isa return std::nullopt;
6140f717e10SHarisuddin Mohamed Isa }
6150f717e10SHarisuddin Mohamed Isa std::string printOut;
6160f717e10SHarisuddin Mohamed Isa const std::string jsonIndent(indentLevel, 0x20);
6170f717e10SHarisuddin Mohamed Isa const auto& callout = _callouts->callouts();
6180f717e10SHarisuddin Mohamed Isa const auto& compDescrp = pv::failingComponentType;
6190f717e10SHarisuddin Mohamed Isa printOut.append(jsonIndent + "\"Callout Section\": {\n");
6200f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "Callout Count", std::to_string(callout.size()), 2);
6210f717e10SHarisuddin Mohamed Isa printOut.append(jsonIndent + jsonIndent + "\"Callouts\": [");
6220f717e10SHarisuddin Mohamed Isa for (auto& entry : callout)
6230f717e10SHarisuddin Mohamed Isa {
6240f717e10SHarisuddin Mohamed Isa printOut.append("{\n");
6250f717e10SHarisuddin Mohamed Isa if (entry->fruIdentity())
6260f717e10SHarisuddin Mohamed Isa {
6270f717e10SHarisuddin Mohamed Isa jsonInsert(
6280f717e10SHarisuddin Mohamed Isa printOut, "FRU Type",
6290f717e10SHarisuddin Mohamed Isa compDescrp.at(entry->fruIdentity()->failingComponentType()), 3);
6300f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "Priority",
6310f717e10SHarisuddin Mohamed Isa pv::getValue(entry->priority(),
6320f717e10SHarisuddin Mohamed Isa pel_values::calloutPriorityValues),
6330f717e10SHarisuddin Mohamed Isa 3);
6340f717e10SHarisuddin Mohamed Isa if (!entry->locationCode().empty())
6350f717e10SHarisuddin Mohamed Isa {
6360f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "Location Code", entry->locationCode(), 3);
6370f717e10SHarisuddin Mohamed Isa }
6380f717e10SHarisuddin Mohamed Isa if (entry->fruIdentity()->getPN().has_value())
6390f717e10SHarisuddin Mohamed Isa {
6400f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "Part Number",
6410f717e10SHarisuddin Mohamed Isa entry->fruIdentity()->getPN().value(), 3);
6420f717e10SHarisuddin Mohamed Isa }
6430f717e10SHarisuddin Mohamed Isa if (entry->fruIdentity()->getMaintProc().has_value())
6440f717e10SHarisuddin Mohamed Isa {
6459e8b49e6SMatt Spinler jsonInsert(printOut, "Procedure",
6460f717e10SHarisuddin Mohamed Isa entry->fruIdentity()->getMaintProc().value(), 3);
6470f717e10SHarisuddin Mohamed Isa if (pv::procedureDesc.find(
6480f717e10SHarisuddin Mohamed Isa entry->fruIdentity()->getMaintProc().value()) !=
6490f717e10SHarisuddin Mohamed Isa pv::procedureDesc.end())
6500f717e10SHarisuddin Mohamed Isa {
6510f717e10SHarisuddin Mohamed Isa jsonInsert(
6520f717e10SHarisuddin Mohamed Isa printOut, "Description",
6530f717e10SHarisuddin Mohamed Isa pv::procedureDesc.at(
6540f717e10SHarisuddin Mohamed Isa entry->fruIdentity()->getMaintProc().value()),
6550f717e10SHarisuddin Mohamed Isa 3);
6560f717e10SHarisuddin Mohamed Isa }
6570f717e10SHarisuddin Mohamed Isa }
6580f717e10SHarisuddin Mohamed Isa if (entry->fruIdentity()->getCCIN().has_value())
6590f717e10SHarisuddin Mohamed Isa {
6600f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "CCIN",
6610f717e10SHarisuddin Mohamed Isa entry->fruIdentity()->getCCIN().value(), 3);
6620f717e10SHarisuddin Mohamed Isa }
6630f717e10SHarisuddin Mohamed Isa if (entry->fruIdentity()->getSN().has_value())
6640f717e10SHarisuddin Mohamed Isa {
6650f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "Serial Number",
6660f717e10SHarisuddin Mohamed Isa entry->fruIdentity()->getSN().value(), 3);
6670f717e10SHarisuddin Mohamed Isa }
6680f717e10SHarisuddin Mohamed Isa }
6690f717e10SHarisuddin Mohamed Isa if (entry->pceIdentity())
6700f717e10SHarisuddin Mohamed Isa {
6710f717e10SHarisuddin Mohamed Isa const auto& pceIdentMtms = entry->pceIdentity()->mtms();
6720f717e10SHarisuddin Mohamed Isa if (!pceIdentMtms.machineTypeAndModel().empty())
6730f717e10SHarisuddin Mohamed Isa {
6740f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "PCE MTMS",
6750f717e10SHarisuddin Mohamed Isa pceIdentMtms.machineTypeAndModel() + "_" +
6760f717e10SHarisuddin Mohamed Isa pceIdentMtms.machineSerialNumber(),
6770f717e10SHarisuddin Mohamed Isa 3);
6780f717e10SHarisuddin Mohamed Isa }
6790f717e10SHarisuddin Mohamed Isa if (!entry->pceIdentity()->enclosureName().empty())
6800f717e10SHarisuddin Mohamed Isa {
6810f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "PCE Name",
6820f717e10SHarisuddin Mohamed Isa entry->pceIdentity()->enclosureName(), 3);
6830f717e10SHarisuddin Mohamed Isa }
6840f717e10SHarisuddin Mohamed Isa }
6850f717e10SHarisuddin Mohamed Isa if (entry->mru())
6860f717e10SHarisuddin Mohamed Isa {
6870f717e10SHarisuddin Mohamed Isa const auto& mruCallouts = entry->mru()->mrus();
6880f717e10SHarisuddin Mohamed Isa std::string mruId;
6890f717e10SHarisuddin Mohamed Isa for (auto& element : mruCallouts)
6900f717e10SHarisuddin Mohamed Isa {
6910f717e10SHarisuddin Mohamed Isa if (!mruId.empty())
6920f717e10SHarisuddin Mohamed Isa {
6930f717e10SHarisuddin Mohamed Isa mruId.append(", " + getNumberString("%08X", element.id));
6940f717e10SHarisuddin Mohamed Isa }
6950f717e10SHarisuddin Mohamed Isa else
6960f717e10SHarisuddin Mohamed Isa {
6970f717e10SHarisuddin Mohamed Isa mruId.append(getNumberString("%08X", element.id));
6980f717e10SHarisuddin Mohamed Isa }
6990f717e10SHarisuddin Mohamed Isa }
7000f717e10SHarisuddin Mohamed Isa jsonInsert(printOut, "MRU Id", mruId, 3);
7010f717e10SHarisuddin Mohamed Isa }
7020f717e10SHarisuddin Mohamed Isa printOut.erase(printOut.size() - 2);
7030f717e10SHarisuddin Mohamed Isa printOut.append("\n" + jsonIndent + jsonIndent + "}, ");
7040f717e10SHarisuddin Mohamed Isa };
7050f717e10SHarisuddin Mohamed Isa printOut.erase(printOut.size() - 2);
7060f717e10SHarisuddin Mohamed Isa printOut.append("]\n" + jsonIndent + "}");
7070f717e10SHarisuddin Mohamed Isa return printOut;
7080f717e10SHarisuddin Mohamed Isa }
7090f717e10SHarisuddin Mohamed Isa
getJSON(message::Registry & registry,const std::vector<std::string> & plugins,uint8_t creatorID) const71025291157SPatrick Williams std::optional<std::string> SRC::getJSON(message::Registry& registry,
71125291157SPatrick Williams const std::vector<std::string>& plugins
71225291157SPatrick Williams [[maybe_unused]],
713c8d6cc61SHarisuddin Mohamed Isa uint8_t creatorID) const
7140f717e10SHarisuddin Mohamed Isa {
7150f717e10SHarisuddin Mohamed Isa std::string ps;
716c8d6cc61SHarisuddin Mohamed Isa std::vector<std::string> hexwords;
717bebeb948SHarisuddin Mohamed Isa jsonInsert(ps, pv::sectionVer, getNumberString("%d", _header.version), 1);
718bebeb948SHarisuddin Mohamed Isa jsonInsert(ps, pv::subSection, getNumberString("%d", _header.subType), 1);
719b832aa5eSMatt Spinler jsonInsert(ps, pv::createdBy,
720b832aa5eSMatt Spinler getComponentName(_header.componentID, creatorID), 1);
7210f717e10SHarisuddin Mohamed Isa jsonInsert(ps, "SRC Version", getNumberString("0x%02X", _version), 1);
722c32e5516SHarisuddin Mohamed Isa jsonInsert(ps, "SRC Format", getNumberString("0x%02X", _hexData[0] & 0xFF),
723c32e5516SHarisuddin Mohamed Isa 1);
724c32e5516SHarisuddin Mohamed Isa jsonInsert(ps, "Virtual Progress SRC",
725c32e5516SHarisuddin Mohamed Isa pv::boolString.at(_flags & virtualProgressSRC), 1);
726c32e5516SHarisuddin Mohamed Isa jsonInsert(ps, "I5/OS Service Event Bit",
727c32e5516SHarisuddin Mohamed Isa pv::boolString.at(_flags & i5OSServiceEventBit), 1);
728c32e5516SHarisuddin Mohamed Isa jsonInsert(ps, "Hypervisor Dump Initiated",
729c32e5516SHarisuddin Mohamed Isa pv::boolString.at(_flags & hypDumpInit), 1);
730075e5bafSMatt Spinler
731075e5bafSMatt Spinler if (isBMCSRC())
732075e5bafSMatt Spinler {
733075e5bafSMatt Spinler std::string ccinString;
734075e5bafSMatt Spinler uint32_t ccin = _hexData[1] >> 16;
735075e5bafSMatt Spinler
736075e5bafSMatt Spinler if (ccin)
737075e5bafSMatt Spinler {
738075e5bafSMatt Spinler ccinString = getNumberString("%04X", ccin);
739075e5bafSMatt Spinler }
740075e5bafSMatt Spinler // The PEL spec calls it a backplane, so call it that here.
741075e5bafSMatt Spinler jsonInsert(ps, "Backplane CCIN", ccinString, 1);
742afa2c799SMatt Spinler
7433e274432SSumit Kumar jsonInsert(ps, "Terminate FW Error",
7443e274432SSumit Kumar pv::boolString.at(
7453e274432SSumit Kumar _hexData[3] &
7463e274432SSumit Kumar static_cast<uint32_t>(ErrorStatusFlags::terminateFwErr)),
7473e274432SSumit Kumar 1);
7484deed972SMatt Spinler }
7494deed972SMatt Spinler
7504deed972SMatt Spinler if (isBMCSRC() || isHostbootSRC())
7514deed972SMatt Spinler {
752afa2c799SMatt Spinler jsonInsert(ps, "Deconfigured",
753afa2c799SMatt Spinler pv::boolString.at(
754afa2c799SMatt Spinler _hexData[3] &
755afa2c799SMatt Spinler static_cast<uint32_t>(ErrorStatusFlags::deconfigured)),
756afa2c799SMatt Spinler 1);
757afa2c799SMatt Spinler
758afa2c799SMatt Spinler jsonInsert(
759afa2c799SMatt Spinler ps, "Guarded",
760075c7923SPatrick Williams pv::boolString.at(
761075c7923SPatrick Williams _hexData[3] & static_cast<uint32_t>(ErrorStatusFlags::guarded)),
762afa2c799SMatt Spinler 1);
763075e5bafSMatt Spinler }
764075e5bafSMatt Spinler
765a214ed30SHarisuddin Mohamed Isa auto errorDetails = getErrorDetails(registry, DetailLevel::json, true);
7660f717e10SHarisuddin Mohamed Isa if (errorDetails)
7670f717e10SHarisuddin Mohamed Isa {
7680f717e10SHarisuddin Mohamed Isa ps.append(errorDetails.value());
7690f717e10SHarisuddin Mohamed Isa }
7700f717e10SHarisuddin Mohamed Isa jsonInsert(ps, "Valid Word Count", getNumberString("0x%02X", _wordCount),
7710f717e10SHarisuddin Mohamed Isa 1);
7720f717e10SHarisuddin Mohamed Isa std::string refcode = asciiString();
773c8d6cc61SHarisuddin Mohamed Isa hexwords.push_back(refcode);
774fecaa57cSHarisuddin Mohamed Isa std::string extRefcode;
775fecaa57cSHarisuddin Mohamed Isa size_t pos = refcode.find(0x20);
776fecaa57cSHarisuddin Mohamed Isa if (pos != std::string::npos)
777fecaa57cSHarisuddin Mohamed Isa {
778fecaa57cSHarisuddin Mohamed Isa size_t nextPos = refcode.find_first_not_of(0x20, pos);
779fecaa57cSHarisuddin Mohamed Isa if (nextPos != std::string::npos)
780fecaa57cSHarisuddin Mohamed Isa {
781fecaa57cSHarisuddin Mohamed Isa extRefcode = trimEnd(refcode.substr(nextPos));
782fecaa57cSHarisuddin Mohamed Isa }
783fecaa57cSHarisuddin Mohamed Isa refcode.erase(pos);
784fecaa57cSHarisuddin Mohamed Isa }
7850f717e10SHarisuddin Mohamed Isa jsonInsert(ps, "Reference Code", refcode, 1);
786fecaa57cSHarisuddin Mohamed Isa if (!extRefcode.empty())
787fecaa57cSHarisuddin Mohamed Isa {
788fecaa57cSHarisuddin Mohamed Isa jsonInsert(ps, "Extended Reference Code", extRefcode, 1);
789fecaa57cSHarisuddin Mohamed Isa }
7900f717e10SHarisuddin Mohamed Isa for (size_t i = 2; i <= _wordCount; i++)
7910f717e10SHarisuddin Mohamed Isa {
792c8d6cc61SHarisuddin Mohamed Isa std::string tmpWord =
793c8d6cc61SHarisuddin Mohamed Isa getNumberString("%08X", _hexData[getWordIndexFromWordNum(i)]);
794c8d6cc61SHarisuddin Mohamed Isa jsonInsert(ps, "Hex Word " + std::to_string(i), tmpWord, 1);
795c8d6cc61SHarisuddin Mohamed Isa hexwords.push_back(tmpWord);
7960f717e10SHarisuddin Mohamed Isa }
7970f717e10SHarisuddin Mohamed Isa auto calloutJson = getCallouts();
7980f717e10SHarisuddin Mohamed Isa if (calloutJson)
7990f717e10SHarisuddin Mohamed Isa {
8000f717e10SHarisuddin Mohamed Isa ps.append(calloutJson.value());
801c8d6cc61SHarisuddin Mohamed Isa ps.append(",\n");
8020f717e10SHarisuddin Mohamed Isa }
803c8d6cc61SHarisuddin Mohamed Isa std::string subsystem = getNumberString("%c", tolower(creatorID));
804c8d6cc61SHarisuddin Mohamed Isa bool srcDetailExists = false;
805c8d6cc61SHarisuddin Mohamed Isa #ifdef PELTOOL
806c8d6cc61SHarisuddin Mohamed Isa if (std::find(plugins.begin(), plugins.end(), subsystem + "src") !=
807c8d6cc61SHarisuddin Mohamed Isa plugins.end())
808c8d6cc61SHarisuddin Mohamed Isa {
809c8d6cc61SHarisuddin Mohamed Isa auto pyJson = getPythonJSON(hexwords, creatorID);
810c8d6cc61SHarisuddin Mohamed Isa if (pyJson)
811c8d6cc61SHarisuddin Mohamed Isa {
812c8d6cc61SHarisuddin Mohamed Isa ps.append(pyJson.value());
813c8d6cc61SHarisuddin Mohamed Isa srcDetailExists = true;
814c8d6cc61SHarisuddin Mohamed Isa }
815c8d6cc61SHarisuddin Mohamed Isa }
816c8d6cc61SHarisuddin Mohamed Isa #endif
817c8d6cc61SHarisuddin Mohamed Isa if (!srcDetailExists)
8180f717e10SHarisuddin Mohamed Isa {
8190f717e10SHarisuddin Mohamed Isa ps.erase(ps.size() - 2);
8200f717e10SHarisuddin Mohamed Isa }
8210f717e10SHarisuddin Mohamed Isa return ps;
8220f717e10SHarisuddin Mohamed Isa }
8230f717e10SHarisuddin Mohamed Isa
addCallouts(const message::Entry & regEntry,const AdditionalData & additionalData,const nlohmann::json & jsonCallouts,const DataInterfaceBase & dataIface)8240398458dSMatt Spinler void SRC::addCallouts(const message::Entry& regEntry,
8250398458dSMatt Spinler const AdditionalData& additionalData,
8265a90a95bSMatt Spinler const nlohmann::json& jsonCallouts,
827ed046856SMatt Spinler const DataInterfaceBase& dataIface)
828ed046856SMatt Spinler {
829075c7923SPatrick Williams auto registryCallouts =
830075c7923SPatrick Williams getRegistryCallouts(regEntry, additionalData, dataIface);
831f00f9d0fSMatt Spinler
832ed046856SMatt Spinler auto item = additionalData.getValue("CALLOUT_INVENTORY_PATH");
83353ef1552SMiguel Gomez auto priority = additionalData.getValue("CALLOUT_PRIORITY");
834f00f9d0fSMatt Spinler
83553ef1552SMiguel Gomez std::optional<CalloutPriority> calloutPriority;
83653ef1552SMiguel Gomez
83753ef1552SMiguel Gomez // Only H, M or L priority values.
83853ef1552SMiguel Gomez if (priority && !(*priority).empty())
83953ef1552SMiguel Gomez {
84053ef1552SMiguel Gomez uint8_t p = (*priority)[0];
84153ef1552SMiguel Gomez if (p == 'H' || p == 'M' || p == 'L')
84253ef1552SMiguel Gomez {
84353ef1552SMiguel Gomez calloutPriority = static_cast<CalloutPriority>(p);
84453ef1552SMiguel Gomez }
84553ef1552SMiguel Gomez }
846f00f9d0fSMatt Spinler // If the first registry callout says to use the passed in inventory
847f00f9d0fSMatt Spinler // path to get the location code for a symbolic FRU callout with a
848f00f9d0fSMatt Spinler // trusted location code, then do not add the inventory path as a
849f00f9d0fSMatt Spinler // normal FRU callout.
850f00f9d0fSMatt Spinler bool useInvForSymbolicFRULocCode =
851f00f9d0fSMatt Spinler !registryCallouts.empty() && registryCallouts[0].useInventoryLocCode &&
852f00f9d0fSMatt Spinler !registryCallouts[0].symbolicFRUTrusted.empty();
853f00f9d0fSMatt Spinler
854f00f9d0fSMatt Spinler if (item && !useInvForSymbolicFRULocCode)
855ed046856SMatt Spinler {
85653ef1552SMiguel Gomez addInventoryCallout(*item, calloutPriority, std::nullopt, dataIface);
857ed046856SMatt Spinler }
858ed046856SMatt Spinler
859717de428SMatt Spinler addDevicePathCallouts(additionalData, dataIface);
8600398458dSMatt Spinler
861f00f9d0fSMatt Spinler addRegistryCallouts(registryCallouts, dataIface,
862f00f9d0fSMatt Spinler (useInvForSymbolicFRULocCode) ? item : std::nullopt);
8635a90a95bSMatt Spinler
8645a90a95bSMatt Spinler if (!jsonCallouts.empty())
8655a90a95bSMatt Spinler {
8665a90a95bSMatt Spinler addJSONCallouts(jsonCallouts, dataIface);
8675a90a95bSMatt Spinler }
868ed046856SMatt Spinler }
869ed046856SMatt Spinler
addLocationCodeOnlyCallout(const std::string & locationCode,const CalloutPriority priority)870*7b92372dSMatt Spinler void SRC::addLocationCodeOnlyCallout(const std::string& locationCode,
871*7b92372dSMatt Spinler const CalloutPriority priority)
872*7b92372dSMatt Spinler {
873*7b92372dSMatt Spinler std::string empty;
874*7b92372dSMatt Spinler std::vector<src::MRU::MRUCallout> mrus;
875*7b92372dSMatt Spinler auto callout = std::make_unique<src::Callout>(priority, locationCode, empty,
876*7b92372dSMatt Spinler empty, empty, mrus);
877*7b92372dSMatt Spinler createCalloutsObject();
878*7b92372dSMatt Spinler _callouts->addCallout(std::move(callout));
879*7b92372dSMatt Spinler }
880*7b92372dSMatt Spinler
addInventoryCallout(const std::string & inventoryPath,const std::optional<CalloutPriority> & priority,const std::optional<std::string> & locationCode,const DataInterfaceBase & dataIface,const std::vector<src::MRU::MRUCallout> & mrus)881ed046856SMatt Spinler void SRC::addInventoryCallout(const std::string& inventoryPath,
882af191c7aSMatt Spinler const std::optional<CalloutPriority>& priority,
883af191c7aSMatt Spinler const std::optional<std::string>& locationCode,
884b8cb60feSMatt Spinler const DataInterfaceBase& dataIface,
885b8cb60feSMatt Spinler const std::vector<src::MRU::MRUCallout>& mrus)
886ed046856SMatt Spinler {
887ed046856SMatt Spinler std::string locCode;
888ed046856SMatt Spinler std::string fn;
889ed046856SMatt Spinler std::string ccin;
890ed046856SMatt Spinler std::string sn;
891ed046856SMatt Spinler std::unique_ptr<src::Callout> callout;
892ed046856SMatt Spinler
8939b90e2a2SMatt Spinler try
8949b90e2a2SMatt Spinler {
895af191c7aSMatt Spinler // Use the passed in location code if there otherwise look it up
896af191c7aSMatt Spinler if (locationCode)
897af191c7aSMatt Spinler {
898af191c7aSMatt Spinler locCode = *locationCode;
899af191c7aSMatt Spinler }
900af191c7aSMatt Spinler else
901af191c7aSMatt Spinler {
9029b90e2a2SMatt Spinler locCode = dataIface.getLocationCode(inventoryPath);
903af191c7aSMatt Spinler }
904ed046856SMatt Spinler
905ed046856SMatt Spinler try
906ed046856SMatt Spinler {
9079b90e2a2SMatt Spinler dataIface.getHWCalloutFields(inventoryPath, fn, ccin, sn);
908ed046856SMatt Spinler
909075c7923SPatrick Williams CalloutPriority p =
910075c7923SPatrick Williams priority ? priority.value() : CalloutPriority::high;
911af191c7aSMatt Spinler
912075c7923SPatrick Williams callout =
913075c7923SPatrick Williams std::make_unique<src::Callout>(p, locCode, fn, ccin, sn, mrus);
914ed046856SMatt Spinler }
91545e83521SPatrick Williams catch (const sdbusplus::exception_t& e)
916ed046856SMatt Spinler {
917075c7923SPatrick Williams std::string msg =
918075c7923SPatrick Williams "No VPD found for " + inventoryPath + ": " + e.what();
91985f61a63SMatt Spinler addDebugData(msg);
920ed046856SMatt Spinler
9219b90e2a2SMatt Spinler // Just create the callout with empty FRU fields
922b8cb60feSMatt Spinler callout = std::make_unique<src::Callout>(
923b8cb60feSMatt Spinler CalloutPriority::high, locCode, fn, ccin, sn, mrus);
9249b90e2a2SMatt Spinler }
9259b90e2a2SMatt Spinler }
92645e83521SPatrick Williams catch (const sdbusplus::exception_t& e)
9279b90e2a2SMatt Spinler {
92885f61a63SMatt Spinler std::string msg = "Could not get location code for " + inventoryPath +
92985f61a63SMatt Spinler ": " + e.what();
93085f61a63SMatt Spinler addDebugData(msg);
9319b90e2a2SMatt Spinler
932479b6927SMatt Spinler // Don't add a callout in this case, because:
933479b6927SMatt Spinler // 1) With how the inventory is primed, there is no case where
934479b6927SMatt Spinler // a location code is expected to be missing. This implies
935479b6927SMatt Spinler // the caller is passing in something invalid.
936479b6927SMatt Spinler // 2) The addDebugData call above will put the passed in path into
937479b6927SMatt Spinler // a user data section that can be seen by development for debug.
938479b6927SMatt Spinler // 3) Even if we wanted to do a 'no_vpd_for_fru' sort of maint.
939479b6927SMatt Spinler // procedure, we don't have a good way to indicate to the user
940479b6927SMatt Spinler // anything about the intended callout (they won't see user data).
941479b6927SMatt Spinler // 4) Creating a new standalone event log for this problem isn't
942479b6927SMatt Spinler // possible from inside a PEL section.
943ed046856SMatt Spinler }
944ed046856SMatt Spinler
945479b6927SMatt Spinler if (callout)
946479b6927SMatt Spinler {
9479b90e2a2SMatt Spinler createCalloutsObject();
948ed046856SMatt Spinler _callouts->addCallout(std::move(callout));
9490398458dSMatt Spinler }
950479b6927SMatt Spinler }
951ed046856SMatt Spinler
getRegistryCallouts(const message::Entry & regEntry,const AdditionalData & additionalData,const DataInterfaceBase & dataIface)952075c7923SPatrick Williams std::vector<message::RegistryCallout> SRC::getRegistryCallouts(
953075c7923SPatrick Williams const message::Entry& regEntry, const AdditionalData& additionalData,
9540398458dSMatt Spinler const DataInterfaceBase& dataIface)
9550398458dSMatt Spinler {
956f00f9d0fSMatt Spinler std::vector<message::RegistryCallout> registryCallouts;
957f00f9d0fSMatt Spinler
958f00f9d0fSMatt Spinler if (regEntry.callouts)
959f00f9d0fSMatt Spinler {
9609a50c8daSMatt Spinler std::vector<std::string> systemNames;
9619a50c8daSMatt Spinler
9620398458dSMatt Spinler try
9630398458dSMatt Spinler {
9649a50c8daSMatt Spinler systemNames = dataIface.getSystemNames();
9659a50c8daSMatt Spinler }
9669a50c8daSMatt Spinler catch (const std::exception& e)
9679a50c8daSMatt Spinler {
9689a50c8daSMatt Spinler // Compatible interface not available yet
9699a50c8daSMatt Spinler }
9700398458dSMatt Spinler
9719a50c8daSMatt Spinler try
9729a50c8daSMatt Spinler {
973f00f9d0fSMatt Spinler registryCallouts = message::Registry::getCallouts(
9746ea4d5f7SMatt Spinler regEntry.callouts.value(), systemNames, additionalData);
975f00f9d0fSMatt Spinler }
976f00f9d0fSMatt Spinler catch (const std::exception& e)
9770398458dSMatt Spinler {
9781aa90d49SJayanth Othayoth addDebugData(std::format(
979f00f9d0fSMatt Spinler "Error parsing PEL message registry callout JSON: {}",
980f00f9d0fSMatt Spinler e.what()));
981f00f9d0fSMatt Spinler }
982f00f9d0fSMatt Spinler }
983f00f9d0fSMatt Spinler
984f00f9d0fSMatt Spinler return registryCallouts;
985f00f9d0fSMatt Spinler }
986f00f9d0fSMatt Spinler
addRegistryCallouts(const std::vector<message::RegistryCallout> & callouts,const DataInterfaceBase & dataIface,std::optional<std::string> trustedSymbolicFRUInvPath)987f00f9d0fSMatt Spinler void SRC::addRegistryCallouts(
988f00f9d0fSMatt Spinler const std::vector<message::RegistryCallout>& callouts,
989f00f9d0fSMatt Spinler const DataInterfaceBase& dataIface,
990f00f9d0fSMatt Spinler std::optional<std::string> trustedSymbolicFRUInvPath)
991f00f9d0fSMatt Spinler {
992f00f9d0fSMatt Spinler try
993f00f9d0fSMatt Spinler {
994f00f9d0fSMatt Spinler for (const auto& callout : callouts)
995f00f9d0fSMatt Spinler {
996f00f9d0fSMatt Spinler addRegistryCallout(callout, dataIface, trustedSymbolicFRUInvPath);
997f00f9d0fSMatt Spinler
998f00f9d0fSMatt Spinler // Only the first callout gets the inventory path
999f00f9d0fSMatt Spinler if (trustedSymbolicFRUInvPath)
1000f00f9d0fSMatt Spinler {
1001f00f9d0fSMatt Spinler trustedSymbolicFRUInvPath = std::nullopt;
1002f00f9d0fSMatt Spinler }
10030398458dSMatt Spinler }
10040398458dSMatt Spinler }
100566491c61SPatrick Williams catch (const std::exception& e)
10060398458dSMatt Spinler {
1007075c7923SPatrick Williams std::string msg =
1008075c7923SPatrick Williams "Error parsing PEL message registry callout JSON: "s + e.what();
100985f61a63SMatt Spinler addDebugData(msg);
10100398458dSMatt Spinler }
10110398458dSMatt Spinler }
10120398458dSMatt Spinler
addRegistryCallout(const message::RegistryCallout & regCallout,const DataInterfaceBase & dataIface,const std::optional<std::string> & trustedSymbolicFRUInvPath)1013f00f9d0fSMatt Spinler void SRC::addRegistryCallout(
1014f00f9d0fSMatt Spinler const message::RegistryCallout& regCallout,
1015f00f9d0fSMatt Spinler const DataInterfaceBase& dataIface,
1016f00f9d0fSMatt Spinler const std::optional<std::string>& trustedSymbolicFRUInvPath)
10170398458dSMatt Spinler {
10180398458dSMatt Spinler std::unique_ptr<src::Callout> callout;
10190398458dSMatt Spinler auto locCode = regCallout.locCode;
1020*7b92372dSMatt Spinler bool locExpanded = true;
10210398458dSMatt Spinler
1022af191c7aSMatt Spinler if (!locCode.empty())
1023af191c7aSMatt Spinler {
1024af191c7aSMatt Spinler try
1025af191c7aSMatt Spinler {
1026af191c7aSMatt Spinler locCode = dataIface.expandLocationCode(locCode, 0);
1027af191c7aSMatt Spinler }
1028af191c7aSMatt Spinler catch (const std::exception& e)
1029af191c7aSMatt Spinler {
10302544b419SPatrick Williams auto msg = "Unable to expand location code " + locCode + ": " +
10312544b419SPatrick Williams e.what();
1032af191c7aSMatt Spinler addDebugData(msg);
1033*7b92372dSMatt Spinler locExpanded = false;
1034af191c7aSMatt Spinler }
1035af191c7aSMatt Spinler }
1036af191c7aSMatt Spinler
10370398458dSMatt Spinler // Via the PEL values table, get the priority enum.
10380398458dSMatt Spinler // The schema will have validated the priority was a valid value.
1039075c7923SPatrick Williams auto priorityIt =
1040075c7923SPatrick Williams pv::findByName(regCallout.priority, pv::calloutPriorityValues);
10410398458dSMatt Spinler assert(priorityIt != pv::calloutPriorityValues.end());
10420398458dSMatt Spinler auto priority =
10430398458dSMatt Spinler static_cast<CalloutPriority>(std::get<pv::fieldValuePos>(*priorityIt));
10440398458dSMatt Spinler
10450398458dSMatt Spinler if (!regCallout.procedure.empty())
10460398458dSMatt Spinler {
10470398458dSMatt Spinler // Procedure callout
10482edce4e2SMatt Spinler callout = std::make_unique<src::Callout>(priority, regCallout.procedure,
10492edce4e2SMatt Spinler src::CalloutValueType::raw);
10500398458dSMatt Spinler }
10510398458dSMatt Spinler else if (!regCallout.symbolicFRU.empty())
10520398458dSMatt Spinler {
10530398458dSMatt Spinler // Symbolic FRU callout
10540398458dSMatt Spinler callout = std::make_unique<src::Callout>(
10550398458dSMatt Spinler priority, regCallout.symbolicFRU, locCode, false);
10560398458dSMatt Spinler }
10570398458dSMatt Spinler else if (!regCallout.symbolicFRUTrusted.empty())
10580398458dSMatt Spinler {
10590398458dSMatt Spinler // Symbolic FRU with trusted location code callout
1060*7b92372dSMatt Spinler bool trusted = false;
10610398458dSMatt Spinler
1062f00f9d0fSMatt Spinler // Use the location code from the inventory path if there is one.
1063f00f9d0fSMatt Spinler if (trustedSymbolicFRUInvPath)
1064f00f9d0fSMatt Spinler {
1065f00f9d0fSMatt Spinler try
1066f00f9d0fSMatt Spinler {
1067f00f9d0fSMatt Spinler locCode = dataIface.getLocationCode(*trustedSymbolicFRUInvPath);
1068*7b92372dSMatt Spinler trusted = true;
1069f00f9d0fSMatt Spinler }
1070f00f9d0fSMatt Spinler catch (const std::exception& e)
1071f00f9d0fSMatt Spinler {
1072f00f9d0fSMatt Spinler addDebugData(
10731aa90d49SJayanth Othayoth std::format("Could not get location code for {}: {}",
1074f00f9d0fSMatt Spinler *trustedSymbolicFRUInvPath, e.what()));
1075f00f9d0fSMatt Spinler locCode.clear();
1076f00f9d0fSMatt Spinler }
1077f00f9d0fSMatt Spinler }
1078f00f9d0fSMatt Spinler
1079*7b92372dSMatt Spinler // Can only trust the location code if it isn't empty and is expanded.
1080*7b92372dSMatt Spinler if (!locCode.empty() && locExpanded)
1081*7b92372dSMatt Spinler {
1082*7b92372dSMatt Spinler trusted = true;
1083*7b92372dSMatt Spinler }
1084*7b92372dSMatt Spinler
10850398458dSMatt Spinler // The registry wants it to be trusted, but that requires a valid
10860398458dSMatt Spinler // location code for it to actually be.
10870398458dSMatt Spinler callout = std::make_unique<src::Callout>(
1088*7b92372dSMatt Spinler priority, regCallout.symbolicFRUTrusted, locCode, trusted);
10890398458dSMatt Spinler }
10900398458dSMatt Spinler else
10910398458dSMatt Spinler {
1092af191c7aSMatt Spinler // A hardware callout
1093*7b92372dSMatt Spinler
1094*7b92372dSMatt Spinler // If couldn't expand the location code, don't bother
1095*7b92372dSMatt Spinler // looking up the inventory path.
1096*7b92372dSMatt Spinler if (!locExpanded && !locCode.empty())
1097*7b92372dSMatt Spinler {
1098*7b92372dSMatt Spinler addLocationCodeOnlyCallout(locCode, priority);
1099*7b92372dSMatt Spinler return;
1100*7b92372dSMatt Spinler }
1101*7b92372dSMatt Spinler
1102bad056beSMatt Spinler std::vector<std::string> inventoryPaths;
1103af191c7aSMatt Spinler
1104af191c7aSMatt Spinler try
1105af191c7aSMatt Spinler {
1106af191c7aSMatt Spinler // Get the inventory item from the unexpanded location code
1107bad056beSMatt Spinler inventoryPaths =
11082f9225a4SMatt Spinler dataIface.getInventoryFromLocCode(regCallout.locCode, 0, false);
1109af191c7aSMatt Spinler }
1110af191c7aSMatt Spinler catch (const std::exception& e)
1111af191c7aSMatt Spinler {
1112af191c7aSMatt Spinler std::string msg =
1113af191c7aSMatt Spinler "Unable to get inventory path from location code: " + locCode +
1114af191c7aSMatt Spinler ": " + e.what();
1115af191c7aSMatt Spinler addDebugData(msg);
1116*7b92372dSMatt Spinler if (!locCode.empty())
1117*7b92372dSMatt Spinler {
1118*7b92372dSMatt Spinler // Still add a callout with just the location code.
1119*7b92372dSMatt Spinler addLocationCodeOnlyCallout(locCode, priority);
1120*7b92372dSMatt Spinler }
1121af191c7aSMatt Spinler return;
1122af191c7aSMatt Spinler }
1123af191c7aSMatt Spinler
1124bad056beSMatt Spinler // Just use first path returned since they all point to the same FRU.
1125bad056beSMatt Spinler addInventoryCallout(inventoryPaths[0], priority, locCode, dataIface);
11260398458dSMatt Spinler }
11270398458dSMatt Spinler
11280398458dSMatt Spinler if (callout)
11290398458dSMatt Spinler {
11300398458dSMatt Spinler createCalloutsObject();
11310398458dSMatt Spinler _callouts->addCallout(std::move(callout));
11320398458dSMatt Spinler }
11330398458dSMatt Spinler }
1134ed046856SMatt Spinler
addDevicePathCallouts(const AdditionalData & additionalData,const DataInterfaceBase & dataIface)1135717de428SMatt Spinler void SRC::addDevicePathCallouts(const AdditionalData& additionalData,
1136717de428SMatt Spinler const DataInterfaceBase& dataIface)
1137717de428SMatt Spinler {
1138717de428SMatt Spinler std::vector<device_callouts::Callout> callouts;
1139717de428SMatt Spinler auto i2cBus = additionalData.getValue("CALLOUT_IIC_BUS");
1140717de428SMatt Spinler auto i2cAddr = additionalData.getValue("CALLOUT_IIC_ADDR");
1141717de428SMatt Spinler auto devPath = additionalData.getValue("CALLOUT_DEVICE_PATH");
1142717de428SMatt Spinler
1143717de428SMatt Spinler // A device callout contains either:
1144717de428SMatt Spinler // * CALLOUT_ERRNO, CALLOUT_DEVICE_PATH
1145717de428SMatt Spinler // * CALLOUT_ERRNO, CALLOUT_IIC_BUS, CALLOUT_IIC_ADDR
1146717de428SMatt Spinler // We don't care about the errno.
1147717de428SMatt Spinler
1148717de428SMatt Spinler if (devPath)
1149717de428SMatt Spinler {
1150717de428SMatt Spinler try
1151717de428SMatt Spinler {
1152717de428SMatt Spinler callouts = device_callouts::getCallouts(*devPath,
1153717de428SMatt Spinler dataIface.getSystemNames());
1154717de428SMatt Spinler }
1155717de428SMatt Spinler catch (const std::exception& e)
1156717de428SMatt Spinler {
1157717de428SMatt Spinler addDebugData(e.what());
1158717de428SMatt Spinler callouts.clear();
1159717de428SMatt Spinler }
1160717de428SMatt Spinler }
1161717de428SMatt Spinler else if (i2cBus && i2cAddr)
1162717de428SMatt Spinler {
1163717de428SMatt Spinler size_t bus;
1164717de428SMatt Spinler uint8_t address;
1165717de428SMatt Spinler
1166717de428SMatt Spinler try
1167717de428SMatt Spinler {
1168717de428SMatt Spinler // If /dev/i2c- is prepended, remove it
1169717de428SMatt Spinler if (i2cBus->find("/dev/i2c-") != std::string::npos)
1170717de428SMatt Spinler {
1171717de428SMatt Spinler *i2cBus = i2cBus->substr(9);
1172717de428SMatt Spinler }
1173717de428SMatt Spinler
1174717de428SMatt Spinler bus = stoul(*i2cBus, nullptr, 0);
1175717de428SMatt Spinler address = stoul(*i2cAddr, nullptr, 0);
1176717de428SMatt Spinler }
1177717de428SMatt Spinler catch (const std::exception& e)
1178717de428SMatt Spinler {
1179075c7923SPatrick Williams std::string msg =
1180075c7923SPatrick Williams "Invalid CALLOUT_IIC_BUS " + *i2cBus + " or CALLOUT_IIC_ADDR " +
1181075c7923SPatrick Williams *i2cAddr + " in AdditionalData property";
1182717de428SMatt Spinler addDebugData(msg);
1183717de428SMatt Spinler return;
1184717de428SMatt Spinler }
1185717de428SMatt Spinler
1186717de428SMatt Spinler try
1187717de428SMatt Spinler {
1188717de428SMatt Spinler callouts = device_callouts::getI2CCallouts(
1189717de428SMatt Spinler bus, address, dataIface.getSystemNames());
1190717de428SMatt Spinler }
1191717de428SMatt Spinler catch (const std::exception& e)
1192717de428SMatt Spinler {
1193717de428SMatt Spinler addDebugData(e.what());
1194717de428SMatt Spinler callouts.clear();
1195717de428SMatt Spinler }
1196717de428SMatt Spinler }
1197717de428SMatt Spinler
1198717de428SMatt Spinler for (const auto& callout : callouts)
1199717de428SMatt Spinler {
1200717de428SMatt Spinler // The priority shouldn't be invalid, but check just in case.
1201717de428SMatt Spinler CalloutPriority priority = CalloutPriority::high;
1202717de428SMatt Spinler
1203717de428SMatt Spinler if (!callout.priority.empty())
1204717de428SMatt Spinler {
1205717de428SMatt Spinler auto p = pel_values::findByValue(
1206717de428SMatt Spinler static_cast<uint32_t>(callout.priority[0]),
1207717de428SMatt Spinler pel_values::calloutPriorityValues);
1208717de428SMatt Spinler
1209717de428SMatt Spinler if (p != pel_values::calloutPriorityValues.end())
1210717de428SMatt Spinler {
1211717de428SMatt Spinler priority = static_cast<CalloutPriority>(callout.priority[0]);
1212717de428SMatt Spinler }
1213717de428SMatt Spinler else
1214717de428SMatt Spinler {
1215717de428SMatt Spinler std::string msg =
1216717de428SMatt Spinler "Invalid priority found in dev callout JSON: " +
1217717de428SMatt Spinler callout.priority[0];
1218717de428SMatt Spinler addDebugData(msg);
1219717de428SMatt Spinler }
1220717de428SMatt Spinler }
1221717de428SMatt Spinler
12220d92b528SMatt Spinler std::optional<std::string> locCode;
12230d92b528SMatt Spinler
12240d92b528SMatt Spinler try
12250d92b528SMatt Spinler {
12260d92b528SMatt Spinler locCode = dataIface.expandLocationCode(callout.locationCode, 0);
12270d92b528SMatt Spinler }
12280d92b528SMatt Spinler catch (const std::exception& e)
12290d92b528SMatt Spinler {
12301aa90d49SJayanth Othayoth auto msg = std::format("Unable to expand location code {}: {}",
12310d92b528SMatt Spinler callout.locationCode, e.what());
12320d92b528SMatt Spinler addDebugData(msg);
1233*7b92372dSMatt Spinler
1234*7b92372dSMatt Spinler // Add the callout with just the unexpanded location code.
1235*7b92372dSMatt Spinler addLocationCodeOnlyCallout(callout.locationCode, priority);
1236*7b92372dSMatt Spinler continue;
12370d92b528SMatt Spinler }
12380d92b528SMatt Spinler
1239717de428SMatt Spinler try
1240717de428SMatt Spinler {
1241bad056beSMatt Spinler auto inventoryPaths = dataIface.getInventoryFromLocCode(
12422f9225a4SMatt Spinler callout.locationCode, 0, false);
1243717de428SMatt Spinler
1244bad056beSMatt Spinler // Just use first path returned since they all
1245bad056beSMatt Spinler // point to the same FRU.
1246bad056beSMatt Spinler addInventoryCallout(inventoryPaths[0], priority, locCode,
1247bad056beSMatt Spinler dataIface);
1248717de428SMatt Spinler }
1249717de428SMatt Spinler catch (const std::exception& e)
1250717de428SMatt Spinler {
1251717de428SMatt Spinler std::string msg =
1252717de428SMatt Spinler "Unable to get inventory path from location code: " +
1253717de428SMatt Spinler callout.locationCode + ": " + e.what();
1254717de428SMatt Spinler addDebugData(msg);
1255*7b92372dSMatt Spinler // Add the callout with just the location code.
1256*7b92372dSMatt Spinler addLocationCodeOnlyCallout(callout.locationCode, priority);
1257*7b92372dSMatt Spinler continue;
1258717de428SMatt Spinler }
1259717de428SMatt Spinler
1260717de428SMatt Spinler // Until the code is there to convert these MRU value strings to
1261717de428SMatt Spinler // the official MRU values in the callout objects, just store
1262717de428SMatt Spinler // the MRU name in the debug UserData section.
1263717de428SMatt Spinler if (!callout.mru.empty())
1264717de428SMatt Spinler {
1265717de428SMatt Spinler std::string msg = "MRU: " + callout.mru;
1266717de428SMatt Spinler addDebugData(msg);
1267717de428SMatt Spinler }
1268717de428SMatt Spinler
1269717de428SMatt Spinler // getCallouts() may have generated some debug data it stored
1270717de428SMatt Spinler // in a callout object. Save it as well.
1271717de428SMatt Spinler if (!callout.debug.empty())
1272717de428SMatt Spinler {
1273717de428SMatt Spinler addDebugData(callout.debug);
1274717de428SMatt Spinler }
1275717de428SMatt Spinler }
1276717de428SMatt Spinler }
1277717de428SMatt Spinler
addJSONCallouts(const nlohmann::json & jsonCallouts,const DataInterfaceBase & dataIface)12785a90a95bSMatt Spinler void SRC::addJSONCallouts(const nlohmann::json& jsonCallouts,
12795a90a95bSMatt Spinler const DataInterfaceBase& dataIface)
12805a90a95bSMatt Spinler {
12815a90a95bSMatt Spinler if (jsonCallouts.empty())
12825a90a95bSMatt Spinler {
12835a90a95bSMatt Spinler return;
12845a90a95bSMatt Spinler }
12855a90a95bSMatt Spinler
12865a90a95bSMatt Spinler if (!jsonCallouts.is_array())
12875a90a95bSMatt Spinler {
12885a90a95bSMatt Spinler addDebugData("Callout JSON isn't an array");
12895a90a95bSMatt Spinler return;
12905a90a95bSMatt Spinler }
12915a90a95bSMatt Spinler
12925a90a95bSMatt Spinler for (const auto& callout : jsonCallouts)
12935a90a95bSMatt Spinler {
12945a90a95bSMatt Spinler try
12955a90a95bSMatt Spinler {
12965a90a95bSMatt Spinler addJSONCallout(callout, dataIface);
12975a90a95bSMatt Spinler }
12985a90a95bSMatt Spinler catch (const std::exception& e)
12995a90a95bSMatt Spinler {
13001aa90d49SJayanth Othayoth addDebugData(std::format(
13015a90a95bSMatt Spinler "Failed extracting callout data from JSON: {}", e.what()));
13025a90a95bSMatt Spinler }
13035a90a95bSMatt Spinler }
13045a90a95bSMatt Spinler }
13055a90a95bSMatt Spinler
addJSONCallout(const nlohmann::json & jsonCallout,const DataInterfaceBase & dataIface)13065a90a95bSMatt Spinler void SRC::addJSONCallout(const nlohmann::json& jsonCallout,
13075a90a95bSMatt Spinler const DataInterfaceBase& dataIface)
13085a90a95bSMatt Spinler {
13093bdd0110SMatt Spinler auto priority = getPriorityFromJSON(jsonCallout);
13103bdd0110SMatt Spinler std::string locCode;
13113bdd0110SMatt Spinler std::string unexpandedLocCode;
13123bdd0110SMatt Spinler std::unique_ptr<src::Callout> callout;
13133bdd0110SMatt Spinler
13143bdd0110SMatt Spinler // Expand the location code if it's there
13153bdd0110SMatt Spinler if (jsonCallout.contains("LocationCode"))
13163bdd0110SMatt Spinler {
13173bdd0110SMatt Spinler unexpandedLocCode = jsonCallout.at("LocationCode").get<std::string>();
13183bdd0110SMatt Spinler
13193bdd0110SMatt Spinler try
13203bdd0110SMatt Spinler {
13213bdd0110SMatt Spinler locCode = dataIface.expandLocationCode(unexpandedLocCode, 0);
13223bdd0110SMatt Spinler }
13233bdd0110SMatt Spinler catch (const std::exception& e)
13243bdd0110SMatt Spinler {
13251aa90d49SJayanth Othayoth addDebugData(std::format("Unable to expand location code {}: {}",
13263bdd0110SMatt Spinler unexpandedLocCode, e.what()));
13273bdd0110SMatt Spinler // Use the value from the JSON so at least there's something
13283bdd0110SMatt Spinler locCode = unexpandedLocCode;
13293bdd0110SMatt Spinler }
13303bdd0110SMatt Spinler }
13313bdd0110SMatt Spinler
13323bdd0110SMatt Spinler // Create either a procedure, symbolic FRU, or normal FRU callout.
13333bdd0110SMatt Spinler if (jsonCallout.contains("Procedure"))
13343bdd0110SMatt Spinler {
13353bdd0110SMatt Spinler auto procedure = jsonCallout.at("Procedure").get<std::string>();
13363bdd0110SMatt Spinler
13373c7ec6d8SMatt Spinler // If it's the registry name instead of the raw name, convert.
13383c7ec6d8SMatt Spinler if (pv::maintenanceProcedures.find(procedure) !=
13393c7ec6d8SMatt Spinler pv::maintenanceProcedures.end())
13403c7ec6d8SMatt Spinler {
13413c7ec6d8SMatt Spinler procedure = pv::maintenanceProcedures.at(procedure);
13423c7ec6d8SMatt Spinler }
13433c7ec6d8SMatt Spinler
13443bdd0110SMatt Spinler callout = std::make_unique<src::Callout>(
13453bdd0110SMatt Spinler static_cast<CalloutPriority>(priority), procedure,
13463bdd0110SMatt Spinler src::CalloutValueType::raw);
13473bdd0110SMatt Spinler }
13483bdd0110SMatt Spinler else if (jsonCallout.contains("SymbolicFRU"))
13493bdd0110SMatt Spinler {
13503bdd0110SMatt Spinler auto fru = jsonCallout.at("SymbolicFRU").get<std::string>();
13513bdd0110SMatt Spinler
13523c7ec6d8SMatt Spinler // If it's the registry name instead of the raw name, convert.
13533c7ec6d8SMatt Spinler if (pv::symbolicFRUs.find(fru) != pv::symbolicFRUs.end())
13543c7ec6d8SMatt Spinler {
13553c7ec6d8SMatt Spinler fru = pv::symbolicFRUs.at(fru);
13563c7ec6d8SMatt Spinler }
13573c7ec6d8SMatt Spinler
13583bdd0110SMatt Spinler bool trusted = false;
13593bdd0110SMatt Spinler if (jsonCallout.contains("TrustedLocationCode") && !locCode.empty())
13603bdd0110SMatt Spinler {
13613bdd0110SMatt Spinler trusted = jsonCallout.at("TrustedLocationCode").get<bool>();
13623bdd0110SMatt Spinler }
13633bdd0110SMatt Spinler
13643bdd0110SMatt Spinler callout = std::make_unique<src::Callout>(
13653bdd0110SMatt Spinler static_cast<CalloutPriority>(priority), fru,
13663bdd0110SMatt Spinler src::CalloutValueType::raw, locCode, trusted);
13673bdd0110SMatt Spinler }
13683bdd0110SMatt Spinler else
13693bdd0110SMatt Spinler {
13703bdd0110SMatt Spinler // A hardware FRU
13713bdd0110SMatt Spinler std::string inventoryPath;
1372b8cb60feSMatt Spinler std::vector<src::MRU::MRUCallout> mrus;
13733bdd0110SMatt Spinler
13743bdd0110SMatt Spinler if (jsonCallout.contains("InventoryPath"))
13753bdd0110SMatt Spinler {
13763bdd0110SMatt Spinler inventoryPath = jsonCallout.at("InventoryPath").get<std::string>();
13773bdd0110SMatt Spinler }
13783bdd0110SMatt Spinler else
13793bdd0110SMatt Spinler {
13803bdd0110SMatt Spinler if (unexpandedLocCode.empty())
13813bdd0110SMatt Spinler {
13823bdd0110SMatt Spinler throw std::runtime_error{"JSON callout needs either an "
13833bdd0110SMatt Spinler "inventory path or location code"};
13843bdd0110SMatt Spinler }
13853bdd0110SMatt Spinler
13863bdd0110SMatt Spinler try
13873bdd0110SMatt Spinler {
1388bad056beSMatt Spinler auto inventoryPaths = dataIface.getInventoryFromLocCode(
13893bdd0110SMatt Spinler unexpandedLocCode, 0, false);
1390bad056beSMatt Spinler // Just use first path returned since they all
1391bad056beSMatt Spinler // point to the same FRU.
1392bad056beSMatt Spinler inventoryPath = inventoryPaths[0];
13933bdd0110SMatt Spinler }
13943bdd0110SMatt Spinler catch (const std::exception& e)
13953bdd0110SMatt Spinler {
1396*7b92372dSMatt Spinler addDebugData(std::format("Unable to get inventory path from "
13973bdd0110SMatt Spinler "location code: {}: {}",
1398*7b92372dSMatt Spinler unexpandedLocCode, e.what()));
1399*7b92372dSMatt Spinler addLocationCodeOnlyCallout(locCode, priority);
1400*7b92372dSMatt Spinler return;
14013bdd0110SMatt Spinler }
14023bdd0110SMatt Spinler }
14033bdd0110SMatt Spinler
1404b8cb60feSMatt Spinler if (jsonCallout.contains("MRUs"))
1405b8cb60feSMatt Spinler {
1406b8cb60feSMatt Spinler mrus = getMRUsFromJSON(jsonCallout.at("MRUs"));
1407b8cb60feSMatt Spinler }
1408b8cb60feSMatt Spinler
14093bdd0110SMatt Spinler // If the location code was also passed in, use that here too
14103bdd0110SMatt Spinler // so addInventoryCallout doesn't have to look it up.
14113bdd0110SMatt Spinler std::optional<std::string> lc;
14123bdd0110SMatt Spinler if (!locCode.empty())
14133bdd0110SMatt Spinler {
14143bdd0110SMatt Spinler lc = locCode;
14153bdd0110SMatt Spinler }
14163bdd0110SMatt Spinler
1417b8cb60feSMatt Spinler addInventoryCallout(inventoryPath, priority, lc, dataIface, mrus);
1418afa2c799SMatt Spinler
1419afa2c799SMatt Spinler if (jsonCallout.contains("Deconfigured"))
1420afa2c799SMatt Spinler {
1421afa2c799SMatt Spinler if (jsonCallout.at("Deconfigured").get<bool>())
1422afa2c799SMatt Spinler {
1423afa2c799SMatt Spinler setErrorStatusFlag(ErrorStatusFlags::deconfigured);
1424afa2c799SMatt Spinler }
1425afa2c799SMatt Spinler }
1426afa2c799SMatt Spinler
1427afa2c799SMatt Spinler if (jsonCallout.contains("Guarded"))
1428afa2c799SMatt Spinler {
1429afa2c799SMatt Spinler if (jsonCallout.at("Guarded").get<bool>())
1430afa2c799SMatt Spinler {
1431afa2c799SMatt Spinler setErrorStatusFlag(ErrorStatusFlags::guarded);
1432afa2c799SMatt Spinler }
1433afa2c799SMatt Spinler }
14343bdd0110SMatt Spinler }
14353bdd0110SMatt Spinler
14363bdd0110SMatt Spinler if (callout)
14373bdd0110SMatt Spinler {
14383bdd0110SMatt Spinler createCalloutsObject();
14393bdd0110SMatt Spinler _callouts->addCallout(std::move(callout));
14403bdd0110SMatt Spinler }
14413bdd0110SMatt Spinler }
14423bdd0110SMatt Spinler
getPriorityFromJSON(const nlohmann::json & json)14433bdd0110SMatt Spinler CalloutPriority SRC::getPriorityFromJSON(const nlohmann::json& json)
14443bdd0110SMatt Spinler {
14453bdd0110SMatt Spinler // Looks like:
14463bdd0110SMatt Spinler // {
14473bdd0110SMatt Spinler // "Priority": "H"
14483bdd0110SMatt Spinler // }
14493bdd0110SMatt Spinler auto p = json.at("Priority").get<std::string>();
14503bdd0110SMatt Spinler if (p.empty())
14513bdd0110SMatt Spinler {
14523bdd0110SMatt Spinler throw std::runtime_error{"Priority field in callout is empty"};
14533bdd0110SMatt Spinler }
14543bdd0110SMatt Spinler
14553bdd0110SMatt Spinler auto priority = static_cast<CalloutPriority>(p.front());
14563bdd0110SMatt Spinler
14573bdd0110SMatt Spinler // Validate it
14583bdd0110SMatt Spinler auto priorityIt = pv::findByValue(static_cast<uint32_t>(priority),
14593bdd0110SMatt Spinler pv::calloutPriorityValues);
14603bdd0110SMatt Spinler if (priorityIt == pv::calloutPriorityValues.end())
14613bdd0110SMatt Spinler {
14623bdd0110SMatt Spinler throw std::runtime_error{
14631aa90d49SJayanth Othayoth std::format("Invalid priority '{}' found in JSON callout", p)};
14643bdd0110SMatt Spinler }
14653bdd0110SMatt Spinler
14663bdd0110SMatt Spinler return priority;
14675a90a95bSMatt Spinler }
14685a90a95bSMatt Spinler
getMRUsFromJSON(const nlohmann::json & mruJSON)146925291157SPatrick Williams std::vector<src::MRU::MRUCallout> SRC::getMRUsFromJSON(
147025291157SPatrick Williams const nlohmann::json& mruJSON)
1471b8cb60feSMatt Spinler {
1472b8cb60feSMatt Spinler std::vector<src::MRU::MRUCallout> mrus;
1473b8cb60feSMatt Spinler
1474b8cb60feSMatt Spinler // Looks like:
1475b8cb60feSMatt Spinler // [
1476b8cb60feSMatt Spinler // {
1477b8cb60feSMatt Spinler // "ID": 100,
1478b8cb60feSMatt Spinler // "Priority": "H"
1479b8cb60feSMatt Spinler // }
1480b8cb60feSMatt Spinler // ]
1481b8cb60feSMatt Spinler if (!mruJSON.is_array())
1482b8cb60feSMatt Spinler {
1483b8cb60feSMatt Spinler addDebugData("MRU callout JSON is not an array");
1484b8cb60feSMatt Spinler return mrus;
1485b8cb60feSMatt Spinler }
1486b8cb60feSMatt Spinler
1487b8cb60feSMatt Spinler for (const auto& mruCallout : mruJSON)
1488b8cb60feSMatt Spinler {
1489b8cb60feSMatt Spinler try
1490b8cb60feSMatt Spinler {
1491b8cb60feSMatt Spinler auto priority = getPriorityFromJSON(mruCallout);
1492b8cb60feSMatt Spinler auto id = mruCallout.at("ID").get<uint32_t>();
1493b8cb60feSMatt Spinler
1494b8cb60feSMatt Spinler src::MRU::MRUCallout mru{static_cast<uint32_t>(priority), id};
1495b8cb60feSMatt Spinler mrus.push_back(std::move(mru));
1496b8cb60feSMatt Spinler }
1497b8cb60feSMatt Spinler catch (const std::exception& e)
1498b8cb60feSMatt Spinler {
14991aa90d49SJayanth Othayoth addDebugData(std::format("Invalid MRU entry in JSON: {}: {}",
1500b8cb60feSMatt Spinler mruCallout.dump(), e.what()));
1501b8cb60feSMatt Spinler }
1502b8cb60feSMatt Spinler }
1503b8cb60feSMatt Spinler
1504b8cb60feSMatt Spinler return mrus;
1505b8cb60feSMatt Spinler }
1506b8cb60feSMatt Spinler
getSrcStruct()15073e274432SSumit Kumar std::vector<uint8_t> SRC::getSrcStruct()
15083e274432SSumit Kumar {
15093e274432SSumit Kumar std::vector<uint8_t> data;
15103e274432SSumit Kumar Stream stream{data};
15113e274432SSumit Kumar
15123e274432SSumit Kumar //------ Ref section 4.3 in PEL doc---
15133e274432SSumit Kumar //------ SRC Structure 40 bytes-------
15143e274432SSumit Kumar // Byte-0 | Byte-1 | Byte-2 | Byte-3 |
15153e274432SSumit Kumar // -----------------------------------
15163e274432SSumit Kumar // 02 | 08 | 00 | 09 | ==> Header
15173e274432SSumit Kumar // 00 | 00 | 00 | 48 | ==> Header
15183e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-2
15193e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-3
15203e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-4
15213e274432SSumit Kumar // 20 | 00 | 00 | 00 | ==> Hex data word-5
15223e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-6
15233e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-7
15243e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-8
15253e274432SSumit Kumar // 00 | 00 | 00 | 00 | ==> Hex data word-9
15263e274432SSumit Kumar // -----------------------------------
15273e274432SSumit Kumar // ASCII string - 8 bytes |
15283e274432SSumit Kumar // -----------------------------------
15293e274432SSumit Kumar // ASCII space NULL - 24 bytes |
15303e274432SSumit Kumar // -----------------------------------
15313e274432SSumit Kumar //_size = Base SRC struct: 8 byte header + hex data section + ASCII string
15323e274432SSumit Kumar
15333e274432SSumit Kumar uint8_t flags = (_flags | postOPPanel);
15343e274432SSumit Kumar
15353e274432SSumit Kumar stream << _version << flags << _reserved1B << _wordCount << _reserved2B
15363e274432SSumit Kumar << _size;
15373e274432SSumit Kumar
15383e274432SSumit Kumar for (auto& word : _hexData)
15393e274432SSumit Kumar {
15403e274432SSumit Kumar stream << word;
15413e274432SSumit Kumar }
15423e274432SSumit Kumar
15433e274432SSumit Kumar _asciiString->flatten(stream);
15443e274432SSumit Kumar
15453e274432SSumit Kumar return data;
15463e274432SSumit Kumar }
15473e274432SSumit Kumar
setProgressCode(const DataInterfaceBase & dataIface)1548875b6c7bSVijay Lobo void SRC::setProgressCode(const DataInterfaceBase& dataIface)
1549875b6c7bSVijay Lobo {
1550875b6c7bSVijay Lobo std::vector<uint8_t> progressSRC;
1551875b6c7bSVijay Lobo
1552875b6c7bSVijay Lobo try
1553875b6c7bSVijay Lobo {
1554875b6c7bSVijay Lobo progressSRC = dataIface.getRawProgressSRC();
1555875b6c7bSVijay Lobo }
1556875b6c7bSVijay Lobo catch (const std::exception& e)
1557875b6c7bSVijay Lobo {
15580bacc8efSMatt Spinler lg2::error("Error getting progress code: {ERROR}", "ERROR", e);
1559875b6c7bSVijay Lobo return;
1560875b6c7bSVijay Lobo }
1561875b6c7bSVijay Lobo
1562875b6c7bSVijay Lobo _hexData[2] = getProgressCode(progressSRC);
1563875b6c7bSVijay Lobo }
1564875b6c7bSVijay Lobo
getProgressCode(std::vector<uint8_t> & rawProgressSRC)1565875b6c7bSVijay Lobo uint32_t SRC::getProgressCode(std::vector<uint8_t>& rawProgressSRC)
1566875b6c7bSVijay Lobo {
1567875b6c7bSVijay Lobo uint32_t progressCode = 0;
1568875b6c7bSVijay Lobo
1569875b6c7bSVijay Lobo // A valid progress SRC is at least 72 bytes
1570875b6c7bSVijay Lobo if (rawProgressSRC.size() < 72)
1571875b6c7bSVijay Lobo {
1572875b6c7bSVijay Lobo return progressCode;
1573875b6c7bSVijay Lobo }
1574875b6c7bSVijay Lobo
1575875b6c7bSVijay Lobo try
1576875b6c7bSVijay Lobo {
1577875b6c7bSVijay Lobo // The ASCII string field in progress SRCs starts at offset 40.
1578875b6c7bSVijay Lobo // Take the first 8 characters to put in the uint32:
1579875b6c7bSVijay Lobo // "CC009189" -> 0xCC009189
1580875b6c7bSVijay Lobo Stream stream{rawProgressSRC, 40};
1581875b6c7bSVijay Lobo src::AsciiString aString{stream};
1582875b6c7bSVijay Lobo auto progressCodeString = aString.get().substr(0, 8);
1583875b6c7bSVijay Lobo
1584875b6c7bSVijay Lobo if (std::all_of(progressCodeString.begin(), progressCodeString.end(),
1585875b6c7bSVijay Lobo [](char c) {
1586875b6c7bSVijay Lobo return std::isxdigit(static_cast<unsigned char>(c));
1587875b6c7bSVijay Lobo }))
1588875b6c7bSVijay Lobo {
1589875b6c7bSVijay Lobo progressCode = std::stoul(progressCodeString, nullptr, 16);
1590875b6c7bSVijay Lobo }
1591875b6c7bSVijay Lobo }
1592875b6c7bSVijay Lobo catch (const std::exception& e)
1593875b6c7bSVijay Lobo {}
1594875b6c7bSVijay Lobo
1595875b6c7bSVijay Lobo return progressCode;
1596875b6c7bSVijay Lobo }
1597875b6c7bSVijay Lobo
1598f9bae185SMatt Spinler } // namespace pels
1599f9bae185SMatt Spinler } // namespace openpower
1600