blob: 791e82109fb35e9cb4a9a42e753e84b78ba4edeb [file] [log] [blame]
Alexander Hansen40fb5492025-10-28 17:56:12 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2019 IBM Corporation
3
Aatir7b291ec2019-11-19 10:37:37 -06004#include "config.h"
5
Patrick Williams2544b412022-10-04 08:41:06 -05006#include "config_main.h"
7
Aatir7b291ec2019-11-19 10:37:37 -06008#include "../bcd_time.hpp"
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +08009#include "../json_utils.hpp"
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080010#include "../paths.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050011#include "../pel.hpp"
Aatir7b291ec2019-11-19 10:37:37 -060012#include "../pel_types.hpp"
13#include "../pel_values.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050014
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +080015#include <Python.h>
16
Aatir186ce8c2019-10-20 15:13:39 -050017#include <CLI/CLI.hpp>
Matt Spinlera561ff62023-07-17 08:43:55 -050018#include <phosphor-logging/log.hpp>
Patrick Williams2544b412022-10-04 08:41:06 -050019
Aatir7b291ec2019-11-19 10:37:37 -060020#include <bitset>
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +080021#include <fstream>
Aatir186ce8c2019-10-20 15:13:39 -050022#include <iostream>
Aatir7b291ec2019-11-19 10:37:37 -060023#include <regex>
Aatir186ce8c2019-10-20 15:13:39 -050024#include <string>
25
Aatir7b291ec2019-11-19 10:37:37 -060026namespace fs = std::filesystem;
Matt Spinlera561ff62023-07-17 08:43:55 -050027using namespace phosphor::logging;
Aatir186ce8c2019-10-20 15:13:39 -050028using namespace openpower::pels;
Aatir7b291ec2019-11-19 10:37:37 -060029namespace message = openpower::pels::message;
30namespace pv = openpower::pels::pel_values;
Aatir186ce8c2019-10-20 15:13:39 -050031
Miguel Gomez011ccae2021-03-25 23:42:09 +000032const uint8_t critSysTermSeverity = 0x51;
33
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +080034using PELFunc = std::function<void(const PEL&, bool hexDump)>;
Matt Spinler0d804ef2020-05-12 16:16:26 -050035message::Registry registry(getPELReadOnlyDataPath() / message::registryFileName,
Matt Spinlerd8e29002020-04-09 09:11:22 -050036 false);
Matt Spinler27de6f32020-02-21 08:35:57 -060037namespace service
38{
39constexpr auto logging = "xyz.openbmc_project.Logging";
40} // namespace service
41
42namespace interface
43{
44constexpr auto deleteObj = "xyz.openbmc_project.Object.Delete";
45constexpr auto deleteAll = "xyz.openbmc_project.Collection.DeleteAll";
46} // namespace interface
47
48namespace object_path
49{
50constexpr auto logEntry = "/xyz/openbmc_project/logging/entry/";
51constexpr auto logging = "/xyz/openbmc_project/logging";
52} // namespace object_path
53
William A. Kennington IIIb6b25572021-05-19 17:09:41 -070054std::string pelLogDir()
55{
Patrick Williamsfa2d9622024-09-30 16:25:43 -040056 return std::string(phosphor::logging::paths::extension()) + "/pels/logs";
William A. Kennington IIIb6b25572021-05-19 17:09:41 -070057}
58
Aatire340c132019-12-09 14:19:29 -060059/**
Aatir37822f62019-12-10 14:40:27 -060060 * @brief helper function to get PEL commit timestamp from file name
Sumit Kumar104c7962022-02-09 06:30:39 -060061 * @retrun uint64_t - PEL commit timestamp
Aatir37822f62019-12-10 14:40:27 -060062 * @param[in] std::string - file name
63 */
Sumit Kumar104c7962022-02-09 06:30:39 -060064uint64_t fileNameToTimestamp(const std::string& fileName)
Aatir37822f62019-12-10 14:40:27 -060065{
66 std::string token = fileName.substr(0, fileName.find("_"));
Sumit Kumar104c7962022-02-09 06:30:39 -060067 uint64_t bcdTime = 0;
Aatir37822f62019-12-10 14:40:27 -060068 if (token.length() >= 14)
69 {
Matt Spinlerbe952d22022-07-01 11:30:11 -050070 int i = 0;
71
Aatir37822f62019-12-10 14:40:27 -060072 try
73 {
Matt Spinler6f07df32025-05-09 11:42:39 -050074 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -060075 bcdTime |= (static_cast<uint64_t>(tmp) << 56);
Aatir37822f62019-12-10 14:40:27 -060076 }
Patrick Williams66491c62021-10-06 12:23:37 -050077 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060078 {
79 std::cout << "Conversion failure: " << err.what() << std::endl;
80 }
81 i += 2;
82 try
83 {
Matt Spinler6f07df32025-05-09 11:42:39 -050084 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -060085 bcdTime |= (static_cast<uint64_t>(tmp) << 48);
Aatir37822f62019-12-10 14:40:27 -060086 }
Patrick Williams66491c62021-10-06 12:23:37 -050087 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060088 {
89 std::cout << "Conversion failure: " << err.what() << std::endl;
90 }
91 i += 2;
92 try
93 {
Matt Spinler6f07df32025-05-09 11:42:39 -050094 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -060095 bcdTime |= (static_cast<uint64_t>(tmp) << 40);
Aatir37822f62019-12-10 14:40:27 -060096 }
Patrick Williams66491c62021-10-06 12:23:37 -050097 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060098 {
99 std::cout << "Conversion failure: " << err.what() << std::endl;
100 }
101 i += 2;
102 try
103 {
Matt Spinler6f07df32025-05-09 11:42:39 -0500104 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -0600105 bcdTime |= (static_cast<uint64_t>(tmp) << 32);
Aatir37822f62019-12-10 14:40:27 -0600106 }
Patrick Williams66491c62021-10-06 12:23:37 -0500107 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600108 {
109 std::cout << "Conversion failure: " << err.what() << std::endl;
110 }
111 i += 2;
112 try
113 {
Matt Spinler6f07df32025-05-09 11:42:39 -0500114 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -0600115 bcdTime |= (tmp << 24);
Aatir37822f62019-12-10 14:40:27 -0600116 }
Patrick Williams66491c62021-10-06 12:23:37 -0500117 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600118 {
119 std::cout << "Conversion failure: " << err.what() << std::endl;
120 }
121 i += 2;
122 try
123 {
Matt Spinler6f07df32025-05-09 11:42:39 -0500124 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -0600125 bcdTime |= (tmp << 16);
Aatir37822f62019-12-10 14:40:27 -0600126 }
Patrick Williams66491c62021-10-06 12:23:37 -0500127 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600128 {
129 std::cout << "Conversion failure: " << err.what() << std::endl;
130 }
131 i += 2;
132 try
133 {
Matt Spinler6f07df32025-05-09 11:42:39 -0500134 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -0600135 bcdTime |= (tmp << 8);
Aatir37822f62019-12-10 14:40:27 -0600136 }
Patrick Williams66491c62021-10-06 12:23:37 -0500137 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600138 {
139 std::cout << "Conversion failure: " << err.what() << std::endl;
140 }
141 i += 2;
142 try
143 {
Matt Spinler6f07df32025-05-09 11:42:39 -0500144 auto tmp = std::stoul(token.substr(i, 2), nullptr, 16);
Sumit Kumar104c7962022-02-09 06:30:39 -0600145 bcdTime |= tmp;
Aatir37822f62019-12-10 14:40:27 -0600146 }
Patrick Williams66491c62021-10-06 12:23:37 -0500147 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600148 {
149 std::cout << "Conversion failure: " << err.what() << std::endl;
150 }
151 }
Sumit Kumar104c7962022-02-09 06:30:39 -0600152 return bcdTime;
Aatir37822f62019-12-10 14:40:27 -0600153}
154
155/**
156 * @brief helper function to get PEL id from file name
157 * @retrun uint32_t - PEL id
158 * @param[in] std::string - file name
159 */
160uint32_t fileNameToPELId(const std::string& fileName)
161{
162 uint32_t num = 0;
163 try
164 {
Matt Spinler6f07df32025-05-09 11:42:39 -0500165 num = std::stoul(fileName.substr(fileName.find("_") + 1), nullptr, 16);
Aatir37822f62019-12-10 14:40:27 -0600166 }
Patrick Williams66491c62021-10-06 12:23:37 -0500167 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600168 {
169 std::cout << "Conversion failure: " << err.what() << std::endl;
170 }
171 return num;
172}
173
174/**
Matt Spinler80129fe2023-01-19 15:09:05 -0600175 * @brief Check if the string ends with the PEL ID string passed in
176 * @param[in] str - string to check for PEL ID
177 * @param[in] pelID - PEL id string
178 *
179 * @return bool - true with suffix matches
Aatire340c132019-12-09 14:19:29 -0600180 */
Matt Spinler80129fe2023-01-19 15:09:05 -0600181bool endsWithPelID(const std::string& str, const std::string& pelID)
Aatire340c132019-12-09 14:19:29 -0600182{
Matt Spinler80129fe2023-01-19 15:09:05 -0600183 constexpr size_t pelIDSize = 8;
184
185 if (pelID.size() != pelIDSize)
186 {
187 return false;
188 }
189
190 size_t slen = str.size(), elen = pelID.size();
Aatire340c132019-12-09 14:19:29 -0600191 if (slen < elen)
192 return false;
193 while (elen)
194 {
Matt Spinler80129fe2023-01-19 15:09:05 -0600195 if (str[--slen] != pelID[--elen])
Aatire340c132019-12-09 14:19:29 -0600196 return false;
197 }
198 return true;
199}
200
Aatir37822f62019-12-10 14:40:27 -0600201/**
202 * @brief get data form raw PEL file.
203 * @param[in] std::string Name of file with raw PEL
204 * @return std::vector<uint8_t> char vector read from raw PEL file.
205 */
Aatirbad5f8a2019-12-10 15:27:16 -0600206std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600207{
208 std::ifstream file(name, std::ifstream::in);
209 if (file.good())
210 {
211 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
212 std::istreambuf_iterator<char>()};
213 return data;
214 }
215 else
216 {
Aatir37822f62019-12-10 14:40:27 -0600217 return {};
218 }
219}
220
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800221/**
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800222 * @brief Initialize Python interpreter and gather all UD parser modules under
223 * the paths found in Python sys.path and the current user directory.
224 * This is to prevent calling a non-existant module which causes Python
225 * to print an import error message and breaking JSON output.
226 *
227 * @return std::vector<std::string> Vector of plugins found in filesystem
228 */
229std::vector<std::string> getPlugins()
230{
231 Py_Initialize();
232 std::vector<std::string> plugins;
233 std::vector<std::string> siteDirs;
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800234 std::array<std::string, 2> parserDirs = {"udparsers", "srcparsers"};
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800235 PyObject* pName = PyUnicode_FromString("sys");
236 PyObject* pModule = PyImport_Import(pName);
237 Py_XDECREF(pName);
238 PyObject* pDict = PyModule_GetDict(pModule);
239 Py_XDECREF(pModule);
240 PyObject* pResult = PyDict_GetItemString(pDict, "path");
241 PyObject* pValue = PyUnicode_FromString(".");
242 PyList_Append(pResult, pValue);
243 Py_XDECREF(pValue);
244 auto list_size = PyList_Size(pResult);
245 for (auto i = 0; i < list_size; i++)
246 {
247 PyObject* item = PyList_GetItem(pResult, i);
248 PyObject* pBytes = PyUnicode_AsEncodedString(item, "utf-8", "~E~");
249 const char* output = PyBytes_AS_STRING(pBytes);
250 Py_XDECREF(pBytes);
251 std::string tmpStr(output);
252 siteDirs.push_back(tmpStr);
253 }
254 for (const auto& dir : siteDirs)
255 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800256 for (const auto& parserDir : parserDirs)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800257 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800258 if (fs::exists(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800259 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800260 for (const auto& entry :
261 fs::directory_iterator(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800262 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800263 if (entry.is_directory() and
264 fs::exists(entry.path().string() + "/" +
265 entry.path().stem().string() + ".py"))
266 {
267 plugins.push_back(entry.path().stem());
268 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800269 }
270 }
271 }
272 }
273 return plugins;
274}
275
276/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800277 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
278 * stdout the full PEL in JSON if fullPEL is true
279 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
280 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800281 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000282 * @param[in] critSysTerm - Boolean to include critical error and system
283 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800284 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
285 * @param[in] foundPEL - Boolean to check if any PEL is present
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800286 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800287 * @param[in] plugins - Vector of strings of plugins found in filesystem
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800288 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800289 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
290 */
Aatir7b291ec2019-11-19 10:37:37 -0600291template <typename T>
Patrick Williams075c7922024-08-16 15:19:49 -0400292std::string genPELJSON(
293 T itr, bool hidden, bool includeInfo, bool critSysTerm, bool fullPEL,
294 bool& foundPEL, const std::optional<std::regex>& scrubRegex,
295 const std::vector<std::string>& plugins, bool hexDump, bool archive)
Aatir7b291ec2019-11-19 10:37:37 -0600296{
Aatir7b291ec2019-11-19 10:37:37 -0600297 std::string val;
Aatir7b291ec2019-11-19 10:37:37 -0600298 std::string listStr;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700299 char name[51];
Sumit Kumar104c7962022-02-09 06:30:39 -0600300 sprintf(name, "/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X",
301 static_cast<uint8_t>((itr.second >> 56) & 0xFF),
302 static_cast<uint8_t>((itr.second >> 48) & 0xFF),
303 static_cast<uint8_t>((itr.second >> 40) & 0xFF),
304 static_cast<uint8_t>((itr.second >> 32) & 0xFF),
305 static_cast<uint8_t>((itr.second >> 24) & 0xFF),
306 static_cast<uint8_t>((itr.second >> 16) & 0xFF),
307 static_cast<uint8_t>((itr.second >> 8) & 0xFF),
308 static_cast<uint8_t>(itr.second & 0xFF), itr.first);
309
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500310 auto fileName = (archive ? pelLogDir() + "/archive" : pelLogDir()) + name;
Aatir7b291ec2019-11-19 10:37:37 -0600311 try
312 {
Aatir37822f62019-12-10 14:40:27 -0600313 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800314 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600315 {
Matt Spinlera561ff62023-07-17 08:43:55 -0500316 log<level::ERR>("Empty PEL file",
317 entry("FILENAME=%s", fileName.c_str()));
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800318 return listStr;
319 }
320 PEL pel{data};
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800321 if (!pel.valid())
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800322 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800323 return listStr;
324 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800325 if (!includeInfo && pel.userHeader().severity() == 0)
326 {
327 return listStr;
328 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000329 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
330 {
331 return listStr;
332 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800333 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
334 if (!hidden && actionFlags.test(hiddenFlagBit))
335 {
336 return listStr;
337 }
338 if (pel.primarySRC() && scrubRegex)
339 {
340 val = pel.primarySRC().value()->asciiString();
341 if (std::regex_search(trimEnd(val), scrubRegex.value(),
342 std::regex_constants::match_not_null))
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800343 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800344 return listStr;
345 }
346 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800347 if (hexDump)
348 {
Arya K Padman8c8aaa02024-04-28 23:23:45 -0500349 std::cout
350 << dumpHex(std::data(pel.data()), pel.size(), 0, false).get()
351 << std::endl;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800352 }
353 else if (fullPEL)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800354 {
355 if (!foundPEL)
356 {
357 std::cout << "[\n";
358 foundPEL = true;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800359 }
360 else
Aatir7b291ec2019-11-19 10:37:37 -0600361 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800362 std::cout << ",\n\n";
363 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800364 pel.toJSON(registry, plugins);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800365 }
366 else
367 {
368 // id
Matt Spinler3025d0b2021-06-02 15:12:52 -0600369 listStr += " \"" +
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800370 getNumberString("0x%X", pel.privateHeader().id()) +
371 "\": {\n";
372 // ASCII
373 if (pel.primarySRC())
374 {
375 val = pel.primarySRC().value()->asciiString();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600376 jsonInsert(listStr, "SRC", trimEnd(val), 2);
377
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800378 // Registry message
379 auto regVal = pel.primarySRC().value()->getErrorDetails(
380 registry, DetailLevel::message, true);
381 if (regVal)
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800382 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800383 val = regVal.value();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600384 jsonInsert(listStr, "Message", val, 2);
Aatir37822f62019-12-10 14:40:27 -0600385 }
Aatir7b291ec2019-11-19 10:37:37 -0600386 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800387 else
388 {
Matt Spinler3025d0b2021-06-02 15:12:52 -0600389 jsonInsert(listStr, "SRC", "No SRC", 2);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800390 }
Matt Spinler3025d0b2021-06-02 15:12:52 -0600391
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800392 // platformid
Matt Spinler3025d0b2021-06-02 15:12:52 -0600393 jsonInsert(listStr, "PLID",
394 getNumberString("0x%X", pel.privateHeader().plid()), 2);
395
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800396 // creatorid
397 std::string creatorID =
398 getNumberString("%c", pel.privateHeader().creatorID());
399 val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
400 : "Unknown Creator ID";
Matt Spinler3025d0b2021-06-02 15:12:52 -0600401 jsonInsert(listStr, "CreatorID", val, 2);
402
403 // subsystem
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800404 std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
405 pel_values::subsystemValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600406 jsonInsert(listStr, "Subsystem", subsystem, 2);
407
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800408 // commit time
Matt Spinlerbe952d22022-07-01 11:30:11 -0500409 char tmpValStr[50];
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800410 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
411 pel.privateHeader().commitTimestamp().month,
412 pel.privateHeader().commitTimestamp().day,
413 pel.privateHeader().commitTimestamp().yearMSB,
414 pel.privateHeader().commitTimestamp().yearLSB,
415 pel.privateHeader().commitTimestamp().hour,
416 pel.privateHeader().commitTimestamp().minutes,
417 pel.privateHeader().commitTimestamp().seconds);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600418 jsonInsert(listStr, "Commit Time", tmpValStr, 2);
419
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800420 // severity
421 std::string severity = pv::getValue(pel.userHeader().severity(),
422 pel_values::severityValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600423 jsonInsert(listStr, "Sev", severity, 2);
424
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800425 // compID
Matt Spinler9a808702023-03-28 09:39:26 -0500426 jsonInsert(
427 listStr, "CompID",
428 getComponentName(pel.privateHeader().header().componentID,
429 pel.privateHeader().creatorID()),
430 2);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600431
Matt Spinlerbe952d22022-07-01 11:30:11 -0500432 auto found = listStr.rfind(",");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800433 if (found != std::string::npos)
434 {
435 listStr.replace(found, 1, "");
Matt Spinler3025d0b2021-06-02 15:12:52 -0600436 listStr += " },\n";
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800437 }
438 foundPEL = true;
Aatir7b291ec2019-11-19 10:37:37 -0600439 }
440 }
Patrick Williams66491c62021-10-06 12:23:37 -0500441 catch (const std::exception& e)
Aatir7b291ec2019-11-19 10:37:37 -0600442 {
Matt Spinlera561ff62023-07-17 08:43:55 -0500443 log<level::ERR>("Hit exception while reading PEL File",
444 entry("FILENAME=%s", fileName.c_str()),
445 entry("ERROR=%s", e.what()));
Aatir7b291ec2019-11-19 10:37:37 -0600446 }
447 return listStr;
448}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800449
Aatir7b291ec2019-11-19 10:37:37 -0600450/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800451 * @brief Print a list of PELs or a JSON array of PELs
452 * @param[in] order - Boolean to print in reverse orser
453 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800454 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000455 * @param[in] critSysTerm - Boolean to include critical error and system
456 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800457 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800458 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800459 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Aatir7b291ec2019-11-19 10:37:37 -0600460 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000461void printPELs(bool order, bool hidden, bool includeInfo, bool critSysTerm,
462 bool fullPEL, const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500463 bool hexDump, bool archive = false)
Aatir7b291ec2019-11-19 10:37:37 -0600464{
465 std::string listStr;
Sumit Kumar104c7962022-02-09 06:30:39 -0600466 std::vector<std::pair<uint32_t, uint64_t>> PELs;
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800467 std::vector<std::string> plugins;
Aatir7b291ec2019-11-19 10:37:37 -0600468 listStr = "{\n";
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500469 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
470 : fs::directory_iterator(pelLogDir()));
Aatir7b291ec2019-11-19 10:37:37 -0600471 it != fs::directory_iterator(); ++it)
472 {
473 if (!fs::is_regular_file((*it).path()))
474 {
475 continue;
476 }
Aatir37822f62019-12-10 14:40:27 -0600477 else
Aatir7b291ec2019-11-19 10:37:37 -0600478 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600479 PELs.emplace_back(fileNameToPELId((*it).path().filename()),
480 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600481 }
482 }
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500483
Sumit Kumar104c7962022-02-09 06:30:39 -0600484 // Sort the pairs based on second time parameter
Matt Spinlerbe952d22022-07-01 11:30:11 -0500485 std::sort(PELs.begin(), PELs.end(),
486 [](const auto& left, const auto& right) {
Patrick Williams075c7922024-08-16 15:19:49 -0400487 return left.second < right.second;
488 });
Sumit Kumar104c7962022-02-09 06:30:39 -0600489
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800490 bool foundPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800491
492 if (fullPEL && !hexDump)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800493 {
494 plugins = getPlugins();
495 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000496 auto buildJSON = [&listStr, &hidden, &includeInfo, &critSysTerm, &fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500497 &foundPEL, &scrubRegex, &plugins, &hexDump,
498 &archive](const auto& i) {
Miguel Gomez011ccae2021-03-25 23:42:09 +0000499 listStr += genPELJSON(i, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500500 foundPEL, scrubRegex, plugins, hexDump, archive);
Aatir37822f62019-12-10 14:40:27 -0600501 };
Aatir7b291ec2019-11-19 10:37:37 -0600502 if (order)
503 {
504 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
505 }
506 else
507 {
508 std::for_each(PELs.begin(), PELs.end(), buildJSON);
509 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800510 if (hexDump)
511 {
512 return;
513 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800514 if (foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600515 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800516 if (fullPEL)
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800517 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800518 std::cout << "]" << std::endl;
519 }
520 else
521 {
522 std::size_t found;
523 found = listStr.rfind(",");
524 if (found != std::string::npos)
525 {
526 listStr.replace(found, 1, "");
527 listStr += "}\n";
528 printf("%s", listStr.c_str());
529 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800530 }
531 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800532 else
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800533 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800534 std::string emptyJSON = fullPEL ? "[]" : "{}";
535 std::cout << emptyJSON << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600536 }
537}
Aatir186ce8c2019-10-20 15:13:39 -0500538
Matt Spinler27de6f32020-02-21 08:35:57 -0600539/**
540 * @brief Calls the function passed in on the PEL with the ID
541 * passed in.
542 *
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800543 * @param[in] id - The string version of the PEL or BMC Log ID, either with or
Matt Spinler27de6f32020-02-21 08:35:57 -0600544 * without the 0x prefix.
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800545 * @param[in] func - The std::function<void(const PEL&, bool hexDump)> function
546 * to run.
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800547 * @param[in] useBMC - if true, search by BMC Log ID, else search by PEL ID
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800548 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler27de6f32020-02-21 08:35:57 -0600549 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800550void callFunctionOnPEL(const std::string& id, const PELFunc& func,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500551 bool useBMC = false, bool hexDump = false,
552 bool archive = false)
Matt Spinler27de6f32020-02-21 08:35:57 -0600553{
554 std::string pelID{id};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800555 if (!useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600556 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800557 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
558
Matt Spinlerbe952d22022-07-01 11:30:11 -0500559 if (pelID.starts_with("0X"))
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800560 {
561 pelID.erase(0, 2);
562 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600563 }
564
565 bool found = false;
566
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500567 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
568 : fs::directory_iterator(pelLogDir()));
Matt Spinler27de6f32020-02-21 08:35:57 -0600569 it != fs::directory_iterator(); ++it)
570 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800571 // The PEL ID is part of the filename, so use that to find the PEL if
572 // "useBMC" is set to false, otherwise we have to search within the PEL
Matt Spinler27de6f32020-02-21 08:35:57 -0600573
574 if (!fs::is_regular_file((*it).path()))
575 {
576 continue;
577 }
578
Matt Spinler80129fe2023-01-19 15:09:05 -0600579 if ((endsWithPelID((*it).path(), pelID) && !useBMC) || useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600580 {
Matt Spinler27de6f32020-02-21 08:35:57 -0600581 auto data = getFileData((*it).path());
582 if (!data.empty())
583 {
584 PEL pel{data};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800585 if (!useBMC ||
586 (useBMC && pel.obmcLogID() == std::stoul(id, nullptr, 0)))
Matt Spinler27de6f32020-02-21 08:35:57 -0600587 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800588 found = true;
589 try
590 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800591 func(pel, hexDump);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800592 break;
593 }
Patrick Williams66491c62021-10-06 12:23:37 -0500594 catch (const std::exception& e)
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800595 {
596 std::cerr << " Internal function threw an exception: "
597 << e.what() << "\n";
598 exit(1);
599 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600600 }
601 }
602 else
603 {
604 std::cerr << "Could not read PEL file\n";
605 exit(1);
606 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600607 }
608 }
609
610 if (!found)
611 {
612 std::cerr << "PEL not found\n";
613 exit(1);
614 }
615}
616
617/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600618 * @brief Delete a PEL file.
Matt Spinler27de6f32020-02-21 08:35:57 -0600619 *
Matt Spinler25d986c2021-02-10 13:26:18 -0600620 * @param[in] id - The PEL ID to delete.
Matt Spinler27de6f32020-02-21 08:35:57 -0600621 */
Matt Spinler25d986c2021-02-10 13:26:18 -0600622void deletePEL(const std::string& id)
Matt Spinler27de6f32020-02-21 08:35:57 -0600623{
Matt Spinler25d986c2021-02-10 13:26:18 -0600624 std::string pelID{id};
Matt Spinler27de6f32020-02-21 08:35:57 -0600625
Matt Spinler25d986c2021-02-10 13:26:18 -0600626 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
627
Matt Spinlerbe952d22022-07-01 11:30:11 -0500628 if (pelID.starts_with("0X"))
Matt Spinler27de6f32020-02-21 08:35:57 -0600629 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600630 pelID.erase(0, 2);
Matt Spinler27de6f32020-02-21 08:35:57 -0600631 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600632
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700633 for (auto it = fs::directory_iterator(pelLogDir());
Matt Spinler25d986c2021-02-10 13:26:18 -0600634 it != fs::directory_iterator(); ++it)
Matt Spinler27de6f32020-02-21 08:35:57 -0600635 {
Matt Spinler80129fe2023-01-19 15:09:05 -0600636 if (endsWithPelID((*it).path(), pelID))
Matt Spinler25d986c2021-02-10 13:26:18 -0600637 {
638 fs::remove((*it).path());
639 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600640 }
641}
642
643/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600644 * @brief Delete all PEL files.
Matt Spinler27de6f32020-02-21 08:35:57 -0600645 */
646void deleteAllPELs()
647{
Matt Spinlera561ff62023-07-17 08:43:55 -0500648 log<level::INFO>("peltool deleting all event logs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600649
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700650 for (const auto& entry : fs::directory_iterator(pelLogDir()))
Matt Spinler27de6f32020-02-21 08:35:57 -0600651 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500652 if (!fs::is_regular_file(entry.path()))
653 {
654 continue;
655 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600656 fs::remove(entry.path());
Matt Spinler27de6f32020-02-21 08:35:57 -0600657 }
658}
659
Matt Spinler1b420bc2020-02-21 08:54:25 -0600660/**
661 * @brief Display a single PEL
662 *
663 * @param[in] pel - the PEL to display
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800664 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler1b420bc2020-02-21 08:54:25 -0600665 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800666void displayPEL(const PEL& pel, bool hexDump)
Matt Spinler1b420bc2020-02-21 08:54:25 -0600667{
668 if (pel.valid())
669 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800670 if (hexDump)
671 {
Arya K Padman8c8aaa02024-04-28 23:23:45 -0500672 std::string dstr =
673 dumpHex(std::data(pel.data()), pel.size(), 0, false).get();
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800674 std::cout << dstr << std::endl;
675 }
676 else
677 {
678 auto plugins = getPlugins();
679 pel.toJSON(registry, plugins);
680 }
Matt Spinler1b420bc2020-02-21 08:54:25 -0600681 }
682 else
683 {
684 std::cerr << "PEL was malformed\n";
685 exit(1);
686 }
687}
688
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800689/**
690 * @brief Print number of PELs
691 * @param[in] hidden - Bool to include hidden logs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800692 * @param[in] includeInfo - Bool to include informational logs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000693 * @param[in] critSysTerm - Bool to include CritSysTerm
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800694 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800695 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000696void printPELCount(bool hidden, bool includeInfo, bool critSysTerm,
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800697 const std::optional<std::regex>& scrubRegex)
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800698{
699 std::size_t count = 0;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700700
701 for (auto it = fs::directory_iterator(pelLogDir());
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800702 it != fs::directory_iterator(); ++it)
703 {
704 if (!fs::is_regular_file((*it).path()))
705 {
706 continue;
707 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800708 std::vector<uint8_t> data = getFileData((*it).path());
709 if (data.empty())
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800710 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800711 continue;
712 }
713 PEL pel{data};
714 if (!pel.valid())
715 {
716 continue;
717 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800718 if (!includeInfo && pel.userHeader().severity() == 0)
719 {
720 continue;
721 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000722 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
723 {
724 continue;
725 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800726 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
727 if (!hidden && actionFlags.test(hiddenFlagBit))
728 {
729 continue;
730 }
731 if (pel.primarySRC() && scrubRegex)
732 {
733 std::string val = pel.primarySRC().value()->asciiString();
734 if (std::regex_search(trimEnd(val), scrubRegex.value(),
735 std::regex_constants::match_not_null))
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800736 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800737 continue;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800738 }
739 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800740 count++;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800741 }
742 std::cout << "{\n"
743 << " \"Number of PELs found\": "
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800744 << getNumberString("%d", count) << "\n}\n";
745}
746
747/**
748 * @brief Generate regex pattern object from file contents
749 * @param[in] scrubFile - File containing regex pattern
750 * @return std::regex - SRC regex object
751 */
752std::regex genRegex(std::string& scrubFile)
753{
754 std::string pattern;
755 std::ifstream contents(scrubFile);
756 if (contents.fail())
757 {
758 std::cerr << "Can't open \"" << scrubFile << "\"\n";
759 exit(1);
760 }
761 std::string line;
762 while (std::getline(contents, line))
763 {
764 if (!line.empty())
765 {
766 pattern.append(line + "|");
767 }
768 }
769 try
770 {
771 std::regex scrubRegex(pattern, std::regex::icase);
772 return scrubRegex;
773 }
Patrick Williams66491c62021-10-06 12:23:37 -0500774 catch (const std::regex_error& e)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800775 {
776 if (e.code() == std::regex_constants::error_collate)
777 std::cerr << "Invalid collating element request\n";
778 else if (e.code() == std::regex_constants::error_ctype)
779 std::cerr << "Invalid character class\n";
780 else if (e.code() == std::regex_constants::error_escape)
781 std::cerr << "Invalid escape character or trailing escape\n";
782 else if (e.code() == std::regex_constants::error_backref)
783 std::cerr << "Invalid back reference\n";
784 else if (e.code() == std::regex_constants::error_brack)
785 std::cerr << "Mismatched bracket ([ or ])\n";
786 else if (e.code() == std::regex_constants::error_paren)
787 {
788 // to catch return code error_badrepeat when error_paren is retured
789 // instead
790 size_t pos = pattern.find_first_of("*+?{");
791 while (pos != std::string::npos)
792 {
793 if (pos == 0 || pattern.substr(pos - 1, 1) == "|")
794 {
795 std::cerr
796 << "A repetition character (*, ?, +, or {) was not "
797 "preceded by a valid regular expression\n";
798 exit(1);
799 }
800 pos = pattern.find_first_of("*+?{", pos + 1);
801 }
802 std::cerr << "Mismatched parentheses (( or ))\n";
803 }
804 else if (e.code() == std::regex_constants::error_brace)
805 std::cerr << "Mismatched brace ({ or })\n";
806 else if (e.code() == std::regex_constants::error_badbrace)
807 std::cerr << "Invalid range inside a { }\n";
808 else if (e.code() == std::regex_constants::error_range)
809 std::cerr << "Invalid character range (e.g., [z-a])\n";
810 else if (e.code() == std::regex_constants::error_space)
811 std::cerr << "Insufficient memory to handle regular expression\n";
812 else if (e.code() == std::regex_constants::error_badrepeat)
813 std::cerr << "A repetition character (*, ?, +, or {) was not "
814 "preceded by a valid regular expression\n";
815 else if (e.code() == std::regex_constants::error_complexity)
816 std::cerr << "The requested match is too complex\n";
817 else if (e.code() == std::regex_constants::error_stack)
818 std::cerr << "Insufficient memory to evaluate a match\n";
819 exit(1);
820 }
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800821}
822
Aatir186ce8c2019-10-20 15:13:39 -0500823static void exitWithError(const std::string& help, const char* err)
824{
825 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
826 exit(-1);
827}
828
829int main(int argc, char** argv)
830{
831 CLI::App app{"OpenBMC PEL Tool"};
832 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600833 std::string idPEL;
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800834 std::string bmcId;
Matt Spinler27de6f32020-02-21 08:35:57 -0600835 std::string idToDelete;
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800836 std::string scrubFile;
837 std::optional<std::regex> scrubRegex;
Aatire340c132019-12-09 14:19:29 -0600838 bool listPEL = false;
839 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800840 bool hidden = false;
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800841 bool includeInfo = false;
Miguel Gomez011ccae2021-03-25 23:42:09 +0000842 bool critSysTerm = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600843 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800844 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800845 bool fullPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800846 bool hexDump = false;
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500847 bool archive = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600848
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800849 app.set_help_flag("--help", "Print this help message and exit");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800850 app.add_option("--file", fileName, "Display a PEL using its Raw PEL file");
Aatire340c132019-12-09 14:19:29 -0600851 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800852 app.add_option("--bmc-id", bmcId,
853 "Display a PEL based on its BMC Event ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800854 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600855 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800856 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600857 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800858 app.add_flag("-h", hidden, "Include hidden PELs");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800859 app.add_flag("-f,--info", includeInfo, "Include informational PELs");
Miguel Gomez011ccae2021-03-25 23:42:09 +0000860 app.add_flag("-t, --termination", critSysTerm,
861 "List only critical system terminating PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600862 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
863 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800864 app.add_option("-s, --scrub", scrubFile,
865 "File containing SRC regular expressions to ignore");
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800866 app.add_flag("-x", hexDump, "Display PEL(s) in hexdump instead of JSON");
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500867 app.add_flag("--archive", archive, "List or display archived PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600868
Aatir186ce8c2019-10-20 15:13:39 -0500869 CLI11_PARSE(app, argc, argv);
870
871 if (!fileName.empty())
872 {
873 std::vector<uint8_t> data = getFileData(fileName);
874 if (!data.empty())
875 {
876 PEL pel{data};
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800877 if (hexDump)
878 {
Arya K Padman8c8aaa02024-04-28 23:23:45 -0500879 std::string dstr =
880 dumpHex(std::data(pel.data()), pel.size(), 0, false).get();
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800881 std::cout << dstr << std::endl;
882 }
883 else
884 {
885 auto plugins = getPlugins();
886 pel.toJSON(registry, plugins);
887 }
Aatir186ce8c2019-10-20 15:13:39 -0500888 }
889 else
890 {
891 exitWithError(app.help("", CLI::AppFormatMode::All),
892 "Raw PEL file can't be read.");
893 }
894 }
Aatire340c132019-12-09 14:19:29 -0600895 else if (!idPEL.empty())
896 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500897 callFunctionOnPEL(idPEL, displayPEL, false, hexDump, archive);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800898 }
899 else if (!bmcId.empty())
900 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500901 callFunctionOnPEL(bmcId, displayPEL, true, hexDump, archive);
Aatire340c132019-12-09 14:19:29 -0600902 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800903 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600904 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800905 if (!scrubFile.empty())
906 {
907 scrubRegex = genRegex(scrubFile);
908 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000909 printPELs(listPELDescOrd, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500910 scrubRegex, hexDump, archive);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800911 }
912 else if (showPELCount)
913 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800914 if (!scrubFile.empty())
915 {
916 scrubRegex = genRegex(scrubFile);
917 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000918 printPELCount(hidden, includeInfo, critSysTerm, scrubRegex);
Aatir7b291ec2019-11-19 10:37:37 -0600919 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600920 else if (!idToDelete.empty())
921 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600922 deletePEL(idToDelete);
Matt Spinler27de6f32020-02-21 08:35:57 -0600923 }
924 else if (deleteAll)
925 {
926 deleteAllPELs();
927 }
Aatir186ce8c2019-10-20 15:13:39 -0500928 else
929 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800930 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500931 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800932 Py_Finalize();
Aatir186ce8c2019-10-20 15:13:39 -0500933 return 0;
934}