1acb7c106SMatt Spinler /**
2acb7c106SMatt Spinler * Copyright © 2020 IBM Corporation
3acb7c106SMatt Spinler *
4acb7c106SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License");
5acb7c106SMatt Spinler * you may not use this file except in compliance with the License.
6acb7c106SMatt Spinler * You may obtain a copy of the License at
7acb7c106SMatt Spinler *
8acb7c106SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0
9acb7c106SMatt Spinler *
10acb7c106SMatt Spinler * Unless required by applicable law or agreed to in writing, software
11acb7c106SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS,
12acb7c106SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13acb7c106SMatt Spinler * See the License for the specific language governing permissions and
14acb7c106SMatt Spinler * limitations under the License.
15acb7c106SMatt Spinler */
16acb7c106SMatt Spinler
17acb7c106SMatt Spinler #include "user_data_json.hpp"
18acb7c106SMatt Spinler
19bebeb948SHarisuddin Mohamed Isa #include "json_utils.hpp"
20acb7c106SMatt Spinler #include "pel_types.hpp"
21bebeb948SHarisuddin Mohamed Isa #include "pel_values.hpp"
2218207145SMatt Spinler #include "stream.hpp"
23acb7c106SMatt Spinler #include "user_data_formats.hpp"
24acb7c106SMatt Spinler
25f67bafd0SHarisuddin Mohamed Isa #include <Python.h>
26f67bafd0SHarisuddin Mohamed Isa
27acb7c106SMatt Spinler #include <nlohmann/json.hpp>
287cc3aea3SMatt Spinler #include <phosphor-logging/lg2.hpp>
292544b419SPatrick Williams
302544b419SPatrick Williams #include <iomanip>
31acb7c106SMatt Spinler #include <sstream>
32acb7c106SMatt Spinler
33acb7c106SMatt Spinler namespace openpower::pels::user_data
34acb7c106SMatt Spinler {
35bebeb948SHarisuddin Mohamed Isa namespace pv = openpower::pels::pel_values;
36516935a5SSumit Kumar using orderedJSON = nlohmann::ordered_json;
37acb7c106SMatt Spinler
pyDecRef(PyObject * pyObj)38f67bafd0SHarisuddin Mohamed Isa void pyDecRef(PyObject* pyObj)
39f67bafd0SHarisuddin Mohamed Isa {
40f67bafd0SHarisuddin Mohamed Isa Py_XDECREF(pyObj);
41f67bafd0SHarisuddin Mohamed Isa }
42f67bafd0SHarisuddin Mohamed Isa
43acb7c106SMatt Spinler /**
44acb7c106SMatt Spinler * @brief Returns a JSON string for use by PEL::printSectionInJSON().
45acb7c106SMatt Spinler *
46acb7c106SMatt Spinler * The returning string will contain a JSON object, but without
47acb7c106SMatt Spinler * the outer {}. If the input JSON isn't a JSON object (dict), then
48acb7c106SMatt Spinler * one will be created with the input added to a 'Data' key.
49acb7c106SMatt Spinler *
50b832aa5eSMatt Spinler * @param[in] creatorID - The creator ID for the PEL
51b832aa5eSMatt Spinler *
52acb7c106SMatt Spinler * @param[in] json - The JSON to convert to a string
53acb7c106SMatt Spinler *
54acb7c106SMatt Spinler * @return std::string - The JSON string
55acb7c106SMatt Spinler */
prettyJSON(uint16_t componentID,uint8_t subType,uint8_t version,uint8_t creatorID,const orderedJSON & json)56acb7c106SMatt Spinler std::string prettyJSON(uint16_t componentID, uint8_t subType, uint8_t version,
57b832aa5eSMatt Spinler uint8_t creatorID, const orderedJSON& json)
58acb7c106SMatt Spinler {
59516935a5SSumit Kumar orderedJSON output;
60bebeb948SHarisuddin Mohamed Isa output[pv::sectionVer] = std::to_string(version);
61bebeb948SHarisuddin Mohamed Isa output[pv::subSection] = std::to_string(subType);
62b832aa5eSMatt Spinler output[pv::createdBy] = getComponentName(componentID, creatorID);
63acb7c106SMatt Spinler
64acb7c106SMatt Spinler if (!json.is_object())
65acb7c106SMatt Spinler {
66acb7c106SMatt Spinler output["Data"] = json;
67acb7c106SMatt Spinler }
68acb7c106SMatt Spinler else
69acb7c106SMatt Spinler {
70acb7c106SMatt Spinler for (const auto& [key, value] : json.items())
71acb7c106SMatt Spinler {
72acb7c106SMatt Spinler output[key] = value;
73acb7c106SMatt Spinler }
74acb7c106SMatt Spinler }
75acb7c106SMatt Spinler
76acb7c106SMatt Spinler // Let nlohmann do the pretty printing.
77acb7c106SMatt Spinler std::stringstream stream;
78acb7c106SMatt Spinler stream << std::setw(4) << output;
79acb7c106SMatt Spinler
80acb7c106SMatt Spinler auto jsonString = stream.str();
81acb7c106SMatt Spinler
82acb7c106SMatt Spinler // Now it looks like:
83acb7c106SMatt Spinler // {
84acb7c106SMatt Spinler // "Section Version": ...
85acb7c106SMatt Spinler // ...
86acb7c106SMatt Spinler // }
87acb7c106SMatt Spinler
88acb7c106SMatt Spinler // Since PEL::printSectionInJSON() will supply the outer { }s,
89acb7c106SMatt Spinler // remove the existing ones.
90acb7c106SMatt Spinler
91acb7c106SMatt Spinler // Replace the { and the following newline, and the } and its
92acb7c106SMatt Spinler // preceeding newline.
93acb7c106SMatt Spinler jsonString.erase(0, 2);
94acb7c106SMatt Spinler
95acb7c106SMatt Spinler auto pos = jsonString.find_last_of('}');
96acb7c106SMatt Spinler jsonString.erase(pos - 1);
97acb7c106SMatt Spinler
98acb7c106SMatt Spinler return jsonString;
99acb7c106SMatt Spinler }
100acb7c106SMatt Spinler
101acb7c106SMatt Spinler /**
10218207145SMatt Spinler * @brief Return a JSON string from the passed in CBOR data.
10318207145SMatt Spinler *
10418207145SMatt Spinler * @param[in] componentID - The comp ID from the UserData section header
10518207145SMatt Spinler * @param[in] subType - The subtype from the UserData section header
10618207145SMatt Spinler * @param[in] version - The version from the UserData section header
107b832aa5eSMatt Spinler * @param[in] creatorID - The creator ID for the PEL
10818207145SMatt Spinler * @param[in] data - The CBOR data
10918207145SMatt Spinler *
11018207145SMatt Spinler * @return std::string - The JSON string
11118207145SMatt Spinler */
getCBORJSON(uint16_t componentID,uint8_t subType,uint8_t version,uint8_t creatorID,const std::vector<uint8_t> & data)11218207145SMatt Spinler std::string getCBORJSON(uint16_t componentID, uint8_t subType, uint8_t version,
113b832aa5eSMatt Spinler uint8_t creatorID, const std::vector<uint8_t>& data)
11418207145SMatt Spinler {
11518207145SMatt Spinler // The CBOR parser needs the pad bytes added to 4 byte align
11618207145SMatt Spinler // removed. The number of bytes added to the pad is on the
11718207145SMatt Spinler // very end, so will remove both fields before parsing.
11818207145SMatt Spinler
11918207145SMatt Spinler // If the data vector is too short, an exception will get
12018207145SMatt Spinler // thrown which will be handled up the call stack.
12118207145SMatt Spinler
12218207145SMatt Spinler auto cborData = data;
12318207145SMatt Spinler uint32_t pad{};
12418207145SMatt Spinler
12518207145SMatt Spinler Stream stream{cborData};
12618207145SMatt Spinler stream.offset(cborData.size() - 4);
12718207145SMatt Spinler stream >> pad;
12818207145SMatt Spinler
12918207145SMatt Spinler if (cborData.size() > (pad + sizeof(pad)))
13018207145SMatt Spinler {
13118207145SMatt Spinler cborData.resize(data.size() - sizeof(pad) - pad);
13218207145SMatt Spinler }
13318207145SMatt Spinler
134bb1c1d5cSMatt Spinler orderedJSON json = orderedJSON::from_cbor(cborData);
13518207145SMatt Spinler
136b832aa5eSMatt Spinler return prettyJSON(componentID, subType, version, creatorID, json);
13718207145SMatt Spinler }
13818207145SMatt Spinler
13918207145SMatt Spinler /**
14018207145SMatt Spinler * @brief Return a JSON string from the passed in text data.
14118207145SMatt Spinler *
142aadf28f5SHarisuddin Mohamed Isa * The function breaks up the input text into a vector of strings with
143aadf28f5SHarisuddin Mohamed Isa * newline as separator and converts that into JSON. It will convert any
144aadf28f5SHarisuddin Mohamed Isa * unprintable characters to periods.
14518207145SMatt Spinler *
14618207145SMatt Spinler * @param[in] componentID - The comp ID from the UserData section header
14718207145SMatt Spinler * @param[in] subType - The subtype from the UserData section header
14818207145SMatt Spinler * @param[in] version - The version from the UserData section header
149b832aa5eSMatt Spinler * @param[in] creatorID - The creator ID for the PEL
15018207145SMatt Spinler * @param[in] data - The CBOR data
15118207145SMatt Spinler *
15218207145SMatt Spinler * @return std::string - The JSON string
15318207145SMatt Spinler */
getTextJSON(uint16_t componentID,uint8_t subType,uint8_t version,uint8_t creatorID,const std::vector<uint8_t> & data)15418207145SMatt Spinler std::string getTextJSON(uint16_t componentID, uint8_t subType, uint8_t version,
155b832aa5eSMatt Spinler uint8_t creatorID, const std::vector<uint8_t>& data)
15618207145SMatt Spinler {
15718207145SMatt Spinler std::vector<std::string> text;
15818207145SMatt Spinler size_t startPos = 0;
15918207145SMatt Spinler
160aadf28f5SHarisuddin Mohamed Isa // Converts any unprintable characters to periods
16118207145SMatt Spinler auto validate = [](char& ch) {
16218207145SMatt Spinler if ((ch < ' ') || (ch > '~'))
16318207145SMatt Spinler {
16418207145SMatt Spinler ch = '.';
16518207145SMatt Spinler }
16618207145SMatt Spinler };
16718207145SMatt Spinler
168aadf28f5SHarisuddin Mohamed Isa // Break up the data into an array of strings with newline as separator
169aadf28f5SHarisuddin Mohamed Isa for (size_t pos = 0; pos < data.size(); ++pos)
17018207145SMatt Spinler {
171aadf28f5SHarisuddin Mohamed Isa if (data[pos] == '\n')
172aadf28f5SHarisuddin Mohamed Isa {
173aadf28f5SHarisuddin Mohamed Isa std::string line{reinterpret_cast<const char*>(&data[startPos]),
174aadf28f5SHarisuddin Mohamed Isa pos - startPos};
175aadf28f5SHarisuddin Mohamed Isa std::for_each(line.begin(), line.end(), validate);
176aadf28f5SHarisuddin Mohamed Isa text.push_back(std::move(line));
177aadf28f5SHarisuddin Mohamed Isa startPos = pos + 1;
178aadf28f5SHarisuddin Mohamed Isa }
179aadf28f5SHarisuddin Mohamed Isa }
180aadf28f5SHarisuddin Mohamed Isa if (startPos < data.size())
18118207145SMatt Spinler {
18218207145SMatt Spinler std::string line{reinterpret_cast<const char*>(&data[startPos]),
18318207145SMatt Spinler data.size() - startPos};
18418207145SMatt Spinler std::for_each(line.begin(), line.end(), validate);
18518207145SMatt Spinler text.push_back(std::move(line));
18618207145SMatt Spinler }
18718207145SMatt Spinler
188516935a5SSumit Kumar orderedJSON json = text;
189b832aa5eSMatt Spinler return prettyJSON(componentID, subType, version, creatorID, json);
19018207145SMatt Spinler }
19118207145SMatt Spinler
19218207145SMatt Spinler /**
193acb7c106SMatt Spinler * @brief Convert to an appropriate JSON string as the data is one of
194acb7c106SMatt Spinler * the formats that we natively support.
195acb7c106SMatt Spinler *
196acb7c106SMatt Spinler * @param[in] componentID - The comp ID from the UserData section header
197acb7c106SMatt Spinler * @param[in] subType - The subtype from the UserData section header
198acb7c106SMatt Spinler * @param[in] version - The version from the UserData section header
199acb7c106SMatt Spinler * @param[in] data - The data itself
200acb7c106SMatt Spinler *
201acb7c106SMatt Spinler * @return std::optional<std::string> - The JSON string if it could be created,
202acb7c106SMatt Spinler * else std::nullopt.
203acb7c106SMatt Spinler */
getBuiltinFormatJSON(uint16_t componentID,uint8_t subType,uint8_t version,const std::vector<uint8_t> & data,uint8_t creatorID)204*25291157SPatrick Williams std::optional<std::string> getBuiltinFormatJSON(
205*25291157SPatrick Williams uint16_t componentID, uint8_t subType, uint8_t version,
206b832aa5eSMatt Spinler const std::vector<uint8_t>& data, uint8_t creatorID)
207acb7c106SMatt Spinler {
208acb7c106SMatt Spinler switch (subType)
209acb7c106SMatt Spinler {
210acb7c106SMatt Spinler case static_cast<uint8_t>(UserDataFormat::json):
211acb7c106SMatt Spinler {
212acb7c106SMatt Spinler std::string jsonString{data.begin(), data.begin() + data.size()};
213acb7c106SMatt Spinler
214bb1c1d5cSMatt Spinler orderedJSON json = orderedJSON::parse(jsonString);
215acb7c106SMatt Spinler
216b832aa5eSMatt Spinler return prettyJSON(componentID, subType, version, creatorID, json);
217acb7c106SMatt Spinler }
21818207145SMatt Spinler case static_cast<uint8_t>(UserDataFormat::cbor):
21918207145SMatt Spinler {
220b832aa5eSMatt Spinler return getCBORJSON(componentID, subType, version, creatorID, data);
22118207145SMatt Spinler }
22218207145SMatt Spinler case static_cast<uint8_t>(UserDataFormat::text):
22318207145SMatt Spinler {
224b832aa5eSMatt Spinler return getTextJSON(componentID, subType, version, creatorID, data);
22518207145SMatt Spinler }
226acb7c106SMatt Spinler default:
227acb7c106SMatt Spinler break;
228acb7c106SMatt Spinler }
229acb7c106SMatt Spinler return std::nullopt;
230acb7c106SMatt Spinler }
231acb7c106SMatt Spinler
232f67bafd0SHarisuddin Mohamed Isa /**
233f67bafd0SHarisuddin Mohamed Isa * @brief Call Python modules to parse the data into a JSON string
234f67bafd0SHarisuddin Mohamed Isa *
235f67bafd0SHarisuddin Mohamed Isa * The module to call is based on the Creator Subsystem ID and the Component
236f67bafd0SHarisuddin Mohamed Isa * ID under the namespace "udparsers". For example: "udparsers.xyyyy.xyyyy"
237f67bafd0SHarisuddin Mohamed Isa * where "x" is the Creator Subsystem ID and "yyyy" is the Component ID.
238f67bafd0SHarisuddin Mohamed Isa *
239f67bafd0SHarisuddin Mohamed Isa * All modules must provide the following:
240f67bafd0SHarisuddin Mohamed Isa * Function: parseUDToJson
241f67bafd0SHarisuddin Mohamed Isa * Argument list:
242f67bafd0SHarisuddin Mohamed Isa * 1. (int) Sub-section type
243f67bafd0SHarisuddin Mohamed Isa * 2. (int) Section version
244f67bafd0SHarisuddin Mohamed Isa * 3. (memoryview): Data
245f67bafd0SHarisuddin Mohamed Isa *-Return data:
246f67bafd0SHarisuddin Mohamed Isa * 1. (str) JSON string
247f67bafd0SHarisuddin Mohamed Isa *
248f67bafd0SHarisuddin Mohamed Isa * @param[in] componentID - The comp ID from the UserData section header
249f67bafd0SHarisuddin Mohamed Isa * @param[in] subType - The subtype from the UserData section header
250f67bafd0SHarisuddin Mohamed Isa * @param[in] version - The version from the UserData section header
251f67bafd0SHarisuddin Mohamed Isa * @param[in] data - The data itself
252f67bafd0SHarisuddin Mohamed Isa * @param[in] creatorID - The creatorID from the PrivateHeader section
253f67bafd0SHarisuddin Mohamed Isa * @return std::optional<std::string> - The JSON string if it could be created,
254f67bafd0SHarisuddin Mohamed Isa * else std::nullopt
255f67bafd0SHarisuddin Mohamed Isa */
getPythonJSON(uint16_t componentID,uint8_t subType,uint8_t version,const std::vector<uint8_t> & data,uint8_t creatorID)256*25291157SPatrick Williams std::optional<std::string> getPythonJSON(
257*25291157SPatrick Williams uint16_t componentID, uint8_t subType, uint8_t version,
258075c7923SPatrick Williams const std::vector<uint8_t>& data, uint8_t creatorID)
259f67bafd0SHarisuddin Mohamed Isa {
260be952d2eSMatt Spinler PyObject *pName, *pModule, *eType, *eValue, *eTraceback, *pKey;
261f67bafd0SHarisuddin Mohamed Isa std::string pErrStr;
262f67bafd0SHarisuddin Mohamed Isa std::string module = getNumberString("%c", tolower(creatorID)) +
263f67bafd0SHarisuddin Mohamed Isa getNumberString("%04x", componentID);
264f67bafd0SHarisuddin Mohamed Isa pName = PyUnicode_FromString(
265f67bafd0SHarisuddin Mohamed Isa std::string("udparsers." + module + "." + module).c_str());
266f67bafd0SHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> modNamePtr(pName, &pyDecRef);
267f67bafd0SHarisuddin Mohamed Isa pModule = PyImport_Import(pName);
268f67bafd0SHarisuddin Mohamed Isa if (pModule == NULL)
269f67bafd0SHarisuddin Mohamed Isa {
270f67bafd0SHarisuddin Mohamed Isa pErrStr = "No error string found";
271f67bafd0SHarisuddin Mohamed Isa PyErr_Fetch(&eType, &eValue, &eTraceback);
272d5c31366SHarisuddin Mohamed Isa if (eType)
273d5c31366SHarisuddin Mohamed Isa {
274d5c31366SHarisuddin Mohamed Isa Py_XDECREF(eType);
275d5c31366SHarisuddin Mohamed Isa }
276d5c31366SHarisuddin Mohamed Isa if (eTraceback)
277d5c31366SHarisuddin Mohamed Isa {
278d5c31366SHarisuddin Mohamed Isa Py_XDECREF(eTraceback);
279d5c31366SHarisuddin Mohamed Isa }
280f67bafd0SHarisuddin Mohamed Isa if (eValue)
281f67bafd0SHarisuddin Mohamed Isa {
282f67bafd0SHarisuddin Mohamed Isa PyObject* pStr = PyObject_Str(eValue);
283d5c31366SHarisuddin Mohamed Isa Py_XDECREF(eValue);
284f67bafd0SHarisuddin Mohamed Isa if (pStr)
285f67bafd0SHarisuddin Mohamed Isa {
286f67bafd0SHarisuddin Mohamed Isa pErrStr = PyUnicode_AsUTF8(pStr);
287f67bafd0SHarisuddin Mohamed Isa Py_XDECREF(pStr);
288f67bafd0SHarisuddin Mohamed Isa }
289f67bafd0SHarisuddin Mohamed Isa }
290d5c31366SHarisuddin Mohamed Isa }
291f67bafd0SHarisuddin Mohamed Isa else
292f67bafd0SHarisuddin Mohamed Isa {
293075c7923SPatrick Williams std::unique_ptr<PyObject, decltype(&pyDecRef)> modPtr(
294075c7923SPatrick Williams pModule, &pyDecRef);
295d5c31366SHarisuddin Mohamed Isa std::string funcToCall = "parseUDToJson";
296d5c31366SHarisuddin Mohamed Isa pKey = PyUnicode_FromString(funcToCall.c_str());
297d5c31366SHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> keyPtr(pKey, &pyDecRef);
298be952d2eSMatt Spinler PyObject* pDict = PyModule_GetDict(pModule);
299d5c31366SHarisuddin Mohamed Isa Py_INCREF(pDict);
300d5c31366SHarisuddin Mohamed Isa if (!PyDict_Contains(pDict, pKey))
301d5c31366SHarisuddin Mohamed Isa {
302d5c31366SHarisuddin Mohamed Isa Py_DECREF(pDict);
3037cc3aea3SMatt Spinler lg2::error("Python module error. Function missing: {FUNC}, "
3047cc3aea3SMatt Spinler "module = {MODULE}, subtype = {SUBTYPE}, "
3057cc3aea3SMatt Spinler "version = {VERSION}, data length = {LEN}",
3067cc3aea3SMatt Spinler "FUNC", funcToCall, "MODULE", module, "SUBTYPE", subType,
3077cc3aea3SMatt Spinler "VERSION", version, "LEN", data.size());
308d5c31366SHarisuddin Mohamed Isa return std::nullopt;
309d5c31366SHarisuddin Mohamed Isa }
310be952d2eSMatt Spinler PyObject* pFunc = PyDict_GetItemString(pDict, funcToCall.c_str());
311d5c31366SHarisuddin Mohamed Isa Py_DECREF(pDict);
312d5c31366SHarisuddin Mohamed Isa Py_INCREF(pFunc);
313f67bafd0SHarisuddin Mohamed Isa if (PyCallable_Check(pFunc))
314f67bafd0SHarisuddin Mohamed Isa {
315f67bafd0SHarisuddin Mohamed Isa auto ud = data.data();
316be952d2eSMatt Spinler PyObject* pArgs = PyTuple_New(3);
317075c7923SPatrick Williams std::unique_ptr<PyObject, decltype(&pyDecRef)> argPtr(
318075c7923SPatrick Williams pArgs, &pyDecRef);
319f67bafd0SHarisuddin Mohamed Isa PyTuple_SetItem(pArgs, 0,
320f67bafd0SHarisuddin Mohamed Isa PyLong_FromUnsignedLong((unsigned long)subType));
321f67bafd0SHarisuddin Mohamed Isa PyTuple_SetItem(pArgs, 1,
322f67bafd0SHarisuddin Mohamed Isa PyLong_FromUnsignedLong((unsigned long)version));
323be952d2eSMatt Spinler PyObject* pData = PyMemoryView_FromMemory(
324f67bafd0SHarisuddin Mohamed Isa reinterpret_cast<char*>(const_cast<unsigned char*>(ud)),
325f67bafd0SHarisuddin Mohamed Isa data.size(), PyBUF_READ);
326f67bafd0SHarisuddin Mohamed Isa PyTuple_SetItem(pArgs, 2, pData);
327be952d2eSMatt Spinler PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
328d5c31366SHarisuddin Mohamed Isa Py_DECREF(pFunc);
329f67bafd0SHarisuddin Mohamed Isa if (pResult)
330f67bafd0SHarisuddin Mohamed Isa {
331d5c31366SHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> resPtr(
332d5c31366SHarisuddin Mohamed Isa pResult, &pyDecRef);
333075c7923SPatrick Williams PyObject* pBytes =
334075c7923SPatrick Williams PyUnicode_AsEncodedString(pResult, "utf-8", "~E~");
335f67bafd0SHarisuddin Mohamed Isa std::unique_ptr<PyObject, decltype(&pyDecRef)> pyBytePtr(
336f67bafd0SHarisuddin Mohamed Isa pBytes, &pyDecRef);
337f67bafd0SHarisuddin Mohamed Isa const char* output = PyBytes_AS_STRING(pBytes);
338f67bafd0SHarisuddin Mohamed Isa try
339f67bafd0SHarisuddin Mohamed Isa {
340bb1c1d5cSMatt Spinler orderedJSON json = orderedJSON::parse(output);
341d5c31366SHarisuddin Mohamed Isa if ((json.is_object() && !json.empty()) ||
342d5c31366SHarisuddin Mohamed Isa (json.is_array() && json.size() > 0) ||
343d5c31366SHarisuddin Mohamed Isa (json.is_string() && json != ""))
344d5c31366SHarisuddin Mohamed Isa {
345b832aa5eSMatt Spinler return prettyJSON(componentID, subType, version,
346b832aa5eSMatt Spinler creatorID, json);
347f67bafd0SHarisuddin Mohamed Isa }
348d5c31366SHarisuddin Mohamed Isa }
34966491c61SPatrick Williams catch (const std::exception& e)
350f67bafd0SHarisuddin Mohamed Isa {
3517cc3aea3SMatt Spinler lg2::error("Bad JSON from parser. Error = {ERROR}, "
3527cc3aea3SMatt Spinler "module = {MODULE}, subtype = {SUBTYPE}, "
3537cc3aea3SMatt Spinler "version = {VERSION}, data length = {LEN}",
3547cc3aea3SMatt Spinler "ERROR", e, "MODULE", module, "SUBTYPE", subType,
3557cc3aea3SMatt Spinler "VERSION", version, "LEN", data.size());
356f67bafd0SHarisuddin Mohamed Isa return std::nullopt;
357f67bafd0SHarisuddin Mohamed Isa }
358f67bafd0SHarisuddin Mohamed Isa }
359f67bafd0SHarisuddin Mohamed Isa else
360f67bafd0SHarisuddin Mohamed Isa {
361f67bafd0SHarisuddin Mohamed Isa pErrStr = "No error string found";
362f67bafd0SHarisuddin Mohamed Isa PyErr_Fetch(&eType, &eValue, &eTraceback);
363d5c31366SHarisuddin Mohamed Isa if (eType)
364d5c31366SHarisuddin Mohamed Isa {
365d5c31366SHarisuddin Mohamed Isa Py_XDECREF(eType);
366d5c31366SHarisuddin Mohamed Isa }
367d5c31366SHarisuddin Mohamed Isa if (eTraceback)
368d5c31366SHarisuddin Mohamed Isa {
369d5c31366SHarisuddin Mohamed Isa Py_XDECREF(eTraceback);
370d5c31366SHarisuddin Mohamed Isa }
371f67bafd0SHarisuddin Mohamed Isa if (eValue)
372f67bafd0SHarisuddin Mohamed Isa {
373f67bafd0SHarisuddin Mohamed Isa PyObject* pStr = PyObject_Str(eValue);
374d5c31366SHarisuddin Mohamed Isa Py_XDECREF(eValue);
375f67bafd0SHarisuddin Mohamed Isa if (pStr)
376f67bafd0SHarisuddin Mohamed Isa {
377f67bafd0SHarisuddin Mohamed Isa pErrStr = PyUnicode_AsUTF8(pStr);
378f67bafd0SHarisuddin Mohamed Isa Py_XDECREF(pStr);
379f67bafd0SHarisuddin Mohamed Isa }
380f67bafd0SHarisuddin Mohamed Isa }
381f67bafd0SHarisuddin Mohamed Isa }
382f67bafd0SHarisuddin Mohamed Isa }
383d5c31366SHarisuddin Mohamed Isa }
384f67bafd0SHarisuddin Mohamed Isa if (!pErrStr.empty())
385f67bafd0SHarisuddin Mohamed Isa {
3867cc3aea3SMatt Spinler lg2::debug("Python exception thrown by parser. Error = {ERROR}, "
3877cc3aea3SMatt Spinler "module = {MODULE}, subtype = {SUBTYPE}, "
3887cc3aea3SMatt Spinler "version = {VERSION}, data length = {LEN}",
3897cc3aea3SMatt Spinler "ERROR", pErrStr, "MODULE", module, "SUBTYPE", subType,
3907cc3aea3SMatt Spinler "VERSION", version, "LEN", data.size());
391f67bafd0SHarisuddin Mohamed Isa }
392f67bafd0SHarisuddin Mohamed Isa return std::nullopt;
393f67bafd0SHarisuddin Mohamed Isa }
394f67bafd0SHarisuddin Mohamed Isa
getJSON(uint16_t componentID,uint8_t subType,uint8_t version,const std::vector<uint8_t> & data,uint8_t creatorID,const std::vector<std::string> & plugins)395*25291157SPatrick Williams std::optional<std::string> getJSON(
396*25291157SPatrick Williams uint16_t componentID, uint8_t subType, uint8_t version,
397075c7923SPatrick Williams const std::vector<uint8_t>& data, uint8_t creatorID,
3983fdcd4e8SHarisuddin Mohamed Isa const std::vector<std::string>& plugins)
399acb7c106SMatt Spinler {
4003fdcd4e8SHarisuddin Mohamed Isa std::string subsystem = getNumberString("%c", tolower(creatorID));
4013fdcd4e8SHarisuddin Mohamed Isa std::string component = getNumberString("%04x", componentID);
402acb7c106SMatt Spinler try
403acb7c106SMatt Spinler {
404f67bafd0SHarisuddin Mohamed Isa if (pv::creatorIDs.at(getNumberString("%c", creatorID)) == "BMC" &&
405f67bafd0SHarisuddin Mohamed Isa componentID == static_cast<uint16_t>(ComponentID::phosphorLogging))
406acb7c106SMatt Spinler {
407b832aa5eSMatt Spinler return getBuiltinFormatJSON(componentID, subType, version, data,
408b832aa5eSMatt Spinler creatorID);
409f67bafd0SHarisuddin Mohamed Isa }
4103fdcd4e8SHarisuddin Mohamed Isa else if (std::find(plugins.begin(), plugins.end(),
4113fdcd4e8SHarisuddin Mohamed Isa subsystem + component) != plugins.end())
412f67bafd0SHarisuddin Mohamed Isa {
413f67bafd0SHarisuddin Mohamed Isa return getPythonJSON(componentID, subType, version, data,
414f67bafd0SHarisuddin Mohamed Isa creatorID);
415acb7c106SMatt Spinler }
416acb7c106SMatt Spinler }
41766491c61SPatrick Williams catch (const std::exception& e)
418acb7c106SMatt Spinler {
4197cc3aea3SMatt Spinler lg2::error("Failed parsing UserData. Error = {ERROR}, "
4207cc3aea3SMatt Spinler "component ID = {COMP_ID}, subtype = {SUBTYPE}, "
4217cc3aea3SMatt Spinler "version = {VERSION}, data length = {LEN}",
4227cc3aea3SMatt Spinler "ERROR", e, "COMP_ID", componentID, "SUBTYPE", subType,
4237cc3aea3SMatt Spinler "VERSION", version, "LEN", data.size());
424acb7c106SMatt Spinler }
425acb7c106SMatt Spinler
426acb7c106SMatt Spinler return std::nullopt;
427acb7c106SMatt Spinler }
428acb7c106SMatt Spinler
429acb7c106SMatt Spinler } // namespace openpower::pels::user_data
430