blob: a4b7f59a0761f25393ddce0d55ce983d4b125981 [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Aatir7b291ec2019-11-19 10:37:37 -060016#include "config.h"
17
Patrick Williams2544b412022-10-04 08:41:06 -050018#include "config_main.h"
19
Aatir7b291ec2019-11-19 10:37:37 -060020#include "../bcd_time.hpp"
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +080021#include "../json_utils.hpp"
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080022#include "../paths.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050023#include "../pel.hpp"
Aatir7b291ec2019-11-19 10:37:37 -060024#include "../pel_types.hpp"
25#include "../pel_values.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050026
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +080027#include <Python.h>
28
Aatir186ce8c2019-10-20 15:13:39 -050029#include <CLI/CLI.hpp>
Matt Spinlera561ff62023-07-17 08:43:55 -050030#include <phosphor-logging/log.hpp>
Patrick Williams2544b412022-10-04 08:41:06 -050031
Aatir7b291ec2019-11-19 10:37:37 -060032#include <bitset>
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +080033#include <fstream>
Aatir186ce8c2019-10-20 15:13:39 -050034#include <iostream>
Aatir7b291ec2019-11-19 10:37:37 -060035#include <regex>
Aatir186ce8c2019-10-20 15:13:39 -050036#include <string>
37
Aatir7b291ec2019-11-19 10:37:37 -060038namespace fs = std::filesystem;
Matt Spinlera561ff62023-07-17 08:43:55 -050039using namespace phosphor::logging;
Aatir186ce8c2019-10-20 15:13:39 -050040using namespace openpower::pels;
Aatir7b291ec2019-11-19 10:37:37 -060041namespace message = openpower::pels::message;
42namespace pv = openpower::pels::pel_values;
Aatir186ce8c2019-10-20 15:13:39 -050043
Miguel Gomez011ccae2021-03-25 23:42:09 +000044const uint8_t critSysTermSeverity = 0x51;
45
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +080046using PELFunc = std::function<void(const PEL&, bool hexDump)>;
Matt Spinler0d804ef2020-05-12 16:16:26 -050047message::Registry registry(getPELReadOnlyDataPath() / message::registryFileName,
Matt Spinlerd8e29002020-04-09 09:11:22 -050048 false);
Matt Spinler27de6f32020-02-21 08:35:57 -060049namespace service
50{
51constexpr auto logging = "xyz.openbmc_project.Logging";
52} // namespace service
53
54namespace interface
55{
56constexpr auto deleteObj = "xyz.openbmc_project.Object.Delete";
57constexpr auto deleteAll = "xyz.openbmc_project.Collection.DeleteAll";
58} // namespace interface
59
60namespace object_path
61{
62constexpr auto logEntry = "/xyz/openbmc_project/logging/entry/";
63constexpr auto logging = "/xyz/openbmc_project/logging";
64} // namespace object_path
65
William A. Kennington IIIb6b25572021-05-19 17:09:41 -070066std::string pelLogDir()
67{
68 return std::string(EXTENSION_PERSIST_DIR) + "/pels/logs";
69}
70
Aatire340c132019-12-09 14:19:29 -060071/**
Aatir37822f62019-12-10 14:40:27 -060072 * @brief helper function to get PEL commit timestamp from file name
Sumit Kumar104c7962022-02-09 06:30:39 -060073 * @retrun uint64_t - PEL commit timestamp
Aatir37822f62019-12-10 14:40:27 -060074 * @param[in] std::string - file name
75 */
Sumit Kumar104c7962022-02-09 06:30:39 -060076uint64_t fileNameToTimestamp(const std::string& fileName)
Aatir37822f62019-12-10 14:40:27 -060077{
78 std::string token = fileName.substr(0, fileName.find("_"));
Sumit Kumar104c7962022-02-09 06:30:39 -060079 uint64_t bcdTime = 0;
Aatir37822f62019-12-10 14:40:27 -060080 if (token.length() >= 14)
81 {
Matt Spinlerbe952d22022-07-01 11:30:11 -050082 int i = 0;
83
Aatir37822f62019-12-10 14:40:27 -060084 try
85 {
Sumit Kumar104c7962022-02-09 06:30:39 -060086 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
87 bcdTime |= (static_cast<uint64_t>(tmp) << 56);
Aatir37822f62019-12-10 14:40:27 -060088 }
Patrick Williams66491c62021-10-06 12:23:37 -050089 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060090 {
91 std::cout << "Conversion failure: " << err.what() << std::endl;
92 }
93 i += 2;
94 try
95 {
Sumit Kumar104c7962022-02-09 06:30:39 -060096 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
97 bcdTime |= (static_cast<uint64_t>(tmp) << 48);
Aatir37822f62019-12-10 14:40:27 -060098 }
Patrick Williams66491c62021-10-06 12:23:37 -050099 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600100 {
101 std::cout << "Conversion failure: " << err.what() << std::endl;
102 }
103 i += 2;
104 try
105 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600106 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
107 bcdTime |= (static_cast<uint64_t>(tmp) << 40);
Aatir37822f62019-12-10 14:40:27 -0600108 }
Patrick Williams66491c62021-10-06 12:23:37 -0500109 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600110 {
111 std::cout << "Conversion failure: " << err.what() << std::endl;
112 }
113 i += 2;
114 try
115 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600116 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
117 bcdTime |= (static_cast<uint64_t>(tmp) << 32);
Aatir37822f62019-12-10 14:40:27 -0600118 }
Patrick Williams66491c62021-10-06 12:23:37 -0500119 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600120 {
121 std::cout << "Conversion failure: " << err.what() << std::endl;
122 }
123 i += 2;
124 try
125 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600126 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
127 bcdTime |= (tmp << 24);
Aatir37822f62019-12-10 14:40:27 -0600128 }
Patrick Williams66491c62021-10-06 12:23:37 -0500129 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600130 {
131 std::cout << "Conversion failure: " << err.what() << std::endl;
132 }
133 i += 2;
134 try
135 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600136 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
137 bcdTime |= (tmp << 16);
Aatir37822f62019-12-10 14:40:27 -0600138 }
Patrick Williams66491c62021-10-06 12:23:37 -0500139 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600140 {
141 std::cout << "Conversion failure: " << err.what() << std::endl;
142 }
143 i += 2;
144 try
145 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600146 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
147 bcdTime |= (tmp << 8);
Aatir37822f62019-12-10 14:40:27 -0600148 }
Patrick Williams66491c62021-10-06 12:23:37 -0500149 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600150 {
151 std::cout << "Conversion failure: " << err.what() << std::endl;
152 }
153 i += 2;
154 try
155 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600156 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
157 bcdTime |= tmp;
Aatir37822f62019-12-10 14:40:27 -0600158 }
Patrick Williams66491c62021-10-06 12:23:37 -0500159 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600160 {
161 std::cout << "Conversion failure: " << err.what() << std::endl;
162 }
163 }
Sumit Kumar104c7962022-02-09 06:30:39 -0600164 return bcdTime;
Aatir37822f62019-12-10 14:40:27 -0600165}
166
167/**
168 * @brief helper function to get PEL id from file name
169 * @retrun uint32_t - PEL id
170 * @param[in] std::string - file name
171 */
172uint32_t fileNameToPELId(const std::string& fileName)
173{
174 uint32_t num = 0;
175 try
176 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500177 num = std::stoul(fileName.substr(fileName.find("_") + 1), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600178 }
Patrick Williams66491c62021-10-06 12:23:37 -0500179 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600180 {
181 std::cout << "Conversion failure: " << err.what() << std::endl;
182 }
183 return num;
184}
185
186/**
Matt Spinler80129fe2023-01-19 15:09:05 -0600187 * @brief Check if the string ends with the PEL ID string passed in
188 * @param[in] str - string to check for PEL ID
189 * @param[in] pelID - PEL id string
190 *
191 * @return bool - true with suffix matches
Aatire340c132019-12-09 14:19:29 -0600192 */
Matt Spinler80129fe2023-01-19 15:09:05 -0600193bool endsWithPelID(const std::string& str, const std::string& pelID)
Aatire340c132019-12-09 14:19:29 -0600194{
Matt Spinler80129fe2023-01-19 15:09:05 -0600195 constexpr size_t pelIDSize = 8;
196
197 if (pelID.size() != pelIDSize)
198 {
199 return false;
200 }
201
202 size_t slen = str.size(), elen = pelID.size();
Aatire340c132019-12-09 14:19:29 -0600203 if (slen < elen)
204 return false;
205 while (elen)
206 {
Matt Spinler80129fe2023-01-19 15:09:05 -0600207 if (str[--slen] != pelID[--elen])
Aatire340c132019-12-09 14:19:29 -0600208 return false;
209 }
210 return true;
211}
212
Aatir37822f62019-12-10 14:40:27 -0600213/**
214 * @brief get data form raw PEL file.
215 * @param[in] std::string Name of file with raw PEL
216 * @return std::vector<uint8_t> char vector read from raw PEL file.
217 */
Aatirbad5f8a2019-12-10 15:27:16 -0600218std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600219{
220 std::ifstream file(name, std::ifstream::in);
221 if (file.good())
222 {
223 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
224 std::istreambuf_iterator<char>()};
225 return data;
226 }
227 else
228 {
Aatir37822f62019-12-10 14:40:27 -0600229 return {};
230 }
231}
232
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800233/**
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800234 * @brief Initialize Python interpreter and gather all UD parser modules under
235 * the paths found in Python sys.path and the current user directory.
236 * This is to prevent calling a non-existant module which causes Python
237 * to print an import error message and breaking JSON output.
238 *
239 * @return std::vector<std::string> Vector of plugins found in filesystem
240 */
241std::vector<std::string> getPlugins()
242{
243 Py_Initialize();
244 std::vector<std::string> plugins;
245 std::vector<std::string> siteDirs;
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800246 std::array<std::string, 2> parserDirs = {"udparsers", "srcparsers"};
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800247 PyObject* pName = PyUnicode_FromString("sys");
248 PyObject* pModule = PyImport_Import(pName);
249 Py_XDECREF(pName);
250 PyObject* pDict = PyModule_GetDict(pModule);
251 Py_XDECREF(pModule);
252 PyObject* pResult = PyDict_GetItemString(pDict, "path");
253 PyObject* pValue = PyUnicode_FromString(".");
254 PyList_Append(pResult, pValue);
255 Py_XDECREF(pValue);
256 auto list_size = PyList_Size(pResult);
257 for (auto i = 0; i < list_size; i++)
258 {
259 PyObject* item = PyList_GetItem(pResult, i);
260 PyObject* pBytes = PyUnicode_AsEncodedString(item, "utf-8", "~E~");
261 const char* output = PyBytes_AS_STRING(pBytes);
262 Py_XDECREF(pBytes);
263 std::string tmpStr(output);
264 siteDirs.push_back(tmpStr);
265 }
266 for (const auto& dir : siteDirs)
267 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800268 for (const auto& parserDir : parserDirs)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800269 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800270 if (fs::exists(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800271 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800272 for (const auto& entry :
273 fs::directory_iterator(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800274 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800275 if (entry.is_directory() and
276 fs::exists(entry.path().string() + "/" +
277 entry.path().stem().string() + ".py"))
278 {
279 plugins.push_back(entry.path().stem());
280 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800281 }
282 }
283 }
284 }
285 return plugins;
286}
287
288/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800289 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
290 * stdout the full PEL in JSON if fullPEL is true
291 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
292 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800293 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000294 * @param[in] critSysTerm - Boolean to include critical error and system
295 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800296 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
297 * @param[in] foundPEL - Boolean to check if any PEL is present
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800298 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800299 * @param[in] plugins - Vector of strings of plugins found in filesystem
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800300 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800301 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
302 */
Aatir7b291ec2019-11-19 10:37:37 -0600303template <typename T>
Miguel Gomez011ccae2021-03-25 23:42:09 +0000304std::string genPELJSON(T itr, bool hidden, bool includeInfo, bool critSysTerm,
305 bool fullPEL, bool& foundPEL,
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800306 const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500307 const std::vector<std::string>& plugins, bool hexDump,
308 bool archive)
Aatir7b291ec2019-11-19 10:37:37 -0600309{
Aatir7b291ec2019-11-19 10:37:37 -0600310 std::string val;
Aatir7b291ec2019-11-19 10:37:37 -0600311 std::string listStr;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700312 char name[51];
Sumit Kumar104c7962022-02-09 06:30:39 -0600313 sprintf(name, "/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X",
314 static_cast<uint8_t>((itr.second >> 56) & 0xFF),
315 static_cast<uint8_t>((itr.second >> 48) & 0xFF),
316 static_cast<uint8_t>((itr.second >> 40) & 0xFF),
317 static_cast<uint8_t>((itr.second >> 32) & 0xFF),
318 static_cast<uint8_t>((itr.second >> 24) & 0xFF),
319 static_cast<uint8_t>((itr.second >> 16) & 0xFF),
320 static_cast<uint8_t>((itr.second >> 8) & 0xFF),
321 static_cast<uint8_t>(itr.second & 0xFF), itr.first);
322
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500323 auto fileName = (archive ? pelLogDir() + "/archive" : pelLogDir()) + name;
Aatir7b291ec2019-11-19 10:37:37 -0600324 try
325 {
Aatir37822f62019-12-10 14:40:27 -0600326 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800327 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600328 {
Matt Spinlera561ff62023-07-17 08:43:55 -0500329 log<level::ERR>("Empty PEL file",
330 entry("FILENAME=%s", fileName.c_str()));
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800331 return listStr;
332 }
333 PEL pel{data};
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800334 if (!pel.valid())
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800335 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800336 return listStr;
337 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800338 if (!includeInfo && pel.userHeader().severity() == 0)
339 {
340 return listStr;
341 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000342 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
343 {
344 return listStr;
345 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800346 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
347 if (!hidden && actionFlags.test(hiddenFlagBit))
348 {
349 return listStr;
350 }
351 if (pel.primarySRC() && scrubRegex)
352 {
353 val = pel.primarySRC().value()->asciiString();
354 if (std::regex_search(trimEnd(val), scrubRegex.value(),
355 std::regex_constants::match_not_null))
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800356 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800357 return listStr;
358 }
359 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800360 if (hexDump)
361 {
Arya K Padman8c8aaa02024-04-28 23:23:45 -0500362 std::cout
363 << dumpHex(std::data(pel.data()), pel.size(), 0, false).get()
364 << std::endl;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800365 }
366 else if (fullPEL)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800367 {
368 if (!foundPEL)
369 {
370 std::cout << "[\n";
371 foundPEL = true;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800372 }
373 else
Aatir7b291ec2019-11-19 10:37:37 -0600374 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800375 std::cout << ",\n\n";
376 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800377 pel.toJSON(registry, plugins);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800378 }
379 else
380 {
381 // id
Matt Spinler3025d0b2021-06-02 15:12:52 -0600382 listStr += " \"" +
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800383 getNumberString("0x%X", pel.privateHeader().id()) +
384 "\": {\n";
385 // ASCII
386 if (pel.primarySRC())
387 {
388 val = pel.primarySRC().value()->asciiString();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600389 jsonInsert(listStr, "SRC", trimEnd(val), 2);
390
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800391 // Registry message
392 auto regVal = pel.primarySRC().value()->getErrorDetails(
393 registry, DetailLevel::message, true);
394 if (regVal)
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800395 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800396 val = regVal.value();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600397 jsonInsert(listStr, "Message", val, 2);
Aatir37822f62019-12-10 14:40:27 -0600398 }
Aatir7b291ec2019-11-19 10:37:37 -0600399 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800400 else
401 {
Matt Spinler3025d0b2021-06-02 15:12:52 -0600402 jsonInsert(listStr, "SRC", "No SRC", 2);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800403 }
Matt Spinler3025d0b2021-06-02 15:12:52 -0600404
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800405 // platformid
Matt Spinler3025d0b2021-06-02 15:12:52 -0600406 jsonInsert(listStr, "PLID",
407 getNumberString("0x%X", pel.privateHeader().plid()), 2);
408
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800409 // creatorid
410 std::string creatorID =
411 getNumberString("%c", pel.privateHeader().creatorID());
412 val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
413 : "Unknown Creator ID";
Matt Spinler3025d0b2021-06-02 15:12:52 -0600414 jsonInsert(listStr, "CreatorID", val, 2);
415
416 // subsystem
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800417 std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
418 pel_values::subsystemValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600419 jsonInsert(listStr, "Subsystem", subsystem, 2);
420
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800421 // commit time
Matt Spinlerbe952d22022-07-01 11:30:11 -0500422 char tmpValStr[50];
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800423 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
424 pel.privateHeader().commitTimestamp().month,
425 pel.privateHeader().commitTimestamp().day,
426 pel.privateHeader().commitTimestamp().yearMSB,
427 pel.privateHeader().commitTimestamp().yearLSB,
428 pel.privateHeader().commitTimestamp().hour,
429 pel.privateHeader().commitTimestamp().minutes,
430 pel.privateHeader().commitTimestamp().seconds);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600431 jsonInsert(listStr, "Commit Time", tmpValStr, 2);
432
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800433 // severity
434 std::string severity = pv::getValue(pel.userHeader().severity(),
435 pel_values::severityValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600436 jsonInsert(listStr, "Sev", severity, 2);
437
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800438 // compID
Matt Spinler9a808702023-03-28 09:39:26 -0500439 jsonInsert(
440 listStr, "CompID",
441 getComponentName(pel.privateHeader().header().componentID,
442 pel.privateHeader().creatorID()),
443 2);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600444
Matt Spinlerbe952d22022-07-01 11:30:11 -0500445 auto found = listStr.rfind(",");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800446 if (found != std::string::npos)
447 {
448 listStr.replace(found, 1, "");
Matt Spinler3025d0b2021-06-02 15:12:52 -0600449 listStr += " },\n";
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800450 }
451 foundPEL = true;
Aatir7b291ec2019-11-19 10:37:37 -0600452 }
453 }
Patrick Williams66491c62021-10-06 12:23:37 -0500454 catch (const std::exception& e)
Aatir7b291ec2019-11-19 10:37:37 -0600455 {
Matt Spinlera561ff62023-07-17 08:43:55 -0500456 log<level::ERR>("Hit exception while reading PEL File",
457 entry("FILENAME=%s", fileName.c_str()),
458 entry("ERROR=%s", e.what()));
Aatir7b291ec2019-11-19 10:37:37 -0600459 }
460 return listStr;
461}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800462
Aatir7b291ec2019-11-19 10:37:37 -0600463/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800464 * @brief Print a list of PELs or a JSON array of PELs
465 * @param[in] order - Boolean to print in reverse orser
466 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800467 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000468 * @param[in] critSysTerm - Boolean to include critical error and system
469 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800470 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800471 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800472 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Aatir7b291ec2019-11-19 10:37:37 -0600473 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000474void printPELs(bool order, bool hidden, bool includeInfo, bool critSysTerm,
475 bool fullPEL, const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500476 bool hexDump, bool archive = false)
Aatir7b291ec2019-11-19 10:37:37 -0600477{
478 std::string listStr;
Sumit Kumar104c7962022-02-09 06:30:39 -0600479 std::vector<std::pair<uint32_t, uint64_t>> PELs;
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800480 std::vector<std::string> plugins;
Aatir7b291ec2019-11-19 10:37:37 -0600481 listStr = "{\n";
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500482 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
483 : fs::directory_iterator(pelLogDir()));
Aatir7b291ec2019-11-19 10:37:37 -0600484 it != fs::directory_iterator(); ++it)
485 {
486 if (!fs::is_regular_file((*it).path()))
487 {
488 continue;
489 }
Aatir37822f62019-12-10 14:40:27 -0600490 else
Aatir7b291ec2019-11-19 10:37:37 -0600491 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600492 PELs.emplace_back(fileNameToPELId((*it).path().filename()),
493 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600494 }
495 }
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500496
Sumit Kumar104c7962022-02-09 06:30:39 -0600497 // Sort the pairs based on second time parameter
Matt Spinlerbe952d22022-07-01 11:30:11 -0500498 std::sort(PELs.begin(), PELs.end(),
499 [](const auto& left, const auto& right) {
Patrick Williamsac1ba3f2023-05-10 07:50:16 -0500500 return left.second < right.second;
501 });
Sumit Kumar104c7962022-02-09 06:30:39 -0600502
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800503 bool foundPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800504
505 if (fullPEL && !hexDump)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800506 {
507 plugins = getPlugins();
508 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000509 auto buildJSON = [&listStr, &hidden, &includeInfo, &critSysTerm, &fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500510 &foundPEL, &scrubRegex, &plugins, &hexDump,
511 &archive](const auto& i) {
Miguel Gomez011ccae2021-03-25 23:42:09 +0000512 listStr += genPELJSON(i, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500513 foundPEL, scrubRegex, plugins, hexDump, archive);
Aatir37822f62019-12-10 14:40:27 -0600514 };
Aatir7b291ec2019-11-19 10:37:37 -0600515 if (order)
516 {
517 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
518 }
519 else
520 {
521 std::for_each(PELs.begin(), PELs.end(), buildJSON);
522 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800523 if (hexDump)
524 {
525 return;
526 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800527 if (foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600528 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800529 if (fullPEL)
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800530 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800531 std::cout << "]" << std::endl;
532 }
533 else
534 {
535 std::size_t found;
536 found = listStr.rfind(",");
537 if (found != std::string::npos)
538 {
539 listStr.replace(found, 1, "");
540 listStr += "}\n";
541 printf("%s", listStr.c_str());
542 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800543 }
544 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800545 else
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800546 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800547 std::string emptyJSON = fullPEL ? "[]" : "{}";
548 std::cout << emptyJSON << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600549 }
550}
Aatir186ce8c2019-10-20 15:13:39 -0500551
Matt Spinler27de6f32020-02-21 08:35:57 -0600552/**
553 * @brief Calls the function passed in on the PEL with the ID
554 * passed in.
555 *
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800556 * @param[in] id - The string version of the PEL or BMC Log ID, either with or
Matt Spinler27de6f32020-02-21 08:35:57 -0600557 * without the 0x prefix.
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800558 * @param[in] func - The std::function<void(const PEL&, bool hexDump)> function
559 * to run.
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800560 * @param[in] useBMC - if true, search by BMC Log ID, else search by PEL ID
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800561 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler27de6f32020-02-21 08:35:57 -0600562 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800563void callFunctionOnPEL(const std::string& id, const PELFunc& func,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500564 bool useBMC = false, bool hexDump = false,
565 bool archive = false)
Matt Spinler27de6f32020-02-21 08:35:57 -0600566{
567 std::string pelID{id};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800568 if (!useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600569 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800570 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
571
Matt Spinlerbe952d22022-07-01 11:30:11 -0500572 if (pelID.starts_with("0X"))
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800573 {
574 pelID.erase(0, 2);
575 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600576 }
577
578 bool found = false;
579
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500580 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
581 : fs::directory_iterator(pelLogDir()));
Matt Spinler27de6f32020-02-21 08:35:57 -0600582 it != fs::directory_iterator(); ++it)
583 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800584 // The PEL ID is part of the filename, so use that to find the PEL if
585 // "useBMC" is set to false, otherwise we have to search within the PEL
Matt Spinler27de6f32020-02-21 08:35:57 -0600586
587 if (!fs::is_regular_file((*it).path()))
588 {
589 continue;
590 }
591
Matt Spinler80129fe2023-01-19 15:09:05 -0600592 if ((endsWithPelID((*it).path(), pelID) && !useBMC) || useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600593 {
Matt Spinler27de6f32020-02-21 08:35:57 -0600594 auto data = getFileData((*it).path());
595 if (!data.empty())
596 {
597 PEL pel{data};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800598 if (!useBMC ||
599 (useBMC && pel.obmcLogID() == std::stoul(id, nullptr, 0)))
Matt Spinler27de6f32020-02-21 08:35:57 -0600600 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800601 found = true;
602 try
603 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800604 func(pel, hexDump);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800605 break;
606 }
Patrick Williams66491c62021-10-06 12:23:37 -0500607 catch (const std::exception& e)
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800608 {
609 std::cerr << " Internal function threw an exception: "
610 << e.what() << "\n";
611 exit(1);
612 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600613 }
614 }
615 else
616 {
617 std::cerr << "Could not read PEL file\n";
618 exit(1);
619 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600620 }
621 }
622
623 if (!found)
624 {
625 std::cerr << "PEL not found\n";
626 exit(1);
627 }
628}
629
630/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600631 * @brief Delete a PEL file.
Matt Spinler27de6f32020-02-21 08:35:57 -0600632 *
Matt Spinler25d986c2021-02-10 13:26:18 -0600633 * @param[in] id - The PEL ID to delete.
Matt Spinler27de6f32020-02-21 08:35:57 -0600634 */
Matt Spinler25d986c2021-02-10 13:26:18 -0600635void deletePEL(const std::string& id)
Matt Spinler27de6f32020-02-21 08:35:57 -0600636{
Matt Spinler25d986c2021-02-10 13:26:18 -0600637 std::string pelID{id};
Matt Spinler27de6f32020-02-21 08:35:57 -0600638
Matt Spinler25d986c2021-02-10 13:26:18 -0600639 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
640
Matt Spinlerbe952d22022-07-01 11:30:11 -0500641 if (pelID.starts_with("0X"))
Matt Spinler27de6f32020-02-21 08:35:57 -0600642 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600643 pelID.erase(0, 2);
Matt Spinler27de6f32020-02-21 08:35:57 -0600644 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600645
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700646 for (auto it = fs::directory_iterator(pelLogDir());
Matt Spinler25d986c2021-02-10 13:26:18 -0600647 it != fs::directory_iterator(); ++it)
Matt Spinler27de6f32020-02-21 08:35:57 -0600648 {
Matt Spinler80129fe2023-01-19 15:09:05 -0600649 if (endsWithPelID((*it).path(), pelID))
Matt Spinler25d986c2021-02-10 13:26:18 -0600650 {
651 fs::remove((*it).path());
652 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600653 }
654}
655
656/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600657 * @brief Delete all PEL files.
Matt Spinler27de6f32020-02-21 08:35:57 -0600658 */
659void deleteAllPELs()
660{
Matt Spinlera561ff62023-07-17 08:43:55 -0500661 log<level::INFO>("peltool deleting all event logs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600662
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700663 for (const auto& entry : fs::directory_iterator(pelLogDir()))
Matt Spinler27de6f32020-02-21 08:35:57 -0600664 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500665 if (!fs::is_regular_file(entry.path()))
666 {
667 continue;
668 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600669 fs::remove(entry.path());
Matt Spinler27de6f32020-02-21 08:35:57 -0600670 }
671}
672
Matt Spinler1b420bc2020-02-21 08:54:25 -0600673/**
674 * @brief Display a single PEL
675 *
676 * @param[in] pel - the PEL to display
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800677 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler1b420bc2020-02-21 08:54:25 -0600678 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800679void displayPEL(const PEL& pel, bool hexDump)
Matt Spinler1b420bc2020-02-21 08:54:25 -0600680{
681 if (pel.valid())
682 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800683 if (hexDump)
684 {
Arya K Padman8c8aaa02024-04-28 23:23:45 -0500685 std::string dstr =
686 dumpHex(std::data(pel.data()), pel.size(), 0, false).get();
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800687 std::cout << dstr << std::endl;
688 }
689 else
690 {
691 auto plugins = getPlugins();
692 pel.toJSON(registry, plugins);
693 }
Matt Spinler1b420bc2020-02-21 08:54:25 -0600694 }
695 else
696 {
697 std::cerr << "PEL was malformed\n";
698 exit(1);
699 }
700}
701
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800702/**
703 * @brief Print number of PELs
704 * @param[in] hidden - Bool to include hidden logs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800705 * @param[in] includeInfo - Bool to include informational logs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000706 * @param[in] critSysTerm - Bool to include CritSysTerm
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800707 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800708 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000709void printPELCount(bool hidden, bool includeInfo, bool critSysTerm,
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800710 const std::optional<std::regex>& scrubRegex)
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800711{
712 std::size_t count = 0;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700713
714 for (auto it = fs::directory_iterator(pelLogDir());
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800715 it != fs::directory_iterator(); ++it)
716 {
717 if (!fs::is_regular_file((*it).path()))
718 {
719 continue;
720 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800721 std::vector<uint8_t> data = getFileData((*it).path());
722 if (data.empty())
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800723 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800724 continue;
725 }
726 PEL pel{data};
727 if (!pel.valid())
728 {
729 continue;
730 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800731 if (!includeInfo && pel.userHeader().severity() == 0)
732 {
733 continue;
734 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000735 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
736 {
737 continue;
738 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800739 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
740 if (!hidden && actionFlags.test(hiddenFlagBit))
741 {
742 continue;
743 }
744 if (pel.primarySRC() && scrubRegex)
745 {
746 std::string val = pel.primarySRC().value()->asciiString();
747 if (std::regex_search(trimEnd(val), scrubRegex.value(),
748 std::regex_constants::match_not_null))
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800749 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800750 continue;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800751 }
752 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800753 count++;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800754 }
755 std::cout << "{\n"
756 << " \"Number of PELs found\": "
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800757 << getNumberString("%d", count) << "\n}\n";
758}
759
760/**
761 * @brief Generate regex pattern object from file contents
762 * @param[in] scrubFile - File containing regex pattern
763 * @return std::regex - SRC regex object
764 */
765std::regex genRegex(std::string& scrubFile)
766{
767 std::string pattern;
768 std::ifstream contents(scrubFile);
769 if (contents.fail())
770 {
771 std::cerr << "Can't open \"" << scrubFile << "\"\n";
772 exit(1);
773 }
774 std::string line;
775 while (std::getline(contents, line))
776 {
777 if (!line.empty())
778 {
779 pattern.append(line + "|");
780 }
781 }
782 try
783 {
784 std::regex scrubRegex(pattern, std::regex::icase);
785 return scrubRegex;
786 }
Patrick Williams66491c62021-10-06 12:23:37 -0500787 catch (const std::regex_error& e)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800788 {
789 if (e.code() == std::regex_constants::error_collate)
790 std::cerr << "Invalid collating element request\n";
791 else if (e.code() == std::regex_constants::error_ctype)
792 std::cerr << "Invalid character class\n";
793 else if (e.code() == std::regex_constants::error_escape)
794 std::cerr << "Invalid escape character or trailing escape\n";
795 else if (e.code() == std::regex_constants::error_backref)
796 std::cerr << "Invalid back reference\n";
797 else if (e.code() == std::regex_constants::error_brack)
798 std::cerr << "Mismatched bracket ([ or ])\n";
799 else if (e.code() == std::regex_constants::error_paren)
800 {
801 // to catch return code error_badrepeat when error_paren is retured
802 // instead
803 size_t pos = pattern.find_first_of("*+?{");
804 while (pos != std::string::npos)
805 {
806 if (pos == 0 || pattern.substr(pos - 1, 1) == "|")
807 {
808 std::cerr
809 << "A repetition character (*, ?, +, or {) was not "
810 "preceded by a valid regular expression\n";
811 exit(1);
812 }
813 pos = pattern.find_first_of("*+?{", pos + 1);
814 }
815 std::cerr << "Mismatched parentheses (( or ))\n";
816 }
817 else if (e.code() == std::regex_constants::error_brace)
818 std::cerr << "Mismatched brace ({ or })\n";
819 else if (e.code() == std::regex_constants::error_badbrace)
820 std::cerr << "Invalid range inside a { }\n";
821 else if (e.code() == std::regex_constants::error_range)
822 std::cerr << "Invalid character range (e.g., [z-a])\n";
823 else if (e.code() == std::regex_constants::error_space)
824 std::cerr << "Insufficient memory to handle regular expression\n";
825 else if (e.code() == std::regex_constants::error_badrepeat)
826 std::cerr << "A repetition character (*, ?, +, or {) was not "
827 "preceded by a valid regular expression\n";
828 else if (e.code() == std::regex_constants::error_complexity)
829 std::cerr << "The requested match is too complex\n";
830 else if (e.code() == std::regex_constants::error_stack)
831 std::cerr << "Insufficient memory to evaluate a match\n";
832 exit(1);
833 }
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800834}
835
Aatir186ce8c2019-10-20 15:13:39 -0500836static void exitWithError(const std::string& help, const char* err)
837{
838 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
839 exit(-1);
840}
841
842int main(int argc, char** argv)
843{
844 CLI::App app{"OpenBMC PEL Tool"};
845 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600846 std::string idPEL;
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800847 std::string bmcId;
Matt Spinler27de6f32020-02-21 08:35:57 -0600848 std::string idToDelete;
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800849 std::string scrubFile;
850 std::optional<std::regex> scrubRegex;
Aatire340c132019-12-09 14:19:29 -0600851 bool listPEL = false;
852 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800853 bool hidden = false;
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800854 bool includeInfo = false;
Miguel Gomez011ccae2021-03-25 23:42:09 +0000855 bool critSysTerm = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600856 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800857 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800858 bool fullPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800859 bool hexDump = false;
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500860 bool archive = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600861
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800862 app.set_help_flag("--help", "Print this help message and exit");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800863 app.add_option("--file", fileName, "Display a PEL using its Raw PEL file");
Aatire340c132019-12-09 14:19:29 -0600864 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800865 app.add_option("--bmc-id", bmcId,
866 "Display a PEL based on its BMC Event ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800867 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600868 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800869 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600870 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800871 app.add_flag("-h", hidden, "Include hidden PELs");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800872 app.add_flag("-f,--info", includeInfo, "Include informational PELs");
Miguel Gomez011ccae2021-03-25 23:42:09 +0000873 app.add_flag("-t, --termination", critSysTerm,
874 "List only critical system terminating PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600875 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
876 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800877 app.add_option("-s, --scrub", scrubFile,
878 "File containing SRC regular expressions to ignore");
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800879 app.add_flag("-x", hexDump, "Display PEL(s) in hexdump instead of JSON");
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500880 app.add_flag("--archive", archive, "List or display archived PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600881
Aatir186ce8c2019-10-20 15:13:39 -0500882 CLI11_PARSE(app, argc, argv);
883
884 if (!fileName.empty())
885 {
886 std::vector<uint8_t> data = getFileData(fileName);
887 if (!data.empty())
888 {
889 PEL pel{data};
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800890 if (hexDump)
891 {
Arya K Padman8c8aaa02024-04-28 23:23:45 -0500892 std::string dstr =
893 dumpHex(std::data(pel.data()), pel.size(), 0, false).get();
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800894 std::cout << dstr << std::endl;
895 }
896 else
897 {
898 auto plugins = getPlugins();
899 pel.toJSON(registry, plugins);
900 }
Aatir186ce8c2019-10-20 15:13:39 -0500901 }
902 else
903 {
904 exitWithError(app.help("", CLI::AppFormatMode::All),
905 "Raw PEL file can't be read.");
906 }
907 }
Aatire340c132019-12-09 14:19:29 -0600908 else if (!idPEL.empty())
909 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500910 callFunctionOnPEL(idPEL, displayPEL, false, hexDump, archive);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800911 }
912 else if (!bmcId.empty())
913 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500914 callFunctionOnPEL(bmcId, displayPEL, true, hexDump, archive);
Aatire340c132019-12-09 14:19:29 -0600915 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800916 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600917 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800918 if (!scrubFile.empty())
919 {
920 scrubRegex = genRegex(scrubFile);
921 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000922 printPELs(listPELDescOrd, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500923 scrubRegex, hexDump, archive);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800924 }
925 else if (showPELCount)
926 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800927 if (!scrubFile.empty())
928 {
929 scrubRegex = genRegex(scrubFile);
930 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000931 printPELCount(hidden, includeInfo, critSysTerm, scrubRegex);
Aatir7b291ec2019-11-19 10:37:37 -0600932 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600933 else if (!idToDelete.empty())
934 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600935 deletePEL(idToDelete);
Matt Spinler27de6f32020-02-21 08:35:57 -0600936 }
937 else if (deleteAll)
938 {
939 deleteAllPELs();
940 }
Aatir186ce8c2019-10-20 15:13:39 -0500941 else
942 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800943 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500944 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800945 Py_Finalize();
Aatir186ce8c2019-10-20 15:13:39 -0500946 return 0;
947}