PEL: Print list of PELs
PelTool commands for printing a list of PELs.
PEL list sample:
{
"0x50000004": {
"SRC": "BD8D1001",
"PLID": "0x50000004",
"CreatorID": "BMC",
"Subsystem": "bmc_firmware",
"Commit Time": "10/24/2019 15:50:08",
"Sev": "unrecoverable",
"CompID": "0x1000"
}
}
Change-Id: Ifd864a6561c09de098689195edcf107b3fe550e3
Signed-off-by: Aatir <aatrapps@gmail.com>
diff --git a/extensions/openpower-pels/pel_values.cpp b/extensions/openpower-pels/pel_values.cpp
index 775c0f5..8f5c1cd 100644
--- a/extensions/openpower-pels/pel_values.cpp
+++ b/extensions/openpower-pels/pel_values.cpp
@@ -239,6 +239,19 @@
{"S", "SLIC"}, {"B", "Hostboot"}, {"T", "OCC"}, {"M", "I/O Drawer"},
{"K", "Sapphire"}, {"P", "PowerNV"}};
+std::string getValue(const uint8_t field, const pel_values::PELValues& values)
+{
+
+ auto tmp = pel_values::findByValue(field, values);
+ if (tmp != values.end())
+ {
+ return std::get<pel_values::registryNamePos>(*tmp);
+ }
+ else
+ {
+ return "invalid";
+ }
+}
} // namespace pel_values
} // namespace pels
} // namespace openpower
diff --git a/extensions/openpower-pels/pel_values.hpp b/extensions/openpower-pels/pel_values.hpp
index 9d49dbe..8d86acf 100644
--- a/extensions/openpower-pels/pel_values.hpp
+++ b/extensions/openpower-pels/pel_values.hpp
@@ -25,6 +25,14 @@
using PELValues = std::vector<PELFieldValue>;
/**
+ * @brief Helper function to get values from lookup tables.
+ * @return std::string - the value
+ * @param[in] uint8_t - field to get value for
+ * @param[in] PELValues - lookup table
+ */
+std::string getValue(const uint8_t field, const pel_values::PELValues& values);
+
+/**
* @brief Find the desired entry in a PELValues table based on the
* field value.
*
diff --git a/extensions/openpower-pels/tools/peltool.cpp b/extensions/openpower-pels/tools/peltool.cpp
index 1208f24..041449e 100644
--- a/extensions/openpower-pels/tools/peltool.cpp
+++ b/extensions/openpower-pels/tools/peltool.cpp
@@ -13,15 +13,185 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "config.h"
+
+#include "../bcd_time.hpp"
#include "../pel.hpp"
+#include "../pel_types.hpp"
+#include "../pel_values.hpp"
#include <CLI/CLI.hpp>
+#include <bitset>
#include <iostream>
+#include <phosphor-logging/log.hpp>
+#include <regex>
#include <string>
+#include <xyz/openbmc_project/Common/File/error.hpp>
+namespace fs = std::filesystem;
using namespace phosphor::logging;
using namespace openpower::pels;
+namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
+namespace message = openpower::pels::message;
+namespace pv = openpower::pels::pel_values;
+std::string ltrim(const std::string& s)
+{
+ return std::regex_replace(s, std::regex("^\\s+"), std::string(""));
+}
+
+std::string rtrim(const std::string& s)
+{
+ return std::regex_replace(s, std::regex("\\s+$"), std::string(""));
+}
+
+std::string trim(const std::string& s)
+{
+ return ltrim(rtrim(s));
+}
+
+template <typename T>
+std::string genPELJSON(T itr)
+{
+ std::size_t found;
+ std::string val;
+ char tmpValStr[50];
+ std::string listStr;
+ char name[50];
+ sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", itr.second.yearMSB,
+ itr.second.yearLSB, itr.second.month, itr.second.day,
+ itr.second.hour, itr.second.minutes, itr.second.seconds,
+ itr.second.hundredths, itr.first);
+ std::string fileName(name);
+ fileName = EXTENSION_PERSIST_DIR "/pels/logs/" + fileName;
+ try
+ {
+ std::ifstream stream(fileName, std::ios::in | std::ios::binary);
+ std::vector<uint8_t> data((std::istreambuf_iterator<char>(stream)),
+ std::istreambuf_iterator<char>());
+ stream.close();
+ PEL pel{data};
+ if (pel.valid())
+ {
+ // id
+ sprintf(tmpValStr, "0x%X", pel.privateHeader().id());
+ val = std::string(tmpValStr);
+ listStr += "\t\"" + val + "\": {\n";
+ // ASCII
+ val = pel.primarySRC() ? pel.primarySRC().value()->asciiString()
+ : "No SRC";
+ listStr += "\t\t\"SRC\": \"" + trim(val) + "\",\n";
+ // platformid
+ sprintf(tmpValStr, "0x%X", pel.privateHeader().plid());
+ val = std::string(tmpValStr);
+ listStr += "\t\t\"PLID\": \"" + val + "\",\n";
+ // creatorid
+ sprintf(tmpValStr, "%c", pel.privateHeader().creatorID());
+ std::string creatorID(tmpValStr);
+ val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
+ : "Unknown Creator ID";
+ listStr += "\t\t\"CreatorID\": \"" + val + "\",\n";
+ // subsytem
+ std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
+ pel_values::subsystemValues);
+ listStr += "\t\t\"Subsystem\": \"" + subsystem + "\",\n";
+ // commit time
+ sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
+ pel.privateHeader().commitTimestamp().month,
+ pel.privateHeader().commitTimestamp().day,
+ pel.privateHeader().commitTimestamp().yearMSB,
+ pel.privateHeader().commitTimestamp().yearLSB,
+ pel.privateHeader().commitTimestamp().hour,
+ pel.privateHeader().commitTimestamp().minutes,
+ pel.privateHeader().commitTimestamp().seconds);
+ val = std::string(tmpValStr);
+ listStr += "\t\t\"Commit Time\": \"" + val + "\",\n";
+ // severity
+ std::string severity = pv::getValue(pel.userHeader().severity(),
+ pel_values::severityValues);
+ listStr += "\t\t\"Sev\": \"" + severity + "\",\n ";
+ // compID
+ sprintf(tmpValStr, "0x%X",
+ pel.privateHeader().header().componentID);
+ val = std::string(tmpValStr);
+ listStr += "\t\t\"CompID\": \"" + val + "\",\n ";
+
+ found = listStr.rfind(",");
+ if (found != std::string::npos)
+ {
+ listStr.replace(found, 1, "");
+ listStr += "\t}, \n";
+ }
+ }
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>("Hit exception while reading PEL File",
+ entry("FILENAME=%s", fileName.c_str()),
+ entry("ERROR=%s", e.what()));
+ }
+ return listStr;
+}
+/**
+ * @brief Print a list of PELs
+ */
+void printList(bool order, bool hidden)
+{
+ std::string listStr;
+ std::map<uint32_t, BCDTime> PELs;
+ std::size_t found;
+ listStr = "{\n";
+ for (auto it = fs::directory_iterator(EXTENSION_PERSIST_DIR "/pels/logs");
+ it != fs::directory_iterator(); ++it)
+ {
+ if (!fs::is_regular_file((*it).path()))
+ {
+ continue;
+ }
+ try
+ {
+ std::ifstream stream((*it).path(), std::ios::in | std::ios::binary);
+ std::vector<uint8_t> data((std::istreambuf_iterator<char>(stream)),
+ std::istreambuf_iterator<char>());
+ stream.close();
+ PEL pel{data};
+ if (pel.valid())
+ {
+
+ std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
+ if (hidden || !actionFlags.test(hiddenFlagBit))
+ {
+ PELs.emplace(pel.id(),
+ pel.privateHeader().commitTimestamp());
+ }
+ }
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>("Hit exception while reading PEL File",
+ entry("FILENAME=%s", (*it).path().c_str()),
+ entry("ERROR=%s", e.what()));
+ }
+ }
+ std::string val;
+ auto buildJSON = [&listStr](const auto& i) { listStr += genPELJSON(i); };
+ if (order)
+ {
+ std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
+ }
+ else
+ {
+ std::for_each(PELs.begin(), PELs.end(), buildJSON);
+ }
+
+ found = listStr.rfind(",");
+ if (found != std::string::npos)
+ {
+ listStr.replace(found, 1, "");
+ listStr += "\n}\n";
+ printf("%s", listStr.c_str());
+ }
+}
/**
* @brief get data form raw PEL file.
* @param[in] std::string Name of file with raw PEL
@@ -53,7 +223,15 @@
{
CLI::App app{"OpenBMC PEL Tool"};
std::string fileName;
- app.add_option("-f,--file", fileName, "Raw PEL File");
+ bool listPEL;
+ bool listPELDescOrd;
+ bool listPELShowHidden;
+ listPELDescOrd = false;
+ listPELShowHidden = false;
+ app.add_option("-f,--file", fileName, "Raw PEL file");
+ app.add_flag("-l", listPEL, "List PELS");
+ app.add_flag("-r", listPELDescOrd, "Reverse order of output");
+ app.add_flag("-s", listPELShowHidden, "Show hidden PELs");
CLI11_PARSE(app, argc, argv);
if (!fileName.empty())
@@ -70,6 +248,12 @@
"Raw PEL file can't be read.");
}
}
+
+ else if (listPEL)
+ {
+
+ printList(listPELDescOrd, listPELShowHidden);
+ }
else
{
exitWithError(app.help("", CLI::AppFormatMode::All),
diff --git a/extensions/openpower-pels/user_header.hpp b/extensions/openpower-pels/user_header.hpp
index 5689a1c..6692dd3 100644
--- a/extensions/openpower-pels/user_header.hpp
+++ b/extensions/openpower-pels/user_header.hpp
@@ -173,6 +173,15 @@
*/
std::optional<std::string> getJSON() const override;
+ /**
+ * @brief Helper function to get values from lookup tables.
+ * @return std::string - the value
+ * @param[in] uint8_t - field to get value for
+ * @param[in] PELValues - lookup table
+ */
+ std::string getValue(const uint8_t field,
+ const pel_values::PELValues& values) const;
+
private:
/**
* @brief Fills in the object from the stream data
@@ -232,15 +241,6 @@
* @brief The second reserved word placeholder.
*/
uint32_t _reserved4Byte2;
-
- /**
- * @brief Helper function to get values from lookup tables.
- * @return std::string - the value
- * @param[in] uint8_t - field to get value for
- * @param[in] PELValues - lookup table
- */
- std::string getValue(const uint8_t field,
- const pel_values::PELValues& values) const;
};
} // namespace pels