blob: 3acfd8a98d0b8ab34c2a93ae216a9b1aa56184e3 [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
Sumit Kumar104c7962022-02-09 06:30:39 -060074 * @retrun uint64_t - PEL commit timestamp
Aatir37822f62019-12-10 14:40:27 -060075 * @param[in] std::string - file name
76 */
Sumit Kumar104c7962022-02-09 06:30:39 -060077uint64_t fileNameToTimestamp(const std::string& fileName)
Aatir37822f62019-12-10 14:40:27 -060078{
79 std::string token = fileName.substr(0, fileName.find("_"));
80 int i = 0;
Sumit Kumar104c7962022-02-09 06:30:39 -060081 uint64_t bcdTime = 0;
Aatir37822f62019-12-10 14:40:27 -060082 if (token.length() >= 14)
83 {
84 try
85 {
Sumit Kumar104c7962022-02-09 06:30:39 -060086 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
87 bcdTime |= (static_cast<uint64_t>(tmp) << 56);
Aatir37822f62019-12-10 14:40:27 -060088 }
Patrick Williams66491c62021-10-06 12:23:37 -050089 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -060090 {
91 std::cout << "Conversion failure: " << err.what() << std::endl;
92 }
93 i += 2;
94 try
95 {
Sumit Kumar104c7962022-02-09 06:30:39 -060096 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
97 bcdTime |= (static_cast<uint64_t>(tmp) << 48);
Aatir37822f62019-12-10 14:40:27 -060098 }
Patrick Williams66491c62021-10-06 12:23:37 -050099 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600100 {
101 std::cout << "Conversion failure: " << err.what() << std::endl;
102 }
103 i += 2;
104 try
105 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600106 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
107 bcdTime |= (static_cast<uint64_t>(tmp) << 40);
Aatir37822f62019-12-10 14:40:27 -0600108 }
Patrick Williams66491c62021-10-06 12:23:37 -0500109 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600110 {
111 std::cout << "Conversion failure: " << err.what() << std::endl;
112 }
113 i += 2;
114 try
115 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600116 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
117 bcdTime |= (static_cast<uint64_t>(tmp) << 32);
Aatir37822f62019-12-10 14:40:27 -0600118 }
Patrick Williams66491c62021-10-06 12:23:37 -0500119 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600120 {
121 std::cout << "Conversion failure: " << err.what() << std::endl;
122 }
123 i += 2;
124 try
125 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600126 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
127 bcdTime |= (tmp << 24);
Aatir37822f62019-12-10 14:40:27 -0600128 }
Patrick Williams66491c62021-10-06 12:23:37 -0500129 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600130 {
131 std::cout << "Conversion failure: " << err.what() << std::endl;
132 }
133 i += 2;
134 try
135 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600136 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
137 bcdTime |= (tmp << 16);
Aatir37822f62019-12-10 14:40:27 -0600138 }
Patrick Williams66491c62021-10-06 12:23:37 -0500139 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600140 {
141 std::cout << "Conversion failure: " << err.what() << std::endl;
142 }
143 i += 2;
144 try
145 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600146 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
147 bcdTime |= (tmp << 8);
Aatir37822f62019-12-10 14:40:27 -0600148 }
Patrick Williams66491c62021-10-06 12:23:37 -0500149 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600150 {
151 std::cout << "Conversion failure: " << err.what() << std::endl;
152 }
153 i += 2;
154 try
155 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600156 auto tmp = std::stoul(token.substr(i, 2), 0, 16);
157 bcdTime |= tmp;
Aatir37822f62019-12-10 14:40:27 -0600158 }
Patrick Williams66491c62021-10-06 12:23:37 -0500159 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600160 {
161 std::cout << "Conversion failure: " << err.what() << std::endl;
162 }
163 }
Sumit Kumar104c7962022-02-09 06:30:39 -0600164 return bcdTime;
Aatir37822f62019-12-10 14:40:27 -0600165}
166
167/**
168 * @brief helper function to get PEL id from file name
169 * @retrun uint32_t - PEL id
170 * @param[in] std::string - file name
171 */
172uint32_t fileNameToPELId(const std::string& fileName)
173{
174 uint32_t num = 0;
175 try
176 {
Sumit Kumara1e40842021-06-23 09:52:25 -0500177 num = std::stoul(fileName.substr(fileName.find("_") + 1), 0, 16);
Aatir37822f62019-12-10 14:40:27 -0600178 }
Patrick Williams66491c62021-10-06 12:23:37 -0500179 catch (const std::exception& err)
Aatir37822f62019-12-10 14:40:27 -0600180 {
181 std::cout << "Conversion failure: " << err.what() << std::endl;
182 }
183 return num;
184}
185
186/**
Aatire340c132019-12-09 14:19:29 -0600187 * @brief helper function to check string suffix
188 * @retrun bool - true with suffix matches
189 * @param[in] std::string - string to check for suffix
190 * @param[in] std::string - suffix string
191 */
192bool ends_with(const std::string& str, const std::string& end)
193{
194 size_t slen = str.size(), elen = end.size();
195 if (slen < elen)
196 return false;
197 while (elen)
198 {
199 if (str[--slen] != end[--elen])
200 return false;
201 }
202 return true;
203}
204
Aatir37822f62019-12-10 14:40:27 -0600205/**
206 * @brief get data form raw PEL file.
207 * @param[in] std::string Name of file with raw PEL
208 * @return std::vector<uint8_t> char vector read from raw PEL file.
209 */
Aatirbad5f8a2019-12-10 15:27:16 -0600210std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600211{
212 std::ifstream file(name, std::ifstream::in);
213 if (file.good())
214 {
215 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
216 std::istreambuf_iterator<char>()};
217 return data;
218 }
219 else
220 {
Aatir37822f62019-12-10 14:40:27 -0600221 return {};
222 }
223}
224
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800225/**
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800226 * @brief Initialize Python interpreter and gather all UD parser modules under
227 * the paths found in Python sys.path and the current user directory.
228 * This is to prevent calling a non-existant module which causes Python
229 * to print an import error message and breaking JSON output.
230 *
231 * @return std::vector<std::string> Vector of plugins found in filesystem
232 */
233std::vector<std::string> getPlugins()
234{
235 Py_Initialize();
236 std::vector<std::string> plugins;
237 std::vector<std::string> siteDirs;
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800238 std::array<std::string, 2> parserDirs = {"udparsers", "srcparsers"};
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800239 PyObject* pName = PyUnicode_FromString("sys");
240 PyObject* pModule = PyImport_Import(pName);
241 Py_XDECREF(pName);
242 PyObject* pDict = PyModule_GetDict(pModule);
243 Py_XDECREF(pModule);
244 PyObject* pResult = PyDict_GetItemString(pDict, "path");
245 PyObject* pValue = PyUnicode_FromString(".");
246 PyList_Append(pResult, pValue);
247 Py_XDECREF(pValue);
248 auto list_size = PyList_Size(pResult);
249 for (auto i = 0; i < list_size; i++)
250 {
251 PyObject* item = PyList_GetItem(pResult, i);
252 PyObject* pBytes = PyUnicode_AsEncodedString(item, "utf-8", "~E~");
253 const char* output = PyBytes_AS_STRING(pBytes);
254 Py_XDECREF(pBytes);
255 std::string tmpStr(output);
256 siteDirs.push_back(tmpStr);
257 }
258 for (const auto& dir : siteDirs)
259 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800260 for (const auto& parserDir : parserDirs)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800261 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800262 if (fs::exists(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800263 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800264 for (const auto& entry :
265 fs::directory_iterator(dir + "/" + parserDir))
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800266 {
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800267 if (entry.is_directory() and
268 fs::exists(entry.path().string() + "/" +
269 entry.path().stem().string() + ".py"))
270 {
271 plugins.push_back(entry.path().stem());
272 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800273 }
274 }
275 }
276 }
277 return plugins;
278}
279
280/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800281 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
282 * stdout the full PEL in JSON if fullPEL is true
283 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
284 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800285 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000286 * @param[in] critSysTerm - Boolean to include critical error and system
287 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800288 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
289 * @param[in] foundPEL - Boolean to check if any PEL is present
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800290 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800291 * @param[in] plugins - Vector of strings of plugins found in filesystem
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800292 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800293 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
294 */
Aatir7b291ec2019-11-19 10:37:37 -0600295template <typename T>
Miguel Gomez011ccae2021-03-25 23:42:09 +0000296std::string genPELJSON(T itr, bool hidden, bool includeInfo, bool critSysTerm,
297 bool fullPEL, bool& foundPEL,
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800298 const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500299 const std::vector<std::string>& plugins, bool hexDump,
300 bool archive)
Aatir7b291ec2019-11-19 10:37:37 -0600301{
302 std::size_t found;
303 std::string val;
304 char tmpValStr[50];
305 std::string listStr;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700306 char name[51];
Sumit Kumar104c7962022-02-09 06:30:39 -0600307 sprintf(name, "/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X",
308 static_cast<uint8_t>((itr.second >> 56) & 0xFF),
309 static_cast<uint8_t>((itr.second >> 48) & 0xFF),
310 static_cast<uint8_t>((itr.second >> 40) & 0xFF),
311 static_cast<uint8_t>((itr.second >> 32) & 0xFF),
312 static_cast<uint8_t>((itr.second >> 24) & 0xFF),
313 static_cast<uint8_t>((itr.second >> 16) & 0xFF),
314 static_cast<uint8_t>((itr.second >> 8) & 0xFF),
315 static_cast<uint8_t>(itr.second & 0xFF), itr.first);
316
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500317 auto fileName = (archive ? pelLogDir() + "/archive" : pelLogDir()) + name;
Aatir7b291ec2019-11-19 10:37:37 -0600318 try
319 {
Aatir37822f62019-12-10 14:40:27 -0600320 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800321 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600322 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800323 log<level::ERR>("Empty PEL file",
324 entry("FILENAME=%s", fileName.c_str()));
325 return listStr;
326 }
327 PEL pel{data};
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800328 if (!pel.valid())
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800329 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800330 return listStr;
331 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800332 if (!includeInfo && pel.userHeader().severity() == 0)
333 {
334 return listStr;
335 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000336 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
337 {
338 return listStr;
339 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800340 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
341 if (!hidden && actionFlags.test(hiddenFlagBit))
342 {
343 return listStr;
344 }
345 if (pel.primarySRC() && scrubRegex)
346 {
347 val = pel.primarySRC().value()->asciiString();
348 if (std::regex_search(trimEnd(val), scrubRegex.value(),
349 std::regex_constants::match_not_null))
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800350 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800351 return listStr;
352 }
353 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800354 if (hexDump)
355 {
356 std::cout << dumpHex(std::data(pel.data()), pel.size(), 0, false)
357 << std::endl;
358 }
359 else if (fullPEL)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800360 {
361 if (!foundPEL)
362 {
363 std::cout << "[\n";
364 foundPEL = true;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800365 }
366 else
Aatir7b291ec2019-11-19 10:37:37 -0600367 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800368 std::cout << ",\n\n";
369 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800370 pel.toJSON(registry, plugins);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800371 }
372 else
373 {
374 // id
Matt Spinler3025d0b2021-06-02 15:12:52 -0600375 listStr += " \"" +
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800376 getNumberString("0x%X", pel.privateHeader().id()) +
377 "\": {\n";
378 // ASCII
379 if (pel.primarySRC())
380 {
381 val = pel.primarySRC().value()->asciiString();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600382 jsonInsert(listStr, "SRC", trimEnd(val), 2);
383
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800384 // Registry message
385 auto regVal = pel.primarySRC().value()->getErrorDetails(
386 registry, DetailLevel::message, true);
387 if (regVal)
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800388 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800389 val = regVal.value();
Matt Spinler3025d0b2021-06-02 15:12:52 -0600390 jsonInsert(listStr, "Message", val, 2);
Aatir37822f62019-12-10 14:40:27 -0600391 }
Aatir7b291ec2019-11-19 10:37:37 -0600392 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800393 else
394 {
Matt Spinler3025d0b2021-06-02 15:12:52 -0600395 jsonInsert(listStr, "SRC", "No SRC", 2);
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800396 }
Matt Spinler3025d0b2021-06-02 15:12:52 -0600397
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800398 // platformid
Matt Spinler3025d0b2021-06-02 15:12:52 -0600399 jsonInsert(listStr, "PLID",
400 getNumberString("0x%X", pel.privateHeader().plid()), 2);
401
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800402 // creatorid
403 std::string creatorID =
404 getNumberString("%c", pel.privateHeader().creatorID());
405 val = pv::creatorIDs.count(creatorID) ? pv::creatorIDs.at(creatorID)
406 : "Unknown Creator ID";
Matt Spinler3025d0b2021-06-02 15:12:52 -0600407 jsonInsert(listStr, "CreatorID", val, 2);
408
409 // subsystem
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800410 std::string subsystem = pv::getValue(pel.userHeader().subsystem(),
411 pel_values::subsystemValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600412 jsonInsert(listStr, "Subsystem", subsystem, 2);
413
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800414 // commit time
415 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
416 pel.privateHeader().commitTimestamp().month,
417 pel.privateHeader().commitTimestamp().day,
418 pel.privateHeader().commitTimestamp().yearMSB,
419 pel.privateHeader().commitTimestamp().yearLSB,
420 pel.privateHeader().commitTimestamp().hour,
421 pel.privateHeader().commitTimestamp().minutes,
422 pel.privateHeader().commitTimestamp().seconds);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600423 jsonInsert(listStr, "Commit Time", tmpValStr, 2);
424
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800425 // severity
426 std::string severity = pv::getValue(pel.userHeader().severity(),
427 pel_values::severityValues);
Matt Spinler3025d0b2021-06-02 15:12:52 -0600428 jsonInsert(listStr, "Sev", severity, 2);
429
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800430 // compID
Matt Spinler3025d0b2021-06-02 15:12:52 -0600431 jsonInsert(listStr, "CompID",
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800432 getNumberString(
Matt Spinler3025d0b2021-06-02 15:12:52 -0600433 "0x%X", pel.privateHeader().header().componentID),
434 2);
435
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800436 found = listStr.rfind(",");
437 if (found != std::string::npos)
438 {
439 listStr.replace(found, 1, "");
Matt Spinler3025d0b2021-06-02 15:12:52 -0600440 listStr += " },\n";
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800441 }
442 foundPEL = true;
Aatir7b291ec2019-11-19 10:37:37 -0600443 }
444 }
Patrick Williams66491c62021-10-06 12:23:37 -0500445 catch (const std::exception& e)
Aatir7b291ec2019-11-19 10:37:37 -0600446 {
447 log<level::ERR>("Hit exception while reading PEL File",
448 entry("FILENAME=%s", fileName.c_str()),
449 entry("ERROR=%s", e.what()));
450 }
451 return listStr;
452}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800453
Aatir7b291ec2019-11-19 10:37:37 -0600454/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800455 * @brief Print a list of PELs or a JSON array of PELs
456 * @param[in] order - Boolean to print in reverse orser
457 * @param[in] hidden - Boolean to include hidden PELs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800458 * @param[in] includeInfo - Boolean to include informational PELs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000459 * @param[in] critSysTerm - Boolean to include critical error and system
460 * termination PELs
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800461 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800462 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800463 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Aatir7b291ec2019-11-19 10:37:37 -0600464 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000465void printPELs(bool order, bool hidden, bool includeInfo, bool critSysTerm,
466 bool fullPEL, const std::optional<std::regex>& scrubRegex,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500467 bool hexDump, bool archive = false)
Aatir7b291ec2019-11-19 10:37:37 -0600468{
469 std::string listStr;
Sumit Kumar104c7962022-02-09 06:30:39 -0600470 std::vector<std::pair<uint32_t, uint64_t>> PELs;
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800471 std::vector<std::string> plugins;
Aatir7b291ec2019-11-19 10:37:37 -0600472 listStr = "{\n";
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500473 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
474 : fs::directory_iterator(pelLogDir()));
Aatir7b291ec2019-11-19 10:37:37 -0600475 it != fs::directory_iterator(); ++it)
476 {
477 if (!fs::is_regular_file((*it).path()))
478 {
479 continue;
480 }
Aatir37822f62019-12-10 14:40:27 -0600481 else
Aatir7b291ec2019-11-19 10:37:37 -0600482 {
Sumit Kumar104c7962022-02-09 06:30:39 -0600483 PELs.emplace_back(fileNameToPELId((*it).path().filename()),
484 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600485 }
486 }
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500487
Sumit Kumar104c7962022-02-09 06:30:39 -0600488 // Sort the pairs based on second time parameter
489 std::sort(PELs.begin(), PELs.end(), [](auto& left, auto& right) {
490 return left.second < right.second;
491 });
492
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800493 bool foundPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800494
495 if (fullPEL && !hexDump)
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800496 {
497 plugins = getPlugins();
498 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000499 auto buildJSON = [&listStr, &hidden, &includeInfo, &critSysTerm, &fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500500 &foundPEL, &scrubRegex, &plugins, &hexDump,
501 &archive](const auto& i) {
Miguel Gomez011ccae2021-03-25 23:42:09 +0000502 listStr += genPELJSON(i, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500503 foundPEL, scrubRegex, plugins, hexDump, archive);
Aatir37822f62019-12-10 14:40:27 -0600504 };
Aatir7b291ec2019-11-19 10:37:37 -0600505 if (order)
506 {
507 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
508 }
509 else
510 {
511 std::for_each(PELs.begin(), PELs.end(), buildJSON);
512 }
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800513 if (hexDump)
514 {
515 return;
516 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800517 if (foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600518 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800519 if (fullPEL)
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800520 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800521 std::cout << "]" << std::endl;
522 }
523 else
524 {
525 std::size_t found;
526 found = listStr.rfind(",");
527 if (found != std::string::npos)
528 {
529 listStr.replace(found, 1, "");
530 listStr += "}\n";
531 printf("%s", listStr.c_str());
532 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800533 }
534 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800535 else
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800536 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800537 std::string emptyJSON = fullPEL ? "[]" : "{}";
538 std::cout << emptyJSON << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600539 }
540}
Aatir186ce8c2019-10-20 15:13:39 -0500541
Matt Spinler27de6f32020-02-21 08:35:57 -0600542/**
543 * @brief Calls the function passed in on the PEL with the ID
544 * passed in.
545 *
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800546 * @param[in] id - The string version of the PEL or BMC Log ID, either with or
Matt Spinler27de6f32020-02-21 08:35:57 -0600547 * without the 0x prefix.
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800548 * @param[in] func - The std::function<void(const PEL&, bool hexDump)> function
549 * to run.
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800550 * @param[in] useBMC - if true, search by BMC Log ID, else search by PEL ID
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800551 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler27de6f32020-02-21 08:35:57 -0600552 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800553void callFunctionOnPEL(const std::string& id, const PELFunc& func,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500554 bool useBMC = false, bool hexDump = false,
555 bool archive = false)
Matt Spinler27de6f32020-02-21 08:35:57 -0600556{
557 std::string pelID{id};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800558 if (!useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600559 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800560 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
561
562 if (pelID.find("0X") == 0)
563 {
564 pelID.erase(0, 2);
565 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600566 }
567
568 bool found = false;
569
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500570 for (auto it = (archive ? fs::directory_iterator(pelLogDir() + "/archive")
571 : fs::directory_iterator(pelLogDir()));
Matt Spinler27de6f32020-02-21 08:35:57 -0600572 it != fs::directory_iterator(); ++it)
573 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800574 // The PEL ID is part of the filename, so use that to find the PEL if
575 // "useBMC" is set to false, otherwise we have to search within the PEL
Matt Spinler27de6f32020-02-21 08:35:57 -0600576
577 if (!fs::is_regular_file((*it).path()))
578 {
579 continue;
580 }
581
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800582 if ((ends_with((*it).path(), pelID) && !useBMC) || useBMC)
Matt Spinler27de6f32020-02-21 08:35:57 -0600583 {
Matt Spinler27de6f32020-02-21 08:35:57 -0600584 auto data = getFileData((*it).path());
585 if (!data.empty())
586 {
587 PEL pel{data};
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800588 if (!useBMC ||
589 (useBMC && pel.obmcLogID() == std::stoul(id, nullptr, 0)))
Matt Spinler27de6f32020-02-21 08:35:57 -0600590 {
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800591 found = true;
592 try
593 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800594 func(pel, hexDump);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800595 break;
596 }
Patrick Williams66491c62021-10-06 12:23:37 -0500597 catch (const std::exception& e)
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800598 {
599 std::cerr << " Internal function threw an exception: "
600 << e.what() << "\n";
601 exit(1);
602 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600603 }
604 }
605 else
606 {
607 std::cerr << "Could not read PEL file\n";
608 exit(1);
609 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600610 }
611 }
612
613 if (!found)
614 {
615 std::cerr << "PEL not found\n";
616 exit(1);
617 }
618}
619
620/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600621 * @brief Delete a PEL file.
Matt Spinler27de6f32020-02-21 08:35:57 -0600622 *
Matt Spinler25d986c2021-02-10 13:26:18 -0600623 * @param[in] id - The PEL ID to delete.
Matt Spinler27de6f32020-02-21 08:35:57 -0600624 */
Matt Spinler25d986c2021-02-10 13:26:18 -0600625void deletePEL(const std::string& id)
Matt Spinler27de6f32020-02-21 08:35:57 -0600626{
Matt Spinler25d986c2021-02-10 13:26:18 -0600627 std::string pelID{id};
Matt Spinler27de6f32020-02-21 08:35:57 -0600628
Matt Spinler25d986c2021-02-10 13:26:18 -0600629 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
630
631 if (pelID.find("0X") == 0)
Matt Spinler27de6f32020-02-21 08:35:57 -0600632 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600633 pelID.erase(0, 2);
Matt Spinler27de6f32020-02-21 08:35:57 -0600634 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600635
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700636 for (auto it = fs::directory_iterator(pelLogDir());
Matt Spinler25d986c2021-02-10 13:26:18 -0600637 it != fs::directory_iterator(); ++it)
Matt Spinler27de6f32020-02-21 08:35:57 -0600638 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600639 if (ends_with((*it).path(), pelID))
640 {
641 fs::remove((*it).path());
642 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600643 }
644}
645
646/**
Matt Spinler25d986c2021-02-10 13:26:18 -0600647 * @brief Delete all PEL files.
Matt Spinler27de6f32020-02-21 08:35:57 -0600648 */
649void deleteAllPELs()
650{
Matt Spinler25d986c2021-02-10 13:26:18 -0600651 log<level::INFO>("peltool deleting all event logs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600652
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700653 for (const auto& entry : fs::directory_iterator(pelLogDir()))
Matt Spinler27de6f32020-02-21 08:35:57 -0600654 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500655 if (!fs::is_regular_file(entry.path()))
656 {
657 continue;
658 }
Matt Spinler25d986c2021-02-10 13:26:18 -0600659 fs::remove(entry.path());
Matt Spinler27de6f32020-02-21 08:35:57 -0600660 }
661}
662
Matt Spinler1b420bc2020-02-21 08:54:25 -0600663/**
664 * @brief Display a single PEL
665 *
666 * @param[in] pel - the PEL to display
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800667 * @param[in] hexDump - Boolean to print hexdump of PEL instead of JSON
Matt Spinler1b420bc2020-02-21 08:54:25 -0600668 */
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800669void displayPEL(const PEL& pel, bool hexDump)
Matt Spinler1b420bc2020-02-21 08:54:25 -0600670{
671 if (pel.valid())
672 {
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800673 if (hexDump)
674 {
675 std::string dstr =
676 dumpHex(std::data(pel.data()), pel.size(), 0, false);
677 std::cout << dstr << std::endl;
678 }
679 else
680 {
681 auto plugins = getPlugins();
682 pel.toJSON(registry, plugins);
683 }
Matt Spinler1b420bc2020-02-21 08:54:25 -0600684 }
685 else
686 {
687 std::cerr << "PEL was malformed\n";
688 exit(1);
689 }
690}
691
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800692/**
693 * @brief Print number of PELs
694 * @param[in] hidden - Bool to include hidden logs
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800695 * @param[in] includeInfo - Bool to include informational logs
Miguel Gomez011ccae2021-03-25 23:42:09 +0000696 * @param[in] critSysTerm - Bool to include CritSysTerm
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800697 * @param[in] scrubRegex - SRC regex object
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800698 */
Miguel Gomez011ccae2021-03-25 23:42:09 +0000699void printPELCount(bool hidden, bool includeInfo, bool critSysTerm,
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800700 const std::optional<std::regex>& scrubRegex)
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800701{
702 std::size_t count = 0;
William A. Kennington IIIb6b25572021-05-19 17:09:41 -0700703
704 for (auto it = fs::directory_iterator(pelLogDir());
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800705 it != fs::directory_iterator(); ++it)
706 {
707 if (!fs::is_regular_file((*it).path()))
708 {
709 continue;
710 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800711 std::vector<uint8_t> data = getFileData((*it).path());
712 if (data.empty())
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800713 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800714 continue;
715 }
716 PEL pel{data};
717 if (!pel.valid())
718 {
719 continue;
720 }
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800721 if (!includeInfo && pel.userHeader().severity() == 0)
722 {
723 continue;
724 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000725 if (critSysTerm && pel.userHeader().severity() != critSysTermSeverity)
726 {
727 continue;
728 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800729 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
730 if (!hidden && actionFlags.test(hiddenFlagBit))
731 {
732 continue;
733 }
734 if (pel.primarySRC() && scrubRegex)
735 {
736 std::string val = pel.primarySRC().value()->asciiString();
737 if (std::regex_search(trimEnd(val), scrubRegex.value(),
738 std::regex_constants::match_not_null))
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800739 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800740 continue;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800741 }
742 }
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800743 count++;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800744 }
745 std::cout << "{\n"
746 << " \"Number of PELs found\": "
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800747 << getNumberString("%d", count) << "\n}\n";
748}
749
750/**
751 * @brief Generate regex pattern object from file contents
752 * @param[in] scrubFile - File containing regex pattern
753 * @return std::regex - SRC regex object
754 */
755std::regex genRegex(std::string& scrubFile)
756{
757 std::string pattern;
758 std::ifstream contents(scrubFile);
759 if (contents.fail())
760 {
761 std::cerr << "Can't open \"" << scrubFile << "\"\n";
762 exit(1);
763 }
764 std::string line;
765 while (std::getline(contents, line))
766 {
767 if (!line.empty())
768 {
769 pattern.append(line + "|");
770 }
771 }
772 try
773 {
774 std::regex scrubRegex(pattern, std::regex::icase);
775 return scrubRegex;
776 }
Patrick Williams66491c62021-10-06 12:23:37 -0500777 catch (const std::regex_error& e)
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800778 {
779 if (e.code() == std::regex_constants::error_collate)
780 std::cerr << "Invalid collating element request\n";
781 else if (e.code() == std::regex_constants::error_ctype)
782 std::cerr << "Invalid character class\n";
783 else if (e.code() == std::regex_constants::error_escape)
784 std::cerr << "Invalid escape character or trailing escape\n";
785 else if (e.code() == std::regex_constants::error_backref)
786 std::cerr << "Invalid back reference\n";
787 else if (e.code() == std::regex_constants::error_brack)
788 std::cerr << "Mismatched bracket ([ or ])\n";
789 else if (e.code() == std::regex_constants::error_paren)
790 {
791 // to catch return code error_badrepeat when error_paren is retured
792 // instead
793 size_t pos = pattern.find_first_of("*+?{");
794 while (pos != std::string::npos)
795 {
796 if (pos == 0 || pattern.substr(pos - 1, 1) == "|")
797 {
798 std::cerr
799 << "A repetition character (*, ?, +, or {) was not "
800 "preceded by a valid regular expression\n";
801 exit(1);
802 }
803 pos = pattern.find_first_of("*+?{", pos + 1);
804 }
805 std::cerr << "Mismatched parentheses (( or ))\n";
806 }
807 else if (e.code() == std::regex_constants::error_brace)
808 std::cerr << "Mismatched brace ({ or })\n";
809 else if (e.code() == std::regex_constants::error_badbrace)
810 std::cerr << "Invalid range inside a { }\n";
811 else if (e.code() == std::regex_constants::error_range)
812 std::cerr << "Invalid character range (e.g., [z-a])\n";
813 else if (e.code() == std::regex_constants::error_space)
814 std::cerr << "Insufficient memory to handle regular expression\n";
815 else if (e.code() == std::regex_constants::error_badrepeat)
816 std::cerr << "A repetition character (*, ?, +, or {) was not "
817 "preceded by a valid regular expression\n";
818 else if (e.code() == std::regex_constants::error_complexity)
819 std::cerr << "The requested match is too complex\n";
820 else if (e.code() == std::regex_constants::error_stack)
821 std::cerr << "Insufficient memory to evaluate a match\n";
822 exit(1);
823 }
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800824}
825
Aatir186ce8c2019-10-20 15:13:39 -0500826static void exitWithError(const std::string& help, const char* err)
827{
828 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
829 exit(-1);
830}
831
832int main(int argc, char** argv)
833{
834 CLI::App app{"OpenBMC PEL Tool"};
835 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600836 std::string idPEL;
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800837 std::string bmcId;
Matt Spinler27de6f32020-02-21 08:35:57 -0600838 std::string idToDelete;
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800839 std::string scrubFile;
840 std::optional<std::regex> scrubRegex;
Aatire340c132019-12-09 14:19:29 -0600841 bool listPEL = false;
842 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800843 bool hidden = false;
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800844 bool includeInfo = false;
Miguel Gomez011ccae2021-03-25 23:42:09 +0000845 bool critSysTerm = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600846 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800847 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800848 bool fullPEL = false;
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800849 bool hexDump = false;
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500850 bool archive = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600851
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800852 app.set_help_flag("--help", "Print this help message and exit");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800853 app.add_option("--file", fileName, "Display a PEL using its Raw PEL file");
Aatire340c132019-12-09 14:19:29 -0600854 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800855 app.add_option("--bmc-id", bmcId,
856 "Display a PEL based on its BMC Event ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800857 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600858 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800859 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600860 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800861 app.add_flag("-h", hidden, "Include hidden PELs");
Harisuddin Mohamed Isa0c57a672020-03-27 14:16:28 +0800862 app.add_flag("-f,--info", includeInfo, "Include informational PELs");
Miguel Gomez011ccae2021-03-25 23:42:09 +0000863 app.add_flag("-t, --termination", critSysTerm,
864 "List only critical system terminating PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600865 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
866 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800867 app.add_option("-s, --scrub", scrubFile,
868 "File containing SRC regular expressions to ignore");
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800869 app.add_flag("-x", hexDump, "Display PEL(s) in hexdump instead of JSON");
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500870 app.add_flag("--archive", archive, "List or display archived PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600871
Aatir186ce8c2019-10-20 15:13:39 -0500872 CLI11_PARSE(app, argc, argv);
873
874 if (!fileName.empty())
875 {
876 std::vector<uint8_t> data = getFileData(fileName);
877 if (!data.empty())
878 {
879 PEL pel{data};
Harisuddin Mohamed Isaed32c8d2020-10-01 18:12:39 +0800880 if (hexDump)
881 {
882 std::string dstr =
883 dumpHex(std::data(pel.data()), pel.size(), 0, false);
884 std::cout << dstr << std::endl;
885 }
886 else
887 {
888 auto plugins = getPlugins();
889 pel.toJSON(registry, plugins);
890 }
Aatir186ce8c2019-10-20 15:13:39 -0500891 }
892 else
893 {
894 exitWithError(app.help("", CLI::AppFormatMode::All),
895 "Raw PEL file can't be read.");
896 }
897 }
Aatire340c132019-12-09 14:19:29 -0600898 else if (!idPEL.empty())
899 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500900 callFunctionOnPEL(idPEL, displayPEL, false, hexDump, archive);
Harisuddin Mohamed Isa58d3a982020-09-17 19:48:05 +0800901 }
902 else if (!bmcId.empty())
903 {
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500904 callFunctionOnPEL(bmcId, displayPEL, true, hexDump, archive);
Aatire340c132019-12-09 14:19:29 -0600905 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800906 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600907 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800908 if (!scrubFile.empty())
909 {
910 scrubRegex = genRegex(scrubFile);
911 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000912 printPELs(listPELDescOrd, hidden, includeInfo, critSysTerm, fullPEL,
Sumit Kumar1d8835b2021-06-07 09:35:30 -0500913 scrubRegex, hexDump, archive);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800914 }
915 else if (showPELCount)
916 {
Harisuddin Mohamed Isa6f005192020-03-10 17:39:53 +0800917 if (!scrubFile.empty())
918 {
919 scrubRegex = genRegex(scrubFile);
920 }
Miguel Gomez011ccae2021-03-25 23:42:09 +0000921 printPELCount(hidden, includeInfo, critSysTerm, scrubRegex);
Aatir7b291ec2019-11-19 10:37:37 -0600922 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600923 else if (!idToDelete.empty())
924 {
Matt Spinler25d986c2021-02-10 13:26:18 -0600925 deletePEL(idToDelete);
Matt Spinler27de6f32020-02-21 08:35:57 -0600926 }
927 else if (deleteAll)
928 {
929 deleteAllPELs();
930 }
Aatir186ce8c2019-10-20 15:13:39 -0500931 else
932 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800933 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500934 }
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800935 Py_Finalize();
Aatir186ce8c2019-10-20 15:13:39 -0500936 return 0;
937}