diff options
author | Aatir <aatrapps@gmail.com> | 2019-11-19 10:37:37 -0600 |
---|---|---|
committer | Matt Spinler <spinler@us.ibm.com> | 2019-12-09 18:52:48 +0000 |
commit | 7b291ec64bffa3038e075154a474fe0fab80f26f (patch) | |
tree | 391c015697908b8f6e0d15278e58ad3372ef65a0 | |
parent | c92b4eb4f00c5b6516476eda7965f8fecd6fbe35 (diff) | |
download | phosphor-logging-7b291ec64bffa3038e075154a474fe0fab80f26f.tar.gz phosphor-logging-7b291ec64bffa3038e075154a474fe0fab80f26f.zip |
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>
-rw-r--r-- | extensions/openpower-pels/pel_values.cpp | 13 | ||||
-rw-r--r-- | extensions/openpower-pels/pel_values.hpp | 8 | ||||
-rw-r--r-- | extensions/openpower-pels/tools/peltool.cpp | 186 | ||||
-rw-r--r-- | extensions/openpower-pels/user_header.hpp | 18 |
4 files changed, 215 insertions, 10 deletions
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 @@ const std::map<std::string, std::string> creatorIDs = { {"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 PELFieldValue = std::tuple<uint32_t, const char*, const char*>; 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 @@ int main(int argc, char** argv) { 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 @@ int main(int argc, char** argv) "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 @@ class UserHeader : public Section */ 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 @@ class UserHeader : public Section * @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 |