blob: 98572a80457cbc35f04251e6d216b44a6baa906d [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"
Matt Spinler2ea96f62022-02-23 16:31:01 -060024#include "trace.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050025
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +080026#include <Python.h>
Matt Spinler2ea96f62022-02-23 16:31:01 -060027#include <fmt/format.h>
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +080028
Aatir186ce8c2019-10-20 15:13:39 -050029#include <CLI/CLI.hpp>
Aatir7b291ec2019-11-19 10:37:37 -060030#include <bitset>
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +080031#include <fstream>
Aatir186ce8c2019-10-20 15:13:39 -050032#include <iostream>
Aatir7b291ec2019-11-19 10:37:37 -060033#include <regex>
Aatir186ce8c2019-10-20 15:13:39 -050034#include <string>
35
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 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("_"));
78 int i = 0;
Sumit Kumar104c7962022-02-09 06:30:39 -060079 uint64_t bcdTime = 0;
Aatir37822f62019-12-10 14:40:27 -060080 if (token.length() >= 14)
81 {
82 try
83 {
Sumit Kumar104c7962022-02-09 06:30:39 -060084 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
85 bcdTime |= (static_cast<uint64_t>(tmp) << 56);
Aatir37822f62019-12-10 14:40:27 -060086 }
Patrick Williams66491c62021-10-06 12:23:37 -050087 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060088 {
89 std::cout << "Conversion failure: " << err.what() << std::endl;
90 }
91 i += 2;
92 try
93 {
Sumit Kumar104c7962022-02-09 06:30:39 -060094 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
95 bcdTime |= (static_cast<uint64_t>(tmp) << 48);
Aatir37822f62019-12-10 14:40:27 -060096 }
Patrick Williams66491c62021-10-06 12:23:37 -050097 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060098 {
99 std::cout << "Conversion failure: " << err.what() << std::endl;
100 }
101 i += 2;
102 try
103 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600104 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
105 bcdTime |= (static_cast<uint64_t>(tmp) << 40);
Aatir37822f62019-12-10 14:40:27 -0600106 }
Patrick Williams66491c62021-10-06 12:23:37 -0500107 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600108 {
109 std::cout << "Conversion failure: " << err.what() << std::endl;
110 }
111 i += 2;
112 try
113 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600114 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
115 bcdTime |= (static_cast<uint64_t>(tmp) << 32);
Aatir37822f62019-12-10 14:40:27 -0600116 }
Patrick Williams66491c62021-10-06 12:23:37 -0500117 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600118 {
119 std::cout << "Conversion failure: " << err.what() << std::endl;
120 }
121 i += 2;
122 try
123 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600124 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
125 bcdTime |= (tmp << 24);
Aatir37822f62019-12-10 14:40:27 -0600126 }
Patrick Williams66491c62021-10-06 12:23:37 -0500127 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600128 {
129 std::cout << "Conversion failure: " << err.what() << std::endl;
130 }
131 i += 2;
132 try
133 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600134 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
135 bcdTime |= (tmp << 16);
Aatir37822f62019-12-10 14:40:27 -0600136 }
Patrick Williams66491c62021-10-06 12:23:37 -0500137 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600138 {
139 std::cout << "Conversion failure: " << err.what() << std::endl;
140 }
141 i += 2;
142 try
143 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600144 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
145 bcdTime |= (tmp << 8);
Aatir37822f62019-12-10 14:40:27 -0600146 }
Patrick Williams66491c62021-10-06 12:23:37 -0500147 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600148 {
149 std::cout << "Conversion failure: " << err.what() << std::endl;
150 }
151 i += 2;
152 try
153 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600154 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
155 bcdTime |= tmp;
Aatir37822f62019-12-10 14:40:27 -0600156 }
Patrick Williams66491c62021-10-06 12:23:37 -0500157 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600158 {
159 std::cout << "Conversion failure: " << err.what() << std::endl;
160 }
161 }
Sumit Kumar104c7962022-02-09 06:30:39 -0600162 return bcdTime;
Aatir37822f62019-12-10 14:40:27 -0600163}
164
165/**
166 * @brief helper function to get PEL id from file name
167 * @retrun uint32_t - PEL id
168 * @param[in] std::string - file name
169 */
170uint32_t fileNameToPELId(const std::string& fileName)
171{
172 uint32_t num = 0;
173 try
174 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500175 num = std::stoul(fileName.substr(fileName.find("_") + 1), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600176 }
Patrick Williams66491c62021-10-06 12:23:37 -0500177 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600178 {
179 std::cout << "Conversion failure: " << err.what() << std::endl;
180 }
181 return num;
182}
183
184/**
Aatire340c132019-12-09 14:19:29 -0600185 * @brief helper function to check string suffix
186 * @retrun bool - true with suffix matches
187 * @param[in] std::string - string to check for suffix
188 * @param[in] std::string - suffix string
189 */
190bool ends_with(const std::string& str, const std::string& end)
191{
192 size_t slen = str.size(), elen = end.size();
193 if (slen < elen)
194 return false;
195 while (elen)
196 {
197 if (str[--slen] != end[--elen])
198 return false;
199 }
200 return true;
201}
202
Aatir37822f62019-12-10 14:40:27 -0600203/**
204 * @brief get data form raw PEL file.
205 * @param[in] std::string Name of file with raw PEL
206 * @return std::vector<uint8_t> char vector read from raw PEL file.
207 */
Aatirbad5f8a2019-12-10 15:27:16 -0600208std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600209{
210 std::ifstream file(name, std::ifstream::in);
211 if (file.good())
212 {
213 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
214 std::istreambuf_iterator<char>()};
215 return data;
216 }
217 else
218 {
Aatir37822f62019-12-10 14:40:27 -0600219 return {};
220 }
221}
222
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800223/**
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800224 * @brief Initialize Python interpreter and gather all UD parser modules under
225 * the paths found in Python sys.path and the current user directory.
226 * This is to prevent calling a non-existant module which causes Python
227 * to print an import error message and breaking JSON output.
228 *
229 * @return std::vector<std::string> Vector of plugins found in filesystem
230 */
231std::vector<std::string> getPlugins()
232{
233 Py_Initialize();
234 std::vector<std::string> plugins;
235 std::vector<std::string> siteDirs;
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800236 std::array<std::string, 2> parserDirs = {"udparsers", "srcparsers"};
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800237 PyObject* pName = PyUnicode_FromString("sys");
238 PyObject* pModule = PyImport_Import(pName);
239 Py_XDECREF(pName);
240 PyObject* pDict = PyModule_GetDict(pModule);
241 Py_XDECREF(pModule);
242 PyObject* pResult = PyDict_GetItemString(pDict, "path");
243 PyObject* pValue = PyUnicode_FromString(".");
244 PyList_Append(pResult, pValue);
245 Py_XDECREF(pValue);
246 auto list_size = PyList_Size(pResult);
247 for (auto i = 0; i < list_size; i++)
248 {
249 PyObject* item = PyList_GetItem(pResult, i);
250 PyObject* pBytes = PyUnicode_AsEncodedString(item, "utf-8", "~E~");
251 const char* output = PyBytes_AS_STRING(pBytes);
252 Py_XDECREF(pBytes);
253 std::string tmpStr(output);
254 siteDirs.push_back(tmpStr);
255 }
256 for (const auto& dir : siteDirs)
257 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800258 for (const auto& parserDir : parserDirs)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800259 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800260 if (fs::exists(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800261 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800262 for (const auto& entry :
263 fs::directory_iterator(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800264 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800265 if (entry.is_directory() and
266 fs::exists(entry.path().string() + "/" +
267 entry.path().stem().string() + ".py"))
268 {
269 plugins.push_back(entry.path().stem());
270 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800271 }
272 }
273 }
274 }
275 return plugins;
276}
277
278/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800279 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
280 * stdout the full PEL in JSON if fullPEL is true
281 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
282 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800283 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000284 * @param[in] critSysTerm - Boolean to include critical error and system
285 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800286 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
287 * @param[in] foundPEL - Boolean to check if any PEL is present
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800288 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800289 * @param[in] plugins - Vector of strings of plugins found in filesystem
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800290 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800291 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
292 */
Aatir7b291ec2019-11-19 10:37:37 -0600293template <typename T>
Miguel Gomez011ccae2021-03-25 23:42:09 +0000294std::string genPELJSON(T itr, bool hidden, bool includeInfo, bool critSysTerm,
295 bool fullPEL, bool& foundPEL,
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800296 const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500297 const std::vector<std::string>& plugins, bool hexDump,
298 bool archive)
Aatir7b291ec2019-11-19 10:37:37 -0600299{
300 std::size_t found;
301 std::string val;
302 char tmpValStr[50];
303 std::string listStr;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700304 char name[51];
Sumit Kumar104c7962022-02-09 06:30:39 -0600305 sprintf(name, "/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X",
306 static_cast<uint8_t>((itr.second >> 56) & 0xFF),
307 static_cast<uint8_t>((itr.second >> 48) & 0xFF),
308 static_cast<uint8_t>((itr.second >> 40) & 0xFF),
309 static_cast<uint8_t>((itr.second >> 32) & 0xFF),
310 static_cast<uint8_t>((itr.second >> 24) & 0xFF),
311 static_cast<uint8_t>((itr.second >> 16) & 0xFF),
312 static_cast<uint8_t>((itr.second >> 8) & 0xFF),
313 static_cast<uint8_t>(itr.second & 0xFF), itr.first);
314
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500315 auto fileName = (archive ? pelLogDir() + "/archive" : pelLogDir()) + name;
Aatir7b291ec2019-11-19 10:37:37 -0600316 try
317 {
Aatir37822f62019-12-10 14:40:27 -0600318 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800319 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600320 {
Matt Spinler2ea96f62022-02-23 16:31:01 -0600321 trace::error(fmt::format("Empty PEL file {}", fileName));
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800322 return listStr;
323 }
324 PEL pel{data};
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800325 if (!pel.valid())
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800326 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800327 return listStr;
328 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800329 if (!includeInfo && pel.userHeader().severity() == 0)
330 {
331 return listStr;
332 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000333 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
334 {
335 return listStr;
336 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800337 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
338 if (!hidden && actionFlags.test(hiddenFlagBit))
339 {
340 return listStr;
341 }
342 if (pel.primarySRC() && scrubRegex)
343 {
344 val = pel.primarySRC().value()->asciiString();
345 if (std::regex_search(trimEnd(val), scrubRegex.value(),
346 std::regex_constants::match_not_null))
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800347 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800348 return listStr;
349 }
350 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800351 if (hexDump)
352 {
353 std::cout << dumpHex(std::data(pel.data()), pel.size(), 0, false)
354 << std::endl;
355 }
356 else if (fullPEL)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800357 {
358 if (!foundPEL)
359 {
360 std::cout << "[\n";
361 foundPEL = true;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800362 }
363 else
Aatir7b291ec2019-11-19 10:37:37 -0600364 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800365 std::cout << ",\n\n";
366 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800367 pel.toJSON(registry, plugins);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800368 }
369 else
370 {
371 // id
Matt Spinler3025d0b2021-06-02 15:12:52 -0600372 listStr += " \"" +
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800373 getNumberString("0x%X", pel.privateHeader().id()) +
374 "\": {\n";
375 // ASCII
376 if (pel.primarySRC())
377 {
378 val = pel.primarySRC().value()->asciiString();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600379 jsonInsert(listStr, "SRC", trimEnd(val), 2);
380
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800381 // Registry message
382 auto regVal = pel.primarySRC().value()->getErrorDetails(
383 registry, DetailLevel::message, true);
384 if (regVal)
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800385 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800386 val = regVal.value();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600387 jsonInsert(listStr, "Message", val, 2);
Aatir37822f62019-12-10 14:40:27 -0600388 }
Aatir7b291ec2019-11-19 10:37:37 -0600389 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800390 else
391 {
Matt Spinler3025d0b2021-06-02 15:12:52 -0600392 jsonInsert(listStr, "SRC", "No SRC", 2);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800393 }
Matt Spinler3025d0b2021-06-02 15:12:52 -0600394
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800395 // platformid
Matt Spinler3025d0b2021-06-02 15:12:52 -0600396 jsonInsert(listStr, "PLID",
397 getNumberString("0x%X", pel.privateHeader().plid()), 2);
398
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800399 // creatorid
400 std::string creatorID =
401 getNumberString("%c", pel.privateHeader().creatorID());
402 val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
403 : "Unknown Creator ID";
Matt Spinler3025d0b2021-06-02 15:12:52 -0600404 jsonInsert(listStr, "CreatorID", val, 2);
405
406 // subsystem
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800407 std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
408 pel_values::subsystemValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600409 jsonInsert(listStr, "Subsystem", subsystem, 2);
410
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800411 // commit time
412 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
413 pel.privateHeader().commitTimestamp().month,
414 pel.privateHeader().commitTimestamp().day,
415 pel.privateHeader().commitTimestamp().yearMSB,
416 pel.privateHeader().commitTimestamp().yearLSB,
417 pel.privateHeader().commitTimestamp().hour,
418 pel.privateHeader().commitTimestamp().minutes,
419 pel.privateHeader().commitTimestamp().seconds);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600420 jsonInsert(listStr, "Commit Time", tmpValStr, 2);
421
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800422 // severity
423 std::string severity = pv::getValue(pel.userHeader().severity(),
424 pel_values::severityValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600425 jsonInsert(listStr, "Sev", severity, 2);
426
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800427 // compID
Matt Spinler3025d0b2021-06-02 15:12:52 -0600428 jsonInsert(listStr, "CompID",
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800429 getNumberString(
Matt Spinler3025d0b2021-06-02 15:12:52 -0600430 "0x%X", pel.privateHeader().header().componentID),
431 2);
432
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800433 found = listStr.rfind(",");
434 if (found != std::string::npos)
435 {
436 listStr.replace(found, 1, "");
Matt Spinler3025d0b2021-06-02 15:12:52 -0600437 listStr += " },\n";
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800438 }
439 foundPEL = true;
Aatir7b291ec2019-11-19 10:37:37 -0600440 }
441 }
Patrick Williams66491c62021-10-06 12:23:37 -0500442 catch (const std::exception& e)
Aatir7b291ec2019-11-19 10:37:37 -0600443 {
Matt Spinler2ea96f62022-02-23 16:31:01 -0600444 trace::error(fmt::format("Hit exception when reading PEL file {}: {}",
445 fileName, e.what()));
Aatir7b291ec2019-11-19 10:37:37 -0600446 }
447 return listStr;
448}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800449
Aatir7b291ec2019-11-19 10:37:37 -0600450/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800451 * @brief Print a list of PELs or a JSON array of PELs
452 * @param[in] order - Boolean to print in reverse orser
453 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800454 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000455 * @param[in] critSysTerm - Boolean to include critical error and system
456 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800457 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800458 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800459 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Aatir7b291ec2019-11-19 10:37:37 -0600460 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000461void printPELs(bool order, bool hidden, bool includeInfo, bool critSysTerm,
462 bool fullPEL, const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500463 bool hexDump, bool archive = false)
Aatir7b291ec2019-11-19 10:37:37 -0600464{
465 std::string listStr;
Sumit Kumar104c7962022-02-09 06:30:39 -0600466 std::vector<std::pair<uint32_t, uint64_t>> PELs;
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800467 std::vector<std::string> plugins;
Aatir7b291ec2019-11-19 10:37:37 -0600468 listStr = "{\n";
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500469 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
470 : fs::directory_iterator(pelLogDir()));
Aatir7b291ec2019-11-19 10:37:37 -0600471 it != fs::directory_iterator(); ++it)
472 {
473 if (!fs::is_regular_file((*it).path()))
474 {
475 continue;
476 }
Aatir37822f62019-12-10 14:40:27 -0600477 else
Aatir7b291ec2019-11-19 10:37:37 -0600478 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600479 PELs.emplace_back(fileNameToPELId((*it).path().filename()),
480 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600481 }
482 }
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500483
Sumit Kumar104c7962022-02-09 06:30:39 -0600484 // Sort the pairs based on second time parameter
485 std::sort(PELs.begin(), PELs.end(), [](auto& left, auto& right) {
486 return left.second < right.second;
487 });
488
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800489 bool foundPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800490
491 if (fullPEL && !hexDump)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800492 {
493 plugins = getPlugins();
494 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000495 auto buildJSON = [&listStr, &hidden, &includeInfo, &critSysTerm, &fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500496 &foundPEL, &scrubRegex, &plugins, &hexDump,
497 &archive](const auto& i) {
Miguel Gomez011ccae2021-03-25 23:42:09 +0000498 listStr += genPELJSON(i, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500499 foundPEL, scrubRegex, plugins, hexDump, archive);
Aatir37822f62019-12-10 14:40:27 -0600500 };
Aatir7b291ec2019-11-19 10:37:37 -0600501 if (order)
502 {
503 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
504 }
505 else
506 {
507 std::for_each(PELs.begin(), PELs.end(), buildJSON);
508 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800509 if (hexDump)
510 {
511 return;
512 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800513 if (foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600514 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800515 if (fullPEL)
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800516 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800517 std::cout << "]" << std::endl;
518 }
519 else
520 {
521 std::size_t found;
522 found = listStr.rfind(",");
523 if (found != std::string::npos)
524 {
525 listStr.replace(found, 1, "");
526 listStr += "}\n";
527 printf("%s", listStr.c_str());
528 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800529 }
530 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800531 else
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800532 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800533 std::string emptyJSON = fullPEL ? "[]" : "{}";
534 std::cout << emptyJSON << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600535 }
536}
Aatir186ce8c2019-10-20 15:13:39 -0500537
Matt Spinler27de6f32020-02-21 08:35:57 -0600538/**
539 * @brief Calls the function passed in on the PEL with the ID
540 * passed in.
541 *
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800542 * @param[in] id - The string version of the PEL or BMC Log ID, either with or
Matt Spinler27de6f32020-02-21 08:35:57 -0600543 * without the 0x prefix.
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800544 * @param[in] func - The std::function<void(const PEL&, bool hexDump)> function
545 * to run.
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800546 * @param[in] useBMC - if true, search by BMC Log ID, else search by PEL ID
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800547 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler27de6f32020-02-21 08:35:57 -0600548 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800549void callFunctionOnPEL(const std::string& id, const PELFunc& func,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500550 bool useBMC = false, bool hexDump = false,
551 bool archive = false)
Matt Spinler27de6f32020-02-21 08:35:57 -0600552{
553 std::string pelID{id};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800554 if (!useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600555 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800556 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
557
558 if (pelID.find("0X") == 0)
559 {
560 pelID.erase(0, 2);
561 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600562 }
563
564 bool found = false;
565
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500566 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
567 : fs::directory_iterator(pelLogDir()));
Matt Spinler27de6f32020-02-21 08:35:57 -0600568 it != fs::directory_iterator(); ++it)
569 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800570 // The PEL ID is part of the filename, so use that to find the PEL if
571 // "useBMC" is set to false, otherwise we have to search within the PEL
Matt Spinler27de6f32020-02-21 08:35:57 -0600572
573 if (!fs::is_regular_file((*it).path()))
574 {
575 continue;
576 }
577
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800578 if ((ends_with((*it).path(), pelID) && !useBMC) || useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600579 {
Matt Spinler27de6f32020-02-21 08:35:57 -0600580 auto data = getFileData((*it).path());
581 if (!data.empty())
582 {
583 PEL pel{data};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800584 if (!useBMC ||
585 (useBMC && pel.obmcLogID() == std::stoul(id, nullptr, 0)))
Matt Spinler27de6f32020-02-21 08:35:57 -0600586 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800587 found = true;
588 try
589 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800590 func(pel, hexDump);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800591 break;
592 }
Patrick Williams66491c62021-10-06 12:23:37 -0500593 catch (const std::exception& e)
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800594 {
595 std::cerr << " Internal function threw an exception: "
596 << e.what() << "\n";
597 exit(1);
598 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600599 }
600 }
601 else
602 {
603 std::cerr << "Could not read PEL file\n";
604 exit(1);
605 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600606 }
607 }
608
609 if (!found)
610 {
611 std::cerr << "PEL not found\n";
612 exit(1);
613 }
614}
615
616/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600617 * @brief Delete a PEL file.
Matt Spinler27de6f32020-02-21 08:35:57 -0600618 *
Matt Spinler25d986c2021-02-10 13:26:18 -0600619 * @param[in] id - The PEL ID to delete.
Matt Spinler27de6f32020-02-21 08:35:57 -0600620 */
Matt Spinler25d986c2021-02-10 13:26:18 -0600621void deletePEL(const std::string& id)
Matt Spinler27de6f32020-02-21 08:35:57 -0600622{
Matt Spinler25d986c2021-02-10 13:26:18 -0600623 std::string pelID{id};
Matt Spinler27de6f32020-02-21 08:35:57 -0600624
Matt Spinler25d986c2021-02-10 13:26:18 -0600625 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
626
627 if (pelID.find("0X") == 0)
Matt Spinler27de6f32020-02-21 08:35:57 -0600628 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600629 pelID.erase(0, 2);
Matt Spinler27de6f32020-02-21 08:35:57 -0600630 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600631
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700632 for (auto it = fs::directory_iterator(pelLogDir());
Matt Spinler25d986c2021-02-10 13:26:18 -0600633 it != fs::directory_iterator(); ++it)
Matt Spinler27de6f32020-02-21 08:35:57 -0600634 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600635 if (ends_with((*it).path(), pelID))
636 {
637 fs::remove((*it).path());
638 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600639 }
640}
641
642/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600643 * @brief Delete all PEL files.
Matt Spinler27de6f32020-02-21 08:35:57 -0600644 */
645void deleteAllPELs()
646{
Matt Spinler2ea96f62022-02-23 16:31:01 -0600647 trace::info("peltool deleting all event logs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600648
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700649 for (const auto& entry : fs::directory_iterator(pelLogDir()))
Matt Spinler27de6f32020-02-21 08:35:57 -0600650 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500651 if (!fs::is_regular_file(entry.path()))
652 {
653 continue;
654 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600655 fs::remove(entry.path());
Matt Spinler27de6f32020-02-21 08:35:57 -0600656 }
657}
658
Matt Spinler1b420bc2020-02-21 08:54:25 -0600659/**
660 * @brief Display a single PEL
661 *
662 * @param[in] pel - the PEL to display
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800663 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler1b420bc2020-02-21 08:54:25 -0600664 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800665void displayPEL(const PEL& pel, bool hexDump)
Matt Spinler1b420bc2020-02-21 08:54:25 -0600666{
667 if (pel.valid())
668 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800669 if (hexDump)
670 {
671 std::string dstr =
672 dumpHex(std::data(pel.data()), pel.size(), 0, false);
673 std::cout << dstr << std::endl;
674 }
675 else
676 {
677 auto plugins = getPlugins();
678 pel.toJSON(registry, plugins);
679 }
Matt Spinler1b420bc2020-02-21 08:54:25 -0600680 }
681 else
682 {
683 std::cerr << "PEL was malformed\n";
684 exit(1);
685 }
686}
687
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800688/**
689 * @brief Print number of PELs
690 * @param[in] hidden - Bool to include hidden logs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800691 * @param[in] includeInfo - Bool to include informational logs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000692 * @param[in] critSysTerm - Bool to include CritSysTerm
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800693 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800694 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000695void printPELCount(bool hidden, bool includeInfo, bool critSysTerm,
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800696 const std::optional<std::regex>& scrubRegex)
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800697{
698 std::size_t count = 0;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700699
700 for (auto it = fs::directory_iterator(pelLogDir());
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800701 it != fs::directory_iterator(); ++it)
702 {
703 if (!fs::is_regular_file((*it).path()))
704 {
705 continue;
706 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800707 std::vector<uint8_t> data = getFileData((*it).path());
708 if (data.empty())
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800709 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800710 continue;
711 }
712 PEL pel{data};
713 if (!pel.valid())
714 {
715 continue;
716 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800717 if (!includeInfo && pel.userHeader().severity() == 0)
718 {
719 continue;
720 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000721 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
722 {
723 continue;
724 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800725 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
726 if (!hidden && actionFlags.test(hiddenFlagBit))
727 {
728 continue;
729 }
730 if (pel.primarySRC() && scrubRegex)
731 {
732 std::string val = pel.primarySRC().value()->asciiString();
733 if (std::regex_search(trimEnd(val), scrubRegex.value(),
734 std::regex_constants::match_not_null))
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800735 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800736 continue;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800737 }
738 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800739 count++;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800740 }
741 std::cout << "{\n"
742 << " \"Number of PELs found\": "
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800743 << getNumberString("%d", count) << "\n}\n";
744}
745
746/**
747 * @brief Generate regex pattern object from file contents
748 * @param[in] scrubFile - File containing regex pattern
749 * @return std::regex - SRC regex object
750 */
751std::regex genRegex(std::string& scrubFile)
752{
753 std::string pattern;
754 std::ifstream contents(scrubFile);
755 if (contents.fail())
756 {
757 std::cerr << "Can't open \"" << scrubFile << "\"\n";
758 exit(1);
759 }
760 std::string line;
761 while (std::getline(contents, line))
762 {
763 if (!line.empty())
764 {
765 pattern.append(line + "|");
766 }
767 }
768 try
769 {
770 std::regex scrubRegex(pattern, std::regex::icase);
771 return scrubRegex;
772 }
Patrick Williams66491c62021-10-06 12:23:37 -0500773 catch (const std::regex_error& e)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800774 {
775 if (e.code() == std::regex_constants::error_collate)
776 std::cerr << "Invalid collating element request\n";
777 else if (e.code() == std::regex_constants::error_ctype)
778 std::cerr << "Invalid character class\n";
779 else if (e.code() == std::regex_constants::error_escape)
780 std::cerr << "Invalid escape character or trailing escape\n";
781 else if (e.code() == std::regex_constants::error_backref)
782 std::cerr << "Invalid back reference\n";
783 else if (e.code() == std::regex_constants::error_brack)
784 std::cerr << "Mismatched bracket ([ or ])\n";
785 else if (e.code() == std::regex_constants::error_paren)
786 {
787 // to catch return code error_badrepeat when error_paren is retured
788 // instead
789 size_t pos = pattern.find_first_of("*+?{");
790 while (pos != std::string::npos)
791 {
792 if (pos == 0 || pattern.substr(pos - 1, 1) == "|")
793 {
794 std::cerr
795 << "A repetition character (*, ?, +, or {) was not "
796 "preceded by a valid regular expression\n";
797 exit(1);
798 }
799 pos = pattern.find_first_of("*+?{", pos + 1);
800 }
801 std::cerr << "Mismatched parentheses (( or ))\n";
802 }
803 else if (e.code() == std::regex_constants::error_brace)
804 std::cerr << "Mismatched brace ({ or })\n";
805 else if (e.code() == std::regex_constants::error_badbrace)
806 std::cerr << "Invalid range inside a { }\n";
807 else if (e.code() == std::regex_constants::error_range)
808 std::cerr << "Invalid character range (e.g., [z-a])\n";
809 else if (e.code() == std::regex_constants::error_space)
810 std::cerr << "Insufficient memory to handle regular expression\n";
811 else if (e.code() == std::regex_constants::error_badrepeat)
812 std::cerr << "A repetition character (*, ?, +, or {) was not "
813 "preceded by a valid regular expression\n";
814 else if (e.code() == std::regex_constants::error_complexity)
815 std::cerr << "The requested match is too complex\n";
816 else if (e.code() == std::regex_constants::error_stack)
817 std::cerr << "Insufficient memory to evaluate a match\n";
818 exit(1);
819 }
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800820}
821
Aatir186ce8c2019-10-20 15:13:39 -0500822static void exitWithError(const std::string& help, const char* err)
823{
824 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
825 exit(-1);
826}
827
828int main(int argc, char** argv)
829{
830 CLI::App app{"OpenBMC PEL Tool"};
831 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600832 std::string idPEL;
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800833 std::string bmcId;
Matt Spinler27de6f32020-02-21 08:35:57 -0600834 std::string idToDelete;
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800835 std::string scrubFile;
836 std::optional<std::regex> scrubRegex;
Aatire340c132019-12-09 14:19:29 -0600837 bool listPEL = false;
838 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800839 bool hidden = false;
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800840 bool includeInfo = false;
Miguel Gomez011ccae2021-03-25 23:42:09 +0000841 bool critSysTerm = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600842 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800843 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800844 bool fullPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800845 bool hexDump = false;
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500846 bool archive = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600847
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800848 app.set_help_flag("--help", "Print this help message and exit");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800849 app.add_option("--file", fileName, "Display a PEL using its Raw PEL file");
Aatire340c132019-12-09 14:19:29 -0600850 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800851 app.add_option("--bmc-id", bmcId,
852 "Display a PEL based on its BMC Event ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800853 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600854 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800855 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600856 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800857 app.add_flag("-h", hidden, "Include hidden PELs");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800858 app.add_flag("-f,--info", includeInfo, "Include informational PELs");
Miguel Gomez011ccae2021-03-25 23:42:09 +0000859 app.add_flag("-t, --termination", critSysTerm,
860 "List only critical system terminating PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600861 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
862 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800863 app.add_option("-s, --scrub", scrubFile,
864 "File containing SRC regular expressions to ignore");
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800865 app.add_flag("-x", hexDump, "Display PEL(s) in hexdump instead of JSON");
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500866 app.add_flag("--archive", archive, "List or display archived PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600867
Aatir186ce8c2019-10-20 15:13:39 -0500868 CLI11_PARSE(app, argc, argv);
869
870 if (!fileName.empty())
871 {
872 std::vector<uint8_t> data = getFileData(fileName);
873 if (!data.empty())
874 {
875 PEL pel{data};
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800876 if (hexDump)
877 {
878 std::string dstr =
879 dumpHex(std::data(pel.data()), pel.size(), 0, false);
880 std::cout << dstr << std::endl;
881 }
882 else
883 {
884 auto plugins = getPlugins();
885 pel.toJSON(registry, plugins);
886 }
Aatir186ce8c2019-10-20 15:13:39 -0500887 }
888 else
889 {
890 exitWithError(app.help("", CLI::AppFormatMode::All),
891 "Raw PEL file can't be read.");
892 }
893 }
Aatire340c132019-12-09 14:19:29 -0600894 else if (!idPEL.empty())
895 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500896 callFunctionOnPEL(idPEL, displayPEL, false, hexDump, archive);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800897 }
898 else if (!bmcId.empty())
899 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500900 callFunctionOnPEL(bmcId, displayPEL, true, hexDump, archive);
Aatire340c132019-12-09 14:19:29 -0600901 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800902 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600903 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800904 if (!scrubFile.empty())
905 {
906 scrubRegex = genRegex(scrubFile);
907 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000908 printPELs(listPELDescOrd, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500909 scrubRegex, hexDump, archive);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800910 }
911 else if (showPELCount)
912 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800913 if (!scrubFile.empty())
914 {
915 scrubRegex = genRegex(scrubFile);
916 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000917 printPELCount(hidden, includeInfo, critSysTerm, scrubRegex);
Aatir7b291ec2019-11-19 10:37:37 -0600918 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600919 else if (!idToDelete.empty())
920 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600921 deletePEL(idToDelete);
Matt Spinler27de6f32020-02-21 08:35:57 -0600922 }
923 else if (deleteAll)
924 {
925 deleteAllPELs();
926 }
Aatir186ce8c2019-10-20 15:13:39 -0500927 else
928 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800929 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500930 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800931 Py_Finalize();
Aatir186ce8c2019-10-20 15:13:39 -0500932 return 0;
933}