blob: 5a2abf715e61d68ba499dcd85a27efd3660d4d0c [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
18#include "../bcd_time.hpp"
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +080019#include "../json_utils.hpp"
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080020#include "../paths.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050021#include "../pel.hpp"
Aatir7b291ec2019-11-19 10:37:37 -060022#include "../pel_types.hpp"
23#include "../pel_values.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050024
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +080025#include <Python.h>
26
Aatir186ce8c2019-10-20 15:13:39 -050027#include <CLI/CLI.hpp>
Aatir7b291ec2019-11-19 10:37:37 -060028#include <bitset>
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +080029#include <fstream>
Aatir186ce8c2019-10-20 15:13:39 -050030#include <iostream>
Aatir7b291ec2019-11-19 10:37:37 -060031#include <phosphor-logging/log.hpp>
32#include <regex>
Aatir186ce8c2019-10-20 15:13:39 -050033#include <string>
Aatir7b291ec2019-11-19 10:37:37 -060034#include <xyz/openbmc_project/Common/File/error.hpp>
Aatir186ce8c2019-10-20 15:13:39 -050035
William A. Kennington IIIb6b25572021-05-19 17:09:41 -070036#include "config_main.h"
37
Aatir7b291ec2019-11-19 10:37:37 -060038namespace fs = std::filesystem;
Aatir186ce8c2019-10-20 15:13:39 -050039using namespace phosphor::logging;
40using namespace openpower::pels;
Aatir7b291ec2019-11-19 10:37:37 -060041namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
42namespace message = openpower::pels::message;
43namespace pv = openpower::pels::pel_values;
Aatir186ce8c2019-10-20 15:13:39 -050044
Miguel Gomez011ccae2021-03-25 23:42:09 +000045const uint8_t critSysTermSeverity = 0x51;
46
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +080047using PELFunc = std::function<void(const PEL&, bool hexDump)>;
Matt Spinler0d804ef2020-05-12 16:16:26 -050048message::Registry registry(getPELReadOnlyDataPath() / message::registryFileName,
Matt Spinlerd8e29002020-04-09 09:11:22 -050049 false);
Matt Spinler27de6f32020-02-21 08:35:57 -060050namespace service
51{
52constexpr auto logging = "xyz.openbmc_project.Logging";
53} // namespace service
54
55namespace interface
56{
57constexpr auto deleteObj = "xyz.openbmc_project.Object.Delete";
58constexpr auto deleteAll = "xyz.openbmc_project.Collection.DeleteAll";
59} // namespace interface
60
61namespace object_path
62{
63constexpr auto logEntry = "/xyz/openbmc_project/logging/entry/";
64constexpr auto logging = "/xyz/openbmc_project/logging";
65} // namespace object_path
66
William A. Kennington IIIb6b25572021-05-19 17:09:41 -070067std::string pelLogDir()
68{
69 return std::string(EXTENSION_PERSIST_DIR) + "/pels/logs";
70}
71
Aatire340c132019-12-09 14:19:29 -060072/**
Aatir37822f62019-12-10 14:40:27 -060073 * @brief helper function to get PEL commit timestamp from file name
74 * @retrun BCDTime - PEL commit timestamp
75 * @param[in] std::string - file name
76 */
77BCDTime fileNameToTimestamp(const std::string& fileName)
78{
79 std::string token = fileName.substr(0, fileName.find("_"));
80 int i = 0;
81 BCDTime tmp;
82 if (token.length() >= 14)
83 {
84 try
85 {
Sumit Kumara1e40842021-06-23 09:52:25 -050086 tmp.yearMSB = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -060087 }
88 catch (std::exception& err)
89 {
90 std::cout << "Conversion failure: " << err.what() << std::endl;
91 }
92 i += 2;
93 try
94 {
Sumit Kumara1e40842021-06-23 09:52:25 -050095 tmp.yearLSB = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -060096 }
97 catch (std::exception& err)
98 {
99 std::cout << "Conversion failure: " << err.what() << std::endl;
100 }
101 i += 2;
102 try
103 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500104 tmp.month = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600105 }
106 catch (std::exception& err)
107 {
108 std::cout << "Conversion failure: " << err.what() << std::endl;
109 }
110 i += 2;
111 try
112 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500113 tmp.day = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600114 }
115 catch (std::exception& err)
116 {
117 std::cout << "Conversion failure: " << err.what() << std::endl;
118 }
119 i += 2;
120 try
121 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500122 tmp.hour = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600123 }
124 catch (std::exception& err)
125 {
126 std::cout << "Conversion failure: " << err.what() << std::endl;
127 }
128 i += 2;
129 try
130 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500131 tmp.minutes = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600132 }
133 catch (std::exception& err)
134 {
135 std::cout << "Conversion failure: " << err.what() << std::endl;
136 }
137 i += 2;
138 try
139 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500140 tmp.seconds = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600141 }
142 catch (std::exception& err)
143 {
144 std::cout << "Conversion failure: " << err.what() << std::endl;
145 }
146 i += 2;
147 try
148 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500149 tmp.hundredths = std::stoul(token.substr(i, 2), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600150 }
151 catch (std::exception& err)
152 {
153 std::cout << "Conversion failure: " << err.what() << std::endl;
154 }
155 }
156 return tmp;
157}
158
159/**
160 * @brief helper function to get PEL id from file name
161 * @retrun uint32_t - PEL id
162 * @param[in] std::string - file name
163 */
164uint32_t fileNameToPELId(const std::string& fileName)
165{
166 uint32_t num = 0;
167 try
168 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500169 num = std::stoul(fileName.substr(fileName.find("_") + 1), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600170 }
171 catch (std::exception& err)
172 {
173 std::cout << "Conversion failure: " << err.what() << std::endl;
174 }
175 return num;
176}
177
178/**
Aatire340c132019-12-09 14:19:29 -0600179 * @brief helper function to check string suffix
180 * @retrun bool - true with suffix matches
181 * @param[in] std::string - string to check for suffix
182 * @param[in] std::string - suffix string
183 */
184bool ends_with(const std::string& str, const std::string& end)
185{
186 size_t slen = str.size(), elen = end.size();
187 if (slen < elen)
188 return false;
189 while (elen)
190 {
191 if (str[--slen] != end[--elen])
192 return false;
193 }
194 return true;
195}
196
Aatir37822f62019-12-10 14:40:27 -0600197/**
198 * @brief get data form raw PEL file.
199 * @param[in] std::string Name of file with raw PEL
200 * @return std::vector<uint8_t> char vector read from raw PEL file.
201 */
Aatirbad5f8a2019-12-10 15:27:16 -0600202std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600203{
204 std::ifstream file(name, std::ifstream::in);
205 if (file.good())
206 {
207 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
208 std::istreambuf_iterator<char>()};
209 return data;
210 }
211 else
212 {
Aatir37822f62019-12-10 14:40:27 -0600213 return {};
214 }
215}
216
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800217/**
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800218 * @brief Initialize Python interpreter and gather all UD parser modules under
219 * the paths found in Python sys.path and the current user directory.
220 * This is to prevent calling a non-existant module which causes Python
221 * to print an import error message and breaking JSON output.
222 *
223 * @return std::vector<std::string> Vector of plugins found in filesystem
224 */
225std::vector<std::string> getPlugins()
226{
227 Py_Initialize();
228 std::vector<std::string> plugins;
229 std::vector<std::string> siteDirs;
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800230 std::array<std::string, 2> parserDirs = {"udparsers", "srcparsers"};
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800231 PyObject* pName = PyUnicode_FromString("sys");
232 PyObject* pModule = PyImport_Import(pName);
233 Py_XDECREF(pName);
234 PyObject* pDict = PyModule_GetDict(pModule);
235 Py_XDECREF(pModule);
236 PyObject* pResult = PyDict_GetItemString(pDict, "path");
237 PyObject* pValue = PyUnicode_FromString(".");
238 PyList_Append(pResult, pValue);
239 Py_XDECREF(pValue);
240 auto list_size = PyList_Size(pResult);
241 for (auto i = 0; i < list_size; i++)
242 {
243 PyObject* item = PyList_GetItem(pResult, i);
244 PyObject* pBytes = PyUnicode_AsEncodedString(item, "utf-8", "~E~");
245 const char* output = PyBytes_AS_STRING(pBytes);
246 Py_XDECREF(pBytes);
247 std::string tmpStr(output);
248 siteDirs.push_back(tmpStr);
249 }
250 for (const auto& dir : siteDirs)
251 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800252 for (const auto& parserDir : parserDirs)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800253 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800254 if (fs::exists(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800255 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800256 for (const auto& entry :
257 fs::directory_iterator(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800258 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800259 if (entry.is_directory() and
260 fs::exists(entry.path().string() + "/" +
261 entry.path().stem().string() + ".py"))
262 {
263 plugins.push_back(entry.path().stem());
264 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800265 }
266 }
267 }
268 }
269 return plugins;
270}
271
272/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800273 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
274 * stdout the full PEL in JSON if fullPEL is true
275 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
276 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800277 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000278 * @param[in] critSysTerm - Boolean to include critical error and system
279 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800280 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
281 * @param[in] foundPEL - Boolean to check if any PEL is present
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800282 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800283 * @param[in] plugins - Vector of strings of plugins found in filesystem
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800284 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800285 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
286 */
Aatir7b291ec2019-11-19 10:37:37 -0600287template <typename T>
Miguel Gomez011ccae2021-03-25 23:42:09 +0000288std::string genPELJSON(T itr, bool hidden, bool includeInfo, bool critSysTerm,
289 bool fullPEL, bool& foundPEL,
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800290 const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500291 const std::vector<std::string>& plugins, bool hexDump,
292 bool archive)
Aatir7b291ec2019-11-19 10:37:37 -0600293{
294 std::size_t found;
295 std::string val;
296 char tmpValStr[50];
297 std::string listStr;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700298 char name[51];
299 sprintf(name, "/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", itr.second.yearMSB,
Aatir7b291ec2019-11-19 10:37:37 -0600300 itr.second.yearLSB, itr.second.month, itr.second.day,
301 itr.second.hour, itr.second.minutes, itr.second.seconds,
302 itr.second.hundredths, itr.first);
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500303 auto fileName = (archive ? pelLogDir() + "/archive" : pelLogDir()) + name;
Aatir7b291ec2019-11-19 10:37:37 -0600304 try
305 {
Aatir37822f62019-12-10 14:40:27 -0600306 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800307 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600308 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800309 log<level::ERR>("Empty PEL file",
310 entry("FILENAME=%s", fileName.c_str()));
311 return listStr;
312 }
313 PEL pel{data};
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800314 if (!pel.valid())
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800315 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800316 return listStr;
317 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800318 if (!includeInfo && pel.userHeader().severity() == 0)
319 {
320 return listStr;
321 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000322 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
323 {
324 return listStr;
325 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800326 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
327 if (!hidden && actionFlags.test(hiddenFlagBit))
328 {
329 return listStr;
330 }
331 if (pel.primarySRC() && scrubRegex)
332 {
333 val = pel.primarySRC().value()->asciiString();
334 if (std::regex_search(trimEnd(val), scrubRegex.value(),
335 std::regex_constants::match_not_null))
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800336 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800337 return listStr;
338 }
339 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800340 if (hexDump)
341 {
342 std::cout << dumpHex(std::data(pel.data()), pel.size(), 0, false)
343 << std::endl;
344 }
345 else if (fullPEL)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800346 {
347 if (!foundPEL)
348 {
349 std::cout << "[\n";
350 foundPEL = true;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800351 }
352 else
Aatir7b291ec2019-11-19 10:37:37 -0600353 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800354 std::cout << ",\n\n";
355 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800356 pel.toJSON(registry, plugins);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800357 }
358 else
359 {
360 // id
Matt Spinler3025d0b2021-06-02 15:12:52 -0600361 listStr += " \"" +
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800362 getNumberString("0x%X", pel.privateHeader().id()) +
363 "\": {\n";
364 // ASCII
365 if (pel.primarySRC())
366 {
367 val = pel.primarySRC().value()->asciiString();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600368 jsonInsert(listStr, "SRC", trimEnd(val), 2);
369
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800370 // Registry message
371 auto regVal = pel.primarySRC().value()->getErrorDetails(
372 registry, DetailLevel::message, true);
373 if (regVal)
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800374 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800375 val = regVal.value();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600376 jsonInsert(listStr, "Message", val, 2);
Aatir37822f62019-12-10 14:40:27 -0600377 }
Aatir7b291ec2019-11-19 10:37:37 -0600378 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800379 else
380 {
Matt Spinler3025d0b2021-06-02 15:12:52 -0600381 jsonInsert(listStr, "SRC", "No SRC", 2);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800382 }
Matt Spinler3025d0b2021-06-02 15:12:52 -0600383
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800384 // platformid
Matt Spinler3025d0b2021-06-02 15:12:52 -0600385 jsonInsert(listStr, "PLID",
386 getNumberString("0x%X", pel.privateHeader().plid()), 2);
387
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800388 // creatorid
389 std::string creatorID =
390 getNumberString("%c", pel.privateHeader().creatorID());
391 val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
392 : "Unknown Creator ID";
Matt Spinler3025d0b2021-06-02 15:12:52 -0600393 jsonInsert(listStr, "CreatorID", val, 2);
394
395 // subsystem
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800396 std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
397 pel_values::subsystemValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600398 jsonInsert(listStr, "Subsystem", subsystem, 2);
399
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800400 // commit time
401 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
402 pel.privateHeader().commitTimestamp().month,
403 pel.privateHeader().commitTimestamp().day,
404 pel.privateHeader().commitTimestamp().yearMSB,
405 pel.privateHeader().commitTimestamp().yearLSB,
406 pel.privateHeader().commitTimestamp().hour,
407 pel.privateHeader().commitTimestamp().minutes,
408 pel.privateHeader().commitTimestamp().seconds);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600409 jsonInsert(listStr, "Commit Time", tmpValStr, 2);
410
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800411 // severity
412 std::string severity = pv::getValue(pel.userHeader().severity(),
413 pel_values::severityValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600414 jsonInsert(listStr, "Sev", severity, 2);
415
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800416 // compID
Matt Spinler3025d0b2021-06-02 15:12:52 -0600417 jsonInsert(listStr, "CompID",
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800418 getNumberString(
Matt Spinler3025d0b2021-06-02 15:12:52 -0600419 "0x%X", pel.privateHeader().header().componentID),
420 2);
421
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800422 found = listStr.rfind(",");
423 if (found != std::string::npos)
424 {
425 listStr.replace(found, 1, "");
Matt Spinler3025d0b2021-06-02 15:12:52 -0600426 listStr += " },\n";
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800427 }
428 foundPEL = true;
Aatir7b291ec2019-11-19 10:37:37 -0600429 }
430 }
431 catch (std::exception& e)
432 {
433 log<level::ERR>("Hit exception while reading PEL File",
434 entry("FILENAME=%s", fileName.c_str()),
435 entry("ERROR=%s", e.what()));
436 }
437 return listStr;
438}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800439
Aatir7b291ec2019-11-19 10:37:37 -0600440/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800441 * @brief Print a list of PELs or a JSON array of PELs
442 * @param[in] order - Boolean to print in reverse orser
443 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800444 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000445 * @param[in] critSysTerm - Boolean to include critical error and system
446 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800447 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800448 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800449 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Aatir7b291ec2019-11-19 10:37:37 -0600450 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000451void printPELs(bool order, bool hidden, bool includeInfo, bool critSysTerm,
452 bool fullPEL, const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500453 bool hexDump, bool archive = false)
Aatir7b291ec2019-11-19 10:37:37 -0600454{
455 std::string listStr;
456 std::map<uint32_t, BCDTime> PELs;
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800457 std::vector<std::string> plugins;
Aatir7b291ec2019-11-19 10:37:37 -0600458 listStr = "{\n";
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500459 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
460 : fs::directory_iterator(pelLogDir()));
Aatir7b291ec2019-11-19 10:37:37 -0600461 it != fs::directory_iterator(); ++it)
462 {
463 if (!fs::is_regular_file((*it).path()))
464 {
465 continue;
466 }
Aatir37822f62019-12-10 14:40:27 -0600467 else
Aatir7b291ec2019-11-19 10:37:37 -0600468 {
Aatir37822f62019-12-10 14:40:27 -0600469 PELs.emplace(fileNameToPELId((*it).path().filename()),
470 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600471 }
472 }
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500473
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800474 bool foundPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800475
476 if (fullPEL && !hexDump)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800477 {
478 plugins = getPlugins();
479 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000480 auto buildJSON = [&listStr, &hidden, &includeInfo, &critSysTerm, &fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500481 &foundPEL, &scrubRegex, &plugins, &hexDump,
482 &archive](const auto& i) {
Miguel Gomez011ccae2021-03-25 23:42:09 +0000483 listStr += genPELJSON(i, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500484 foundPEL, scrubRegex, plugins, hexDump, archive);
Aatir37822f62019-12-10 14:40:27 -0600485 };
Aatir7b291ec2019-11-19 10:37:37 -0600486 if (order)
487 {
488 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
489 }
490 else
491 {
492 std::for_each(PELs.begin(), PELs.end(), buildJSON);
493 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800494 if (hexDump)
495 {
496 return;
497 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800498 if (foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600499 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800500 if (fullPEL)
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800501 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800502 std::cout << "]" << std::endl;
503 }
504 else
505 {
506 std::size_t found;
507 found = listStr.rfind(",");
508 if (found != std::string::npos)
509 {
510 listStr.replace(found, 1, "");
511 listStr += "}\n";
512 printf("%s", listStr.c_str());
513 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800514 }
515 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800516 else
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800517 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800518 std::string emptyJSON = fullPEL ? "[]" : "{}";
519 std::cout << emptyJSON << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600520 }
521}
Aatir186ce8c2019-10-20 15:13:39 -0500522
Matt Spinler27de6f32020-02-21 08:35:57 -0600523/**
524 * @brief Calls the function passed in on the PEL with the ID
525 * passed in.
526 *
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800527 * @param[in] id - The string version of the PEL or BMC Log ID, either with or
Matt Spinler27de6f32020-02-21 08:35:57 -0600528 * without the 0x prefix.
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800529 * @param[in] func - The std::function<void(const PEL&, bool hexDump)> function
530 * to run.
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800531 * @param[in] useBMC - if true, search by BMC Log ID, else search by PEL ID
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800532 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler27de6f32020-02-21 08:35:57 -0600533 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800534void callFunctionOnPEL(const std::string& id, const PELFunc& func,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500535 bool useBMC = false, bool hexDump = false,
536 bool archive = false)
Matt Spinler27de6f32020-02-21 08:35:57 -0600537{
538 std::string pelID{id};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800539 if (!useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600540 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800541 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
542
543 if (pelID.find("0X") == 0)
544 {
545 pelID.erase(0, 2);
546 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600547 }
548
549 bool found = false;
550
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500551 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
552 : fs::directory_iterator(pelLogDir()));
Matt Spinler27de6f32020-02-21 08:35:57 -0600553 it != fs::directory_iterator(); ++it)
554 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800555 // The PEL ID is part of the filename, so use that to find the PEL if
556 // "useBMC" is set to false, otherwise we have to search within the PEL
Matt Spinler27de6f32020-02-21 08:35:57 -0600557
558 if (!fs::is_regular_file((*it).path()))
559 {
560 continue;
561 }
562
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800563 if ((ends_with((*it).path(), pelID) && !useBMC) || useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600564 {
Matt Spinler27de6f32020-02-21 08:35:57 -0600565 auto data = getFileData((*it).path());
566 if (!data.empty())
567 {
568 PEL pel{data};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800569 if (!useBMC ||
570 (useBMC && pel.obmcLogID() == std::stoul(id, nullptr, 0)))
Matt Spinler27de6f32020-02-21 08:35:57 -0600571 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800572 found = true;
573 try
574 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800575 func(pel, hexDump);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800576 break;
577 }
578 catch (std::exception& e)
579 {
580 std::cerr << " Internal function threw an exception: "
581 << e.what() << "\n";
582 exit(1);
583 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600584 }
585 }
586 else
587 {
588 std::cerr << "Could not read PEL file\n";
589 exit(1);
590 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600591 }
592 }
593
594 if (!found)
595 {
596 std::cerr << "PEL not found\n";
597 exit(1);
598 }
599}
600
601/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600602 * @brief Delete a PEL file.
Matt Spinler27de6f32020-02-21 08:35:57 -0600603 *
Matt Spinler25d986c2021-02-10 13:26:18 -0600604 * @param[in] id - The PEL ID to delete.
Matt Spinler27de6f32020-02-21 08:35:57 -0600605 */
Matt Spinler25d986c2021-02-10 13:26:18 -0600606void deletePEL(const std::string& id)
Matt Spinler27de6f32020-02-21 08:35:57 -0600607{
Matt Spinler25d986c2021-02-10 13:26:18 -0600608 std::string pelID{id};
Matt Spinler27de6f32020-02-21 08:35:57 -0600609
Matt Spinler25d986c2021-02-10 13:26:18 -0600610 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
611
612 if (pelID.find("0X") == 0)
Matt Spinler27de6f32020-02-21 08:35:57 -0600613 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600614 pelID.erase(0, 2);
Matt Spinler27de6f32020-02-21 08:35:57 -0600615 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600616
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700617 for (auto it = fs::directory_iterator(pelLogDir());
Matt Spinler25d986c2021-02-10 13:26:18 -0600618 it != fs::directory_iterator(); ++it)
Matt Spinler27de6f32020-02-21 08:35:57 -0600619 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600620 if (ends_with((*it).path(), pelID))
621 {
622 fs::remove((*it).path());
623 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600624 }
625}
626
627/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600628 * @brief Delete all PEL files.
Matt Spinler27de6f32020-02-21 08:35:57 -0600629 */
630void deleteAllPELs()
631{
Matt Spinler25d986c2021-02-10 13:26:18 -0600632 log<level::INFO>("peltool deleting all event logs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600633
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700634 for (const auto& entry : fs::directory_iterator(pelLogDir()))
Matt Spinler27de6f32020-02-21 08:35:57 -0600635 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500636 if (!fs::is_regular_file(entry.path()))
637 {
638 continue;
639 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600640 fs::remove(entry.path());
Matt Spinler27de6f32020-02-21 08:35:57 -0600641 }
642}
643
Matt Spinler1b420bc2020-02-21 08:54:25 -0600644/**
645 * @brief Display a single PEL
646 *
647 * @param[in] pel - the PEL to display
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800648 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler1b420bc2020-02-21 08:54:25 -0600649 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800650void displayPEL(const PEL& pel, bool hexDump)
Matt Spinler1b420bc2020-02-21 08:54:25 -0600651{
652 if (pel.valid())
653 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800654 if (hexDump)
655 {
656 std::string dstr =
657 dumpHex(std::data(pel.data()), pel.size(), 0, false);
658 std::cout << dstr << std::endl;
659 }
660 else
661 {
662 auto plugins = getPlugins();
663 pel.toJSON(registry, plugins);
664 }
Matt Spinler1b420bc2020-02-21 08:54:25 -0600665 }
666 else
667 {
668 std::cerr << "PEL was malformed\n";
669 exit(1);
670 }
671}
672
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800673/**
674 * @brief Print number of PELs
675 * @param[in] hidden - Bool to include hidden logs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800676 * @param[in] includeInfo - Bool to include informational logs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000677 * @param[in] critSysTerm - Bool to include CritSysTerm
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800678 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800679 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000680void printPELCount(bool hidden, bool includeInfo, bool critSysTerm,
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800681 const std::optional<std::regex>& scrubRegex)
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800682{
683 std::size_t count = 0;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700684
685 for (auto it = fs::directory_iterator(pelLogDir());
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800686 it != fs::directory_iterator(); ++it)
687 {
688 if (!fs::is_regular_file((*it).path()))
689 {
690 continue;
691 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800692 std::vector<uint8_t> data = getFileData((*it).path());
693 if (data.empty())
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800694 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800695 continue;
696 }
697 PEL pel{data};
698 if (!pel.valid())
699 {
700 continue;
701 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800702 if (!includeInfo && pel.userHeader().severity() == 0)
703 {
704 continue;
705 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000706 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
707 {
708 continue;
709 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800710 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
711 if (!hidden && actionFlags.test(hiddenFlagBit))
712 {
713 continue;
714 }
715 if (pel.primarySRC() && scrubRegex)
716 {
717 std::string val = pel.primarySRC().value()->asciiString();
718 if (std::regex_search(trimEnd(val), scrubRegex.value(),
719 std::regex_constants::match_not_null))
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800720 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800721 continue;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800722 }
723 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800724 count++;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800725 }
726 std::cout << "{\n"
727 << " \"Number of PELs found\": "
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800728 << getNumberString("%d", count) << "\n}\n";
729}
730
731/**
732 * @brief Generate regex pattern object from file contents
733 * @param[in] scrubFile - File containing regex pattern
734 * @return std::regex - SRC regex object
735 */
736std::regex genRegex(std::string& scrubFile)
737{
738 std::string pattern;
739 std::ifstream contents(scrubFile);
740 if (contents.fail())
741 {
742 std::cerr << "Can't open \"" << scrubFile << "\"\n";
743 exit(1);
744 }
745 std::string line;
746 while (std::getline(contents, line))
747 {
748 if (!line.empty())
749 {
750 pattern.append(line + "|");
751 }
752 }
753 try
754 {
755 std::regex scrubRegex(pattern, std::regex::icase);
756 return scrubRegex;
757 }
758 catch (std::regex_error& e)
759 {
760 if (e.code() == std::regex_constants::error_collate)
761 std::cerr << "Invalid collating element request\n";
762 else if (e.code() == std::regex_constants::error_ctype)
763 std::cerr << "Invalid character class\n";
764 else if (e.code() == std::regex_constants::error_escape)
765 std::cerr << "Invalid escape character or trailing escape\n";
766 else if (e.code() == std::regex_constants::error_backref)
767 std::cerr << "Invalid back reference\n";
768 else if (e.code() == std::regex_constants::error_brack)
769 std::cerr << "Mismatched bracket ([ or ])\n";
770 else if (e.code() == std::regex_constants::error_paren)
771 {
772 // to catch return code error_badrepeat when error_paren is retured
773 // instead
774 size_t pos = pattern.find_first_of("*+?{");
775 while (pos != std::string::npos)
776 {
777 if (pos == 0 || pattern.substr(pos - 1, 1) == "|")
778 {
779 std::cerr
780 << "A repetition character (*, ?, +, or {) was not "
781 "preceded by a valid regular expression\n";
782 exit(1);
783 }
784 pos = pattern.find_first_of("*+?{", pos + 1);
785 }
786 std::cerr << "Mismatched parentheses (( or ))\n";
787 }
788 else if (e.code() == std::regex_constants::error_brace)
789 std::cerr << "Mismatched brace ({ or })\n";
790 else if (e.code() == std::regex_constants::error_badbrace)
791 std::cerr << "Invalid range inside a { }\n";
792 else if (e.code() == std::regex_constants::error_range)
793 std::cerr << "Invalid character range (e.g., [z-a])\n";
794 else if (e.code() == std::regex_constants::error_space)
795 std::cerr << "Insufficient memory to handle regular expression\n";
796 else if (e.code() == std::regex_constants::error_badrepeat)
797 std::cerr << "A repetition character (*, ?, +, or {) was not "
798 "preceded by a valid regular expression\n";
799 else if (e.code() == std::regex_constants::error_complexity)
800 std::cerr << "The requested match is too complex\n";
801 else if (e.code() == std::regex_constants::error_stack)
802 std::cerr << "Insufficient memory to evaluate a match\n";
803 exit(1);
804 }
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800805}
806
Aatir186ce8c2019-10-20 15:13:39 -0500807static void exitWithError(const std::string& help, const char* err)
808{
809 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
810 exit(-1);
811}
812
813int main(int argc, char** argv)
814{
815 CLI::App app{"OpenBMC PEL Tool"};
816 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600817 std::string idPEL;
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800818 std::string bmcId;
Matt Spinler27de6f32020-02-21 08:35:57 -0600819 std::string idToDelete;
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800820 std::string scrubFile;
821 std::optional<std::regex> scrubRegex;
Aatire340c132019-12-09 14:19:29 -0600822 bool listPEL = false;
823 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800824 bool hidden = false;
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800825 bool includeInfo = false;
Miguel Gomez011ccae2021-03-25 23:42:09 +0000826 bool critSysTerm = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600827 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800828 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800829 bool fullPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800830 bool hexDump = false;
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500831 bool archive = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600832
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800833 app.set_help_flag("--help", "Print this help message and exit");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800834 app.add_option("--file", fileName, "Display a PEL using its Raw PEL file");
Aatire340c132019-12-09 14:19:29 -0600835 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800836 app.add_option("--bmc-id", bmcId,
837 "Display a PEL based on its BMC Event ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800838 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600839 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800840 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600841 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800842 app.add_flag("-h", hidden, "Include hidden PELs");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800843 app.add_flag("-f,--info", includeInfo, "Include informational PELs");
Miguel Gomez011ccae2021-03-25 23:42:09 +0000844 app.add_flag("-t, --termination", critSysTerm,
845 "List only critical system terminating PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600846 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
847 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800848 app.add_option("-s, --scrub", scrubFile,
849 "File containing SRC regular expressions to ignore");
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800850 app.add_flag("-x", hexDump, "Display PEL(s) in hexdump instead of JSON");
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500851 app.add_flag("--archive", archive, "List or display archived PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600852
Aatir186ce8c2019-10-20 15:13:39 -0500853 CLI11_PARSE(app, argc, argv);
854
855 if (!fileName.empty())
856 {
857 std::vector<uint8_t> data = getFileData(fileName);
858 if (!data.empty())
859 {
860 PEL pel{data};
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800861 if (hexDump)
862 {
863 std::string dstr =
864 dumpHex(std::data(pel.data()), pel.size(), 0, false);
865 std::cout << dstr << std::endl;
866 }
867 else
868 {
869 auto plugins = getPlugins();
870 pel.toJSON(registry, plugins);
871 }
Aatir186ce8c2019-10-20 15:13:39 -0500872 }
873 else
874 {
875 exitWithError(app.help("", CLI::AppFormatMode::All),
876 "Raw PEL file can't be read.");
877 }
878 }
Aatire340c132019-12-09 14:19:29 -0600879 else if (!idPEL.empty())
880 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500881 callFunctionOnPEL(idPEL, displayPEL, false, hexDump, archive);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800882 }
883 else if (!bmcId.empty())
884 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500885 callFunctionOnPEL(bmcId, displayPEL, true, hexDump, archive);
Aatire340c132019-12-09 14:19:29 -0600886 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800887 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600888 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800889 if (!scrubFile.empty())
890 {
891 scrubRegex = genRegex(scrubFile);
892 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000893 printPELs(listPELDescOrd, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500894 scrubRegex, hexDump, archive);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800895 }
896 else if (showPELCount)
897 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800898 if (!scrubFile.empty())
899 {
900 scrubRegex = genRegex(scrubFile);
901 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000902 printPELCount(hidden, includeInfo, critSysTerm, scrubRegex);
Aatir7b291ec2019-11-19 10:37:37 -0600903 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600904 else if (!idToDelete.empty())
905 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600906 deletePEL(idToDelete);
Matt Spinler27de6f32020-02-21 08:35:57 -0600907 }
908 else if (deleteAll)
909 {
910 deleteAllPELs();
911 }
Aatir186ce8c2019-10-20 15:13:39 -0500912 else
913 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800914 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500915 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800916 Py_Finalize();
Aatir186ce8c2019-10-20 15:13:39 -0500917 return 0;
918}