blob: 643a8a2c4a0e6018f6c80bee2d2b52bdbc186b62 [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 Spinleraaf23ee2023-07-07 16:29:52 -050030#include <phosphor-logging/lg2.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;
Aatir186ce8c2019-10-20 15:13:39 -050039using namespace openpower::pels;
Aatir7b291ec2019-11-19 10:37:37 -060040namespace message = openpower::pels::message;
41namespace pv = openpower::pels::pel_values;
Aatir186ce8c2019-10-20 15:13:39 -050042
Miguel Gomez011ccae2021-03-25 23:42:09 +000043const uint8_t critSysTermSeverity = 0x51;
44
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +080045using PELFunc = std::function<void(const PEL&, bool hexDump)>;
Matt Spinler0d804ef2020-05-12 16:16:26 -050046message::Registry registry(getPELReadOnlyDataPath() / message::registryFileName,
Matt Spinlerd8e29002020-04-09 09:11:22 -050047 false);
Matt Spinler27de6f32020-02-21 08:35:57 -060048namespace service
49{
50constexpr auto logging = "xyz.openbmc_project.Logging";
51} // namespace service
52
53namespace interface
54{
55constexpr auto deleteObj = "xyz.openbmc_project.Object.Delete";
56constexpr auto deleteAll = "xyz.openbmc_project.Collection.DeleteAll";
57} // namespace interface
58
59namespace object_path
60{
61constexpr auto logEntry = "/xyz/openbmc_project/logging/entry/";
62constexpr auto logging = "/xyz/openbmc_project/logging";
63} // namespace object_path
64
William A. Kennington IIIb6b25572021-05-19 17:09:41 -070065std::string pelLogDir()
66{
67 return std::string(EXTENSION_PERSIST_DIR) + "/pels/logs";
68}
69
Aatire340c132019-12-09 14:19:29 -060070/**
Aatir37822f62019-12-10 14:40:27 -060071 * @brief helper function to get PEL commit timestamp from file name
Sumit Kumar104c7962022-02-09 06:30:39 -060072 * @retrun uint64_t - PEL commit timestamp
Aatir37822f62019-12-10 14:40:27 -060073 * @param[in] std::string - file name
74 */
Sumit Kumar104c7962022-02-09 06:30:39 -060075uint64_t fileNameToTimestamp(const std::string& fileName)
Aatir37822f62019-12-10 14:40:27 -060076{
77 std::string token = fileName.substr(0, fileName.find("_"));
Sumit Kumar104c7962022-02-09 06:30:39 -060078 uint64_t bcdTime = 0;
Aatir37822f62019-12-10 14:40:27 -060079 if (token.length() >= 14)
80 {
Matt Spinlerbe952d22022-07-01 11:30:11 -050081 int i = 0;
82
Aatir37822f62019-12-10 14:40:27 -060083 try
84 {
Sumit Kumar104c7962022-02-09 06:30:39 -060085 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
86 bcdTime |= (static_cast<uint64_t>(tmp) << 56);
Aatir37822f62019-12-10 14:40:27 -060087 }
Patrick Williams66491c62021-10-06 12:23:37 -050088 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060089 {
90 std::cout << "Conversion failure: " << err.what() << std::endl;
91 }
92 i += 2;
93 try
94 {
Sumit Kumar104c7962022-02-09 06:30:39 -060095 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
96 bcdTime |= (static_cast<uint64_t>(tmp) << 48);
Aatir37822f62019-12-10 14:40:27 -060097 }
Patrick Williams66491c62021-10-06 12:23:37 -050098 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060099 {
100 std::cout << "Conversion failure: " << err.what() << std::endl;
101 }
102 i += 2;
103 try
104 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600105 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
106 bcdTime |= (static_cast<uint64_t>(tmp) << 40);
Aatir37822f62019-12-10 14:40:27 -0600107 }
Patrick Williams66491c62021-10-06 12:23:37 -0500108 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600109 {
110 std::cout << "Conversion failure: " << err.what() << std::endl;
111 }
112 i += 2;
113 try
114 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600115 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
116 bcdTime |= (static_cast<uint64_t>(tmp) << 32);
Aatir37822f62019-12-10 14:40:27 -0600117 }
Patrick Williams66491c62021-10-06 12:23:37 -0500118 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600119 {
120 std::cout << "Conversion failure: " << err.what() << std::endl;
121 }
122 i += 2;
123 try
124 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600125 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
126 bcdTime |= (tmp << 24);
Aatir37822f62019-12-10 14:40:27 -0600127 }
Patrick Williams66491c62021-10-06 12:23:37 -0500128 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600129 {
130 std::cout << "Conversion failure: " << err.what() << std::endl;
131 }
132 i += 2;
133 try
134 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600135 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
136 bcdTime |= (tmp << 16);
Aatir37822f62019-12-10 14:40:27 -0600137 }
Patrick Williams66491c62021-10-06 12:23:37 -0500138 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600139 {
140 std::cout << "Conversion failure: " << err.what() << std::endl;
141 }
142 i += 2;
143 try
144 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600145 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
146 bcdTime |= (tmp << 8);
Aatir37822f62019-12-10 14:40:27 -0600147 }
Patrick Williams66491c62021-10-06 12:23:37 -0500148 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600149 {
150 std::cout << "Conversion failure: " << err.what() << std::endl;
151 }
152 i += 2;
153 try
154 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600155 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
156 bcdTime |= tmp;
Aatir37822f62019-12-10 14:40:27 -0600157 }
Patrick Williams66491c62021-10-06 12:23:37 -0500158 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600159 {
160 std::cout << "Conversion failure: " << err.what() << std::endl;
161 }
162 }
Sumit Kumar104c7962022-02-09 06:30:39 -0600163 return bcdTime;
Aatir37822f62019-12-10 14:40:27 -0600164}
165
166/**
167 * @brief helper function to get PEL id from file name
168 * @retrun uint32_t - PEL id
169 * @param[in] std::string - file name
170 */
171uint32_t fileNameToPELId(const std::string& fileName)
172{
173 uint32_t num = 0;
174 try
175 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500176 num = std::stoul(fileName.substr(fileName.find("_") + 1), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600177 }
Patrick Williams66491c62021-10-06 12:23:37 -0500178 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600179 {
180 std::cout << "Conversion failure: " << err.what() << std::endl;
181 }
182 return num;
183}
184
185/**
Matt Spinler80129fe2023-01-19 15:09:05 -0600186 * @brief Check if the string ends with the PEL ID string passed in
187 * @param[in] str - string to check for PEL ID
188 * @param[in] pelID - PEL id string
189 *
190 * @return bool - true with suffix matches
Aatire340c132019-12-09 14:19:29 -0600191 */
Matt Spinler80129fe2023-01-19 15:09:05 -0600192bool endsWithPelID(const std::string& str, const std::string& pelID)
Aatire340c132019-12-09 14:19:29 -0600193{
Matt Spinler80129fe2023-01-19 15:09:05 -0600194 constexpr size_t pelIDSize = 8;
195
196 if (pelID.size() != pelIDSize)
197 {
198 return false;
199 }
200
201 size_t slen = str.size(), elen = pelID.size();
Aatire340c132019-12-09 14:19:29 -0600202 if (slen < elen)
203 return false;
204 while (elen)
205 {
Matt Spinler80129fe2023-01-19 15:09:05 -0600206 if (str[--slen] != pelID[--elen])
Aatire340c132019-12-09 14:19:29 -0600207 return false;
208 }
209 return true;
210}
211
Aatir37822f62019-12-10 14:40:27 -0600212/**
213 * @brief get data form raw PEL file.
214 * @param[in] std::string Name of file with raw PEL
215 * @return std::vector<uint8_t> char vector read from raw PEL file.
216 */
Aatirbad5f8a2019-12-10 15:27:16 -0600217std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600218{
219 std::ifstream file(name, std::ifstream::in);
220 if (file.good())
221 {
222 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
223 std::istreambuf_iterator<char>()};
224 return data;
225 }
226 else
227 {
Aatir37822f62019-12-10 14:40:27 -0600228 return {};
229 }
230}
231
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800232/**
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800233 * @brief Initialize Python interpreter and gather all UD parser modules under
234 * the paths found in Python sys.path and the current user directory.
235 * This is to prevent calling a non-existant module which causes Python
236 * to print an import error message and breaking JSON output.
237 *
238 * @return std::vector<std::string> Vector of plugins found in filesystem
239 */
240std::vector<std::string> getPlugins()
241{
242 Py_Initialize();
243 std::vector<std::string> plugins;
244 std::vector<std::string> siteDirs;
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800245 std::array<std::string, 2> parserDirs = {"udparsers", "srcparsers"};
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800246 PyObject* pName = PyUnicode_FromString("sys");
247 PyObject* pModule = PyImport_Import(pName);
248 Py_XDECREF(pName);
249 PyObject* pDict = PyModule_GetDict(pModule);
250 Py_XDECREF(pModule);
251 PyObject* pResult = PyDict_GetItemString(pDict, "path");
252 PyObject* pValue = PyUnicode_FromString(".");
253 PyList_Append(pResult, pValue);
254 Py_XDECREF(pValue);
255 auto list_size = PyList_Size(pResult);
256 for (auto i = 0; i < list_size; i++)
257 {
258 PyObject* item = PyList_GetItem(pResult, i);
259 PyObject* pBytes = PyUnicode_AsEncodedString(item, "utf-8", "~E~");
260 const char* output = PyBytes_AS_STRING(pBytes);
261 Py_XDECREF(pBytes);
262 std::string tmpStr(output);
263 siteDirs.push_back(tmpStr);
264 }
265 for (const auto& dir : siteDirs)
266 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800267 for (const auto& parserDir : parserDirs)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800268 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800269 if (fs::exists(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800270 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800271 for (const auto& entry :
272 fs::directory_iterator(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800273 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800274 if (entry.is_directory() and
275 fs::exists(entry.path().string() + "/" +
276 entry.path().stem().string() + ".py"))
277 {
278 plugins.push_back(entry.path().stem());
279 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800280 }
281 }
282 }
283 }
284 return plugins;
285}
286
287/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800288 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
289 * stdout the full PEL in JSON if fullPEL is true
290 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
291 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800292 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000293 * @param[in] critSysTerm - Boolean to include critical error and system
294 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800295 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
296 * @param[in] foundPEL - Boolean to check if any PEL is present
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800297 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800298 * @param[in] plugins - Vector of strings of plugins found in filesystem
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800299 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800300 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
301 */
Aatir7b291ec2019-11-19 10:37:37 -0600302template <typename T>
Miguel Gomez011ccae2021-03-25 23:42:09 +0000303std::string genPELJSON(T itr, bool hidden, bool includeInfo, bool critSysTerm,
304 bool fullPEL, bool& foundPEL,
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800305 const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500306 const std::vector<std::string>& plugins, bool hexDump,
307 bool archive)
Aatir7b291ec2019-11-19 10:37:37 -0600308{
Aatir7b291ec2019-11-19 10:37:37 -0600309 std::string val;
Aatir7b291ec2019-11-19 10:37:37 -0600310 std::string listStr;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700311 char name[51];
Sumit Kumar104c7962022-02-09 06:30:39 -0600312 sprintf(name, "/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X",
313 static_cast<uint8_t>((itr.second >> 56) & 0xFF),
314 static_cast<uint8_t>((itr.second >> 48) & 0xFF),
315 static_cast<uint8_t>((itr.second >> 40) & 0xFF),
316 static_cast<uint8_t>((itr.second >> 32) & 0xFF),
317 static_cast<uint8_t>((itr.second >> 24) & 0xFF),
318 static_cast<uint8_t>((itr.second >> 16) & 0xFF),
319 static_cast<uint8_t>((itr.second >> 8) & 0xFF),
320 static_cast<uint8_t>(itr.second & 0xFF), itr.first);
321
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500322 auto fileName = (archive ? pelLogDir() + "/archive" : pelLogDir()) + name;
Aatir7b291ec2019-11-19 10:37:37 -0600323 try
324 {
Aatir37822f62019-12-10 14:40:27 -0600325 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800326 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600327 {
Matt Spinleraaf23ee2023-07-07 16:29:52 -0500328 lg2::error("Empty PEL file {FILE}", "FILE", fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800329 return listStr;
330 }
331 PEL pel{data};
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800332 if (!pel.valid())
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800333 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800334 return listStr;
335 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800336 if (!includeInfo && pel.userHeader().severity() == 0)
337 {
338 return listStr;
339 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000340 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
341 {
342 return listStr;
343 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800344 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
345 if (!hidden && actionFlags.test(hiddenFlagBit))
346 {
347 return listStr;
348 }
349 if (pel.primarySRC() && scrubRegex)
350 {
351 val = pel.primarySRC().value()->asciiString();
352 if (std::regex_search(trimEnd(val), scrubRegex.value(),
353 std::regex_constants::match_not_null))
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800354 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800355 return listStr;
356 }
357 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800358 if (hexDump)
359 {
360 std::cout << dumpHex(std::data(pel.data()), pel.size(), 0, false)
361 << std::endl;
362 }
363 else if (fullPEL)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800364 {
365 if (!foundPEL)
366 {
367 std::cout << "[\n";
368 foundPEL = true;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800369 }
370 else
Aatir7b291ec2019-11-19 10:37:37 -0600371 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800372 std::cout << ",\n\n";
373 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800374 pel.toJSON(registry, plugins);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800375 }
376 else
377 {
378 // id
Matt Spinler3025d0b2021-06-02 15:12:52 -0600379 listStr += " \"" +
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800380 getNumberString("0x%X", pel.privateHeader().id()) +
381 "\": {\n";
382 // ASCII
383 if (pel.primarySRC())
384 {
385 val = pel.primarySRC().value()->asciiString();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600386 jsonInsert(listStr, "SRC", trimEnd(val), 2);
387
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800388 // Registry message
389 auto regVal = pel.primarySRC().value()->getErrorDetails(
390 registry, DetailLevel::message, true);
391 if (regVal)
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800392 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800393 val = regVal.value();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600394 jsonInsert(listStr, "Message", val, 2);
Aatir37822f62019-12-10 14:40:27 -0600395 }
Aatir7b291ec2019-11-19 10:37:37 -0600396 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800397 else
398 {
Matt Spinler3025d0b2021-06-02 15:12:52 -0600399 jsonInsert(listStr, "SRC", "No SRC", 2);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800400 }
Matt Spinler3025d0b2021-06-02 15:12:52 -0600401
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800402 // platformid
Matt Spinler3025d0b2021-06-02 15:12:52 -0600403 jsonInsert(listStr, "PLID",
404 getNumberString("0x%X", pel.privateHeader().plid()), 2);
405
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800406 // creatorid
407 std::string creatorID =
408 getNumberString("%c", pel.privateHeader().creatorID());
409 val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
410 : "Unknown Creator ID";
Matt Spinler3025d0b2021-06-02 15:12:52 -0600411 jsonInsert(listStr, "CreatorID", val, 2);
412
413 // subsystem
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800414 std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
415 pel_values::subsystemValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600416 jsonInsert(listStr, "Subsystem", subsystem, 2);
417
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800418 // commit time
Matt Spinlerbe952d22022-07-01 11:30:11 -0500419 char tmpValStr[50];
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800420 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
421 pel.privateHeader().commitTimestamp().month,
422 pel.privateHeader().commitTimestamp().day,
423 pel.privateHeader().commitTimestamp().yearMSB,
424 pel.privateHeader().commitTimestamp().yearLSB,
425 pel.privateHeader().commitTimestamp().hour,
426 pel.privateHeader().commitTimestamp().minutes,
427 pel.privateHeader().commitTimestamp().seconds);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600428 jsonInsert(listStr, "Commit Time", tmpValStr, 2);
429
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800430 // severity
431 std::string severity = pv::getValue(pel.userHeader().severity(),
432 pel_values::severityValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600433 jsonInsert(listStr, "Sev", severity, 2);
434
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800435 // compID
Matt Spinler9a808702023-03-28 09:39:26 -0500436 jsonInsert(
437 listStr, "CompID",
438 getComponentName(pel.privateHeader().header().componentID,
439 pel.privateHeader().creatorID()),
440 2);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600441
Matt Spinlerbe952d22022-07-01 11:30:11 -0500442 auto found = listStr.rfind(",");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800443 if (found != std::string::npos)
444 {
445 listStr.replace(found, 1, "");
Matt Spinler3025d0b2021-06-02 15:12:52 -0600446 listStr += " },\n";
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800447 }
448 foundPEL = true;
Aatir7b291ec2019-11-19 10:37:37 -0600449 }
450 }
Patrick Williams66491c62021-10-06 12:23:37 -0500451 catch (const std::exception& e)
Aatir7b291ec2019-11-19 10:37:37 -0600452 {
Matt Spinleraaf23ee2023-07-07 16:29:52 -0500453 lg2::error("Hit exception while reading PEL File {FILE}: {ERROR}",
454 "FILE", fileName, "ERROR", e);
Aatir7b291ec2019-11-19 10:37:37 -0600455 }
456 return listStr;
457}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800458
Aatir7b291ec2019-11-19 10:37:37 -0600459/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800460 * @brief Print a list of PELs or a JSON array of PELs
461 * @param[in] order - Boolean to print in reverse orser
462 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800463 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000464 * @param[in] critSysTerm - Boolean to include critical error and system
465 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800466 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800467 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800468 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Aatir7b291ec2019-11-19 10:37:37 -0600469 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000470void printPELs(bool order, bool hidden, bool includeInfo, bool critSysTerm,
471 bool fullPEL, const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500472 bool hexDump, bool archive = false)
Aatir7b291ec2019-11-19 10:37:37 -0600473{
474 std::string listStr;
Sumit Kumar104c7962022-02-09 06:30:39 -0600475 std::vector<std::pair<uint32_t, uint64_t>> PELs;
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800476 std::vector<std::string> plugins;
Aatir7b291ec2019-11-19 10:37:37 -0600477 listStr = "{\n";
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500478 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
479 : fs::directory_iterator(pelLogDir()));
Aatir7b291ec2019-11-19 10:37:37 -0600480 it != fs::directory_iterator(); ++it)
481 {
482 if (!fs::is_regular_file((*it).path()))
483 {
484 continue;
485 }
Aatir37822f62019-12-10 14:40:27 -0600486 else
Aatir7b291ec2019-11-19 10:37:37 -0600487 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600488 PELs.emplace_back(fileNameToPELId((*it).path().filename()),
489 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600490 }
491 }
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500492
Sumit Kumar104c7962022-02-09 06:30:39 -0600493 // Sort the pairs based on second time parameter
Matt Spinlerbe952d22022-07-01 11:30:11 -0500494 std::sort(PELs.begin(), PELs.end(),
495 [](const auto& left, const auto& right) {
Patrick Williamsac1ba3f2023-05-10 07:50:16 -0500496 return left.second < right.second;
497 });
Sumit Kumar104c7962022-02-09 06:30:39 -0600498
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800499 bool foundPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800500
501 if (fullPEL && !hexDump)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800502 {
503 plugins = getPlugins();
504 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000505 auto buildJSON = [&listStr, &hidden, &includeInfo, &critSysTerm, &fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500506 &foundPEL, &scrubRegex, &plugins, &hexDump,
507 &archive](const auto& i) {
Miguel Gomez011ccae2021-03-25 23:42:09 +0000508 listStr += genPELJSON(i, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500509 foundPEL, scrubRegex, plugins, hexDump, archive);
Aatir37822f62019-12-10 14:40:27 -0600510 };
Aatir7b291ec2019-11-19 10:37:37 -0600511 if (order)
512 {
513 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
514 }
515 else
516 {
517 std::for_each(PELs.begin(), PELs.end(), buildJSON);
518 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800519 if (hexDump)
520 {
521 return;
522 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800523 if (foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600524 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800525 if (fullPEL)
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800526 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800527 std::cout << "]" << std::endl;
528 }
529 else
530 {
531 std::size_t found;
532 found = listStr.rfind(",");
533 if (found != std::string::npos)
534 {
535 listStr.replace(found, 1, "");
536 listStr += "}\n";
537 printf("%s", listStr.c_str());
538 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800539 }
540 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800541 else
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800542 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800543 std::string emptyJSON = fullPEL ? "[]" : "{}";
544 std::cout << emptyJSON << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600545 }
546}
Aatir186ce8c2019-10-20 15:13:39 -0500547
Matt Spinler27de6f32020-02-21 08:35:57 -0600548/**
549 * @brief Calls the function passed in on the PEL with the ID
550 * passed in.
551 *
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800552 * @param[in] id - The string version of the PEL or BMC Log ID, either with or
Matt Spinler27de6f32020-02-21 08:35:57 -0600553 * without the 0x prefix.
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800554 * @param[in] func - The std::function<void(const PEL&, bool hexDump)> function
555 * to run.
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800556 * @param[in] useBMC - if true, search by BMC Log ID, else search by PEL ID
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800557 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler27de6f32020-02-21 08:35:57 -0600558 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800559void callFunctionOnPEL(const std::string& id, const PELFunc& func,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500560 bool useBMC = false, bool hexDump = false,
561 bool archive = false)
Matt Spinler27de6f32020-02-21 08:35:57 -0600562{
563 std::string pelID{id};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800564 if (!useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600565 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800566 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
567
Matt Spinlerbe952d22022-07-01 11:30:11 -0500568 if (pelID.starts_with("0X"))
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800569 {
570 pelID.erase(0, 2);
571 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600572 }
573
574 bool found = false;
575
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500576 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
577 : fs::directory_iterator(pelLogDir()));
Matt Spinler27de6f32020-02-21 08:35:57 -0600578 it != fs::directory_iterator(); ++it)
579 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800580 // The PEL ID is part of the filename, so use that to find the PEL if
581 // "useBMC" is set to false, otherwise we have to search within the PEL
Matt Spinler27de6f32020-02-21 08:35:57 -0600582
583 if (!fs::is_regular_file((*it).path()))
584 {
585 continue;
586 }
587
Matt Spinler80129fe2023-01-19 15:09:05 -0600588 if ((endsWithPelID((*it).path(), pelID) && !useBMC) || useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600589 {
Matt Spinler27de6f32020-02-21 08:35:57 -0600590 auto data = getFileData((*it).path());
591 if (!data.empty())
592 {
593 PEL pel{data};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800594 if (!useBMC ||
595 (useBMC && pel.obmcLogID() == std::stoul(id, nullptr, 0)))
Matt Spinler27de6f32020-02-21 08:35:57 -0600596 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800597 found = true;
598 try
599 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800600 func(pel, hexDump);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800601 break;
602 }
Patrick Williams66491c62021-10-06 12:23:37 -0500603 catch (const std::exception& e)
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800604 {
605 std::cerr << " Internal function threw an exception: "
606 << e.what() << "\n";
607 exit(1);
608 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600609 }
610 }
611 else
612 {
613 std::cerr << "Could not read PEL file\n";
614 exit(1);
615 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600616 }
617 }
618
619 if (!found)
620 {
621 std::cerr << "PEL not found\n";
622 exit(1);
623 }
624}
625
626/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600627 * @brief Delete a PEL file.
Matt Spinler27de6f32020-02-21 08:35:57 -0600628 *
Matt Spinler25d986c2021-02-10 13:26:18 -0600629 * @param[in] id - The PEL ID to delete.
Matt Spinler27de6f32020-02-21 08:35:57 -0600630 */
Matt Spinler25d986c2021-02-10 13:26:18 -0600631void deletePEL(const std::string& id)
Matt Spinler27de6f32020-02-21 08:35:57 -0600632{
Matt Spinler25d986c2021-02-10 13:26:18 -0600633 std::string pelID{id};
Matt Spinler27de6f32020-02-21 08:35:57 -0600634
Matt Spinler25d986c2021-02-10 13:26:18 -0600635 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
636
Matt Spinlerbe952d22022-07-01 11:30:11 -0500637 if (pelID.starts_with("0X"))
Matt Spinler27de6f32020-02-21 08:35:57 -0600638 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600639 pelID.erase(0, 2);
Matt Spinler27de6f32020-02-21 08:35:57 -0600640 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600641
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700642 for (auto it = fs::directory_iterator(pelLogDir());
Matt Spinler25d986c2021-02-10 13:26:18 -0600643 it != fs::directory_iterator(); ++it)
Matt Spinler27de6f32020-02-21 08:35:57 -0600644 {
Matt Spinler80129fe2023-01-19 15:09:05 -0600645 if (endsWithPelID((*it).path(), pelID))
Matt Spinler25d986c2021-02-10 13:26:18 -0600646 {
647 fs::remove((*it).path());
648 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600649 }
650}
651
652/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600653 * @brief Delete all PEL files.
Matt Spinler27de6f32020-02-21 08:35:57 -0600654 */
655void deleteAllPELs()
656{
Matt Spinleraaf23ee2023-07-07 16:29:52 -0500657 lg2::info("peltool deleting all event logs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600658
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700659 for (const auto& entry : fs::directory_iterator(pelLogDir()))
Matt Spinler27de6f32020-02-21 08:35:57 -0600660 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500661 if (!fs::is_regular_file(entry.path()))
662 {
663 continue;
664 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600665 fs::remove(entry.path());
Matt Spinler27de6f32020-02-21 08:35:57 -0600666 }
667}
668
Matt Spinler1b420bc2020-02-21 08:54:25 -0600669/**
670 * @brief Display a single PEL
671 *
672 * @param[in] pel - the PEL to display
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800673 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler1b420bc2020-02-21 08:54:25 -0600674 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800675void displayPEL(const PEL& pel, bool hexDump)
Matt Spinler1b420bc2020-02-21 08:54:25 -0600676{
677 if (pel.valid())
678 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800679 if (hexDump)
680 {
Patrick Williams2544b412022-10-04 08:41:06 -0500681 std::string dstr = dumpHex(std::data(pel.data()), pel.size(), 0,
682 false);
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800683 std::cout << dstr << std::endl;
684 }
685 else
686 {
687 auto plugins = getPlugins();
688 pel.toJSON(registry, plugins);
689 }
Matt Spinler1b420bc2020-02-21 08:54:25 -0600690 }
691 else
692 {
693 std::cerr << "PEL was malformed\n";
694 exit(1);
695 }
696}
697
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800698/**
699 * @brief Print number of PELs
700 * @param[in] hidden - Bool to include hidden logs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800701 * @param[in] includeInfo - Bool to include informational logs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000702 * @param[in] critSysTerm - Bool to include CritSysTerm
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800703 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800704 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000705void printPELCount(bool hidden, bool includeInfo, bool critSysTerm,
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800706 const std::optional<std::regex>& scrubRegex)
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800707{
708 std::size_t count = 0;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700709
710 for (auto it = fs::directory_iterator(pelLogDir());
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800711 it != fs::directory_iterator(); ++it)
712 {
713 if (!fs::is_regular_file((*it).path()))
714 {
715 continue;
716 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800717 std::vector<uint8_t> data = getFileData((*it).path());
718 if (data.empty())
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800719 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800720 continue;
721 }
722 PEL pel{data};
723 if (!pel.valid())
724 {
725 continue;
726 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800727 if (!includeInfo && pel.userHeader().severity() == 0)
728 {
729 continue;
730 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000731 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
732 {
733 continue;
734 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800735 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
736 if (!hidden && actionFlags.test(hiddenFlagBit))
737 {
738 continue;
739 }
740 if (pel.primarySRC() && scrubRegex)
741 {
742 std::string val = pel.primarySRC().value()->asciiString();
743 if (std::regex_search(trimEnd(val), scrubRegex.value(),
744 std::regex_constants::match_not_null))
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800745 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800746 continue;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800747 }
748 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800749 count++;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800750 }
751 std::cout << "{\n"
752 << " \"Number of PELs found\": "
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800753 << getNumberString("%d", count) << "\n}\n";
754}
755
756/**
757 * @brief Generate regex pattern object from file contents
758 * @param[in] scrubFile - File containing regex pattern
759 * @return std::regex - SRC regex object
760 */
761std::regex genRegex(std::string& scrubFile)
762{
763 std::string pattern;
764 std::ifstream contents(scrubFile);
765 if (contents.fail())
766 {
767 std::cerr << "Can't open \"" << scrubFile << "\"\n";
768 exit(1);
769 }
770 std::string line;
771 while (std::getline(contents, line))
772 {
773 if (!line.empty())
774 {
775 pattern.append(line + "|");
776 }
777 }
778 try
779 {
780 std::regex scrubRegex(pattern, std::regex::icase);
781 return scrubRegex;
782 }
Patrick Williams66491c62021-10-06 12:23:37 -0500783 catch (const std::regex_error& e)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800784 {
785 if (e.code() == std::regex_constants::error_collate)
786 std::cerr << "Invalid collating element request\n";
787 else if (e.code() == std::regex_constants::error_ctype)
788 std::cerr << "Invalid character class\n";
789 else if (e.code() == std::regex_constants::error_escape)
790 std::cerr << "Invalid escape character or trailing escape\n";
791 else if (e.code() == std::regex_constants::error_backref)
792 std::cerr << "Invalid back reference\n";
793 else if (e.code() == std::regex_constants::error_brack)
794 std::cerr << "Mismatched bracket ([ or ])\n";
795 else if (e.code() == std::regex_constants::error_paren)
796 {
797 // to catch return code error_badrepeat when error_paren is retured
798 // instead
799 size_t pos = pattern.find_first_of("*+?{");
800 while (pos != std::string::npos)
801 {
802 if (pos == 0 || pattern.substr(pos - 1, 1) == "|")
803 {
804 std::cerr
805 << "A repetition character (*, ?, +, or {) was not "
806 "preceded by a valid regular expression\n";
807 exit(1);
808 }
809 pos = pattern.find_first_of("*+?{", pos + 1);
810 }
811 std::cerr << "Mismatched parentheses (( or ))\n";
812 }
813 else if (e.code() == std::regex_constants::error_brace)
814 std::cerr << "Mismatched brace ({ or })\n";
815 else if (e.code() == std::regex_constants::error_badbrace)
816 std::cerr << "Invalid range inside a { }\n";
817 else if (e.code() == std::regex_constants::error_range)
818 std::cerr << "Invalid character range (e.g., [z-a])\n";
819 else if (e.code() == std::regex_constants::error_space)
820 std::cerr << "Insufficient memory to handle regular expression\n";
821 else if (e.code() == std::regex_constants::error_badrepeat)
822 std::cerr << "A repetition character (*, ?, +, or {) was not "
823 "preceded by a valid regular expression\n";
824 else if (e.code() == std::regex_constants::error_complexity)
825 std::cerr << "The requested match is too complex\n";
826 else if (e.code() == std::regex_constants::error_stack)
827 std::cerr << "Insufficient memory to evaluate a match\n";
828 exit(1);
829 }
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800830}
831
Aatir186ce8c2019-10-20 15:13:39 -0500832static void exitWithError(const std::string& help, const char* err)
833{
834 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
835 exit(-1);
836}
837
838int main(int argc, char** argv)
839{
840 CLI::App app{"OpenBMC PEL Tool"};
841 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600842 std::string idPEL;
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800843 std::string bmcId;
Matt Spinler27de6f32020-02-21 08:35:57 -0600844 std::string idToDelete;
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800845 std::string scrubFile;
846 std::optional<std::regex> scrubRegex;
Aatire340c132019-12-09 14:19:29 -0600847 bool listPEL = false;
848 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800849 bool hidden = false;
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800850 bool includeInfo = false;
Miguel Gomez011ccae2021-03-25 23:42:09 +0000851 bool critSysTerm = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600852 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800853 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800854 bool fullPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800855 bool hexDump = false;
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500856 bool archive = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600857
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800858 app.set_help_flag("--help", "Print this help message and exit");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800859 app.add_option("--file", fileName, "Display a PEL using its Raw PEL file");
Aatire340c132019-12-09 14:19:29 -0600860 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800861 app.add_option("--bmc-id", bmcId,
862 "Display a PEL based on its BMC Event ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800863 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600864 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800865 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600866 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800867 app.add_flag("-h", hidden, "Include hidden PELs");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800868 app.add_flag("-f,--info", includeInfo, "Include informational PELs");
Miguel Gomez011ccae2021-03-25 23:42:09 +0000869 app.add_flag("-t, --termination", critSysTerm,
870 "List only critical system terminating PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600871 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
872 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800873 app.add_option("-s, --scrub", scrubFile,
874 "File containing SRC regular expressions to ignore");
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800875 app.add_flag("-x", hexDump, "Display PEL(s) in hexdump instead of JSON");
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500876 app.add_flag("--archive", archive, "List or display archived PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600877
Aatir186ce8c2019-10-20 15:13:39 -0500878 CLI11_PARSE(app, argc, argv);
879
880 if (!fileName.empty())
881 {
882 std::vector<uint8_t> data = getFileData(fileName);
883 if (!data.empty())
884 {
885 PEL pel{data};
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800886 if (hexDump)
887 {
Patrick Williams2544b412022-10-04 08:41:06 -0500888 std::string dstr = dumpHex(std::data(pel.data()), pel.size(), 0,
889 false);
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800890 std::cout << dstr << std::endl;
891 }
892 else
893 {
894 auto plugins = getPlugins();
895 pel.toJSON(registry, plugins);
896 }
Aatir186ce8c2019-10-20 15:13:39 -0500897 }
898 else
899 {
900 exitWithError(app.help("", CLI::AppFormatMode::All),
901 "Raw PEL file can't be read.");
902 }
903 }
Aatire340c132019-12-09 14:19:29 -0600904 else if (!idPEL.empty())
905 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500906 callFunctionOnPEL(idPEL, displayPEL, false, hexDump, archive);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800907 }
908 else if (!bmcId.empty())
909 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500910 callFunctionOnPEL(bmcId, displayPEL, true, hexDump, archive);
Aatire340c132019-12-09 14:19:29 -0600911 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800912 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600913 {
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 printPELs(listPELDescOrd, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500919 scrubRegex, hexDump, archive);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800920 }
921 else if (showPELCount)
922 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800923 if (!scrubFile.empty())
924 {
925 scrubRegex = genRegex(scrubFile);
926 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000927 printPELCount(hidden, includeInfo, critSysTerm, scrubRegex);
Aatir7b291ec2019-11-19 10:37:37 -0600928 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600929 else if (!idToDelete.empty())
930 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600931 deletePEL(idToDelete);
Matt Spinler27de6f32020-02-21 08:35:57 -0600932 }
933 else if (deleteAll)
934 {
935 deleteAllPELs();
936 }
Aatir186ce8c2019-10-20 15:13:39 -0500937 else
938 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800939 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500940 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800941 Py_Finalize();
Aatir186ce8c2019-10-20 15:13:39 -0500942 return 0;
943}