summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels/user_data_json.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/openpower-pels/user_data_json.cpp')
-rw-r--r--extensions/openpower-pels/user_data_json.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/extensions/openpower-pels/user_data_json.cpp b/extensions/openpower-pels/user_data_json.cpp
new file mode 100644
index 0000000..a86ccb3
--- /dev/null
+++ b/extensions/openpower-pels/user_data_json.cpp
@@ -0,0 +1,153 @@
+/**
+ * Copyright © 2020 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "user_data_json.hpp"
+
+#include "pel_types.hpp"
+#include "user_data_formats.hpp"
+
+#include <fifo_map.hpp>
+#include <iomanip>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sstream>
+
+namespace openpower::pels::user_data
+{
+
+using namespace phosphor::logging;
+
+// Use fifo_map as nlohmann::json's map. We are just ignoring the 'less'
+// compare. With this map the keys are kept in FIFO order.
+template <class K, class V, class dummy_compare, class A>
+using fifoMap = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
+using fifoJSON = nlohmann::basic_json<fifoMap>;
+
+/**
+ * @brief Returns a JSON string for use by PEL::printSectionInJSON().
+ *
+ * The returning string will contain a JSON object, but without
+ * the outer {}. If the input JSON isn't a JSON object (dict), then
+ * one will be created with the input added to a 'Data' key.
+ *
+ * @param[in] json - The JSON to convert to a string
+ *
+ * @return std::string - The JSON string
+ */
+std::string prettyJSON(uint16_t componentID, uint8_t subType, uint8_t version,
+ const fifoJSON& json)
+{
+ fifoJSON output;
+ output["Section Version"] = std::to_string(version);
+ output["Sub-section type"] = std::to_string(subType);
+
+ char value[10];
+ sprintf(value, "0x%04X", componentID);
+ output["Created by"] = std::string{value};
+
+ if (!json.is_object())
+ {
+ output["Data"] = json;
+ }
+ else
+ {
+ for (const auto& [key, value] : json.items())
+ {
+ output[key] = value;
+ }
+ }
+
+ // Let nlohmann do the pretty printing.
+ std::stringstream stream;
+ stream << std::setw(4) << output;
+
+ auto jsonString = stream.str();
+
+ // Now it looks like:
+ // {
+ // "Section Version": ...
+ // ...
+ // }
+
+ // Since PEL::printSectionInJSON() will supply the outer { }s,
+ // remove the existing ones.
+
+ // Replace the { and the following newline, and the } and its
+ // preceeding newline.
+ jsonString.erase(0, 2);
+
+ auto pos = jsonString.find_last_of('}');
+ jsonString.erase(pos - 1);
+
+ return jsonString;
+}
+
+/**
+ * @brief Convert to an appropriate JSON string as the data is one of
+ * the formats that we natively support.
+ *
+ * @param[in] componentID - The comp ID from the UserData section header
+ * @param[in] subType - The subtype from the UserData section header
+ * @param[in] version - The version from the UserData section header
+ * @param[in] data - The data itself
+ *
+ * @return std::optional<std::string> - The JSON string if it could be created,
+ * else std::nullopt.
+ */
+std::optional<std::string>
+ getBuiltinFormatJSON(uint16_t componentID, uint8_t subType, uint8_t version,
+ const std::vector<uint8_t>& data)
+{
+ switch (subType)
+ {
+ case static_cast<uint8_t>(UserDataFormat::json):
+ {
+ std::string jsonString{data.begin(), data.begin() + data.size()};
+
+ fifoJSON json = nlohmann::json::parse(jsonString);
+
+ return prettyJSON(componentID, subType, version, json);
+ }
+ default:
+ break;
+ }
+ return std::nullopt;
+}
+
+std::optional<std::string> getJSON(uint16_t componentID, uint8_t subType,
+ uint8_t version,
+ const std::vector<uint8_t>& data)
+{
+ try
+ {
+ switch (componentID)
+ {
+ case static_cast<uint16_t>(ComponentID::phosphorLogging):
+ return getBuiltinFormatJSON(componentID, subType, version,
+ data);
+ default:
+ break;
+ }
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>("Failed parsing UserData", entry("ERROR=%s", e.what()));
+ }
+
+ return std::nullopt;
+}
+
+} // namespace openpower::pels::user_data
OpenPOWER on IntegriCloud