blob: ebc9649155eb96fe73441219be79c3cfcf7554d0 [file] [log] [blame]
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301#include "config.h"
2
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05003#include "common_utility.hpp"
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05304#include "defines.hpp"
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05005#include "editor_impl.hpp"
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05006#include "ibm_vpd_utils.hpp"
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05007#include "ipz_parser.hpp"
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05308#include "keyword_vpd_parser.hpp"
Alpana Kumaria00936f2020-04-14 07:15:46 -05009#include "memory_vpd_parser.hpp"
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050010#include "parser_factory.hpp"
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050011#include "vpd_exceptions.hpp"
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053012
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050013#include <assert.h>
Alpana Kumari8ea3f6d2020-04-02 00:26:07 -050014#include <ctype.h>
15
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053016#include <CLI/CLI.hpp>
alpana077ce68722021-07-25 13:23:59 -050017#include <boost/algorithm/string.hpp>
Patrick Williamsc78d8872023-05-10 07:50:56 -050018#include <gpiod.hpp>
19#include <phosphor-logging/log.hpp>
20
21#include <algorithm>
Alpana Kumari65b83602020-09-01 00:24:56 -050022#include <cstdarg>
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053023#include <exception>
PriyangaRamasamy83a1d5d2020-04-30 19:15:43 +053024#include <filesystem>
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053025#include <fstream>
26#include <iostream>
27#include <iterator>
alpana077ce68722021-07-25 13:23:59 -050028#include <regex>
Santosh Puranik253fbe92022-10-06 22:38:09 +053029#include <thread>
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053030
31using namespace std;
32using namespace openpower::vpd;
33using namespace CLI;
34using namespace vpd::keyword::parser;
PriyangaRamasamy83a1d5d2020-04-30 19:15:43 +053035using namespace openpower::vpd::constants;
36namespace fs = filesystem;
37using json = nlohmann::json;
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050038using namespace openpower::vpd::parser::factory;
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050039using namespace openpower::vpd::inventory;
Alpana Kumaria00936f2020-04-14 07:15:46 -050040using namespace openpower::vpd::memory::parser;
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050041using namespace openpower::vpd::parser::interface;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050042using namespace openpower::vpd::exceptions;
Andrew Geissler280197e2020-12-08 20:51:49 -060043using namespace phosphor::logging;
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -050044using namespace openpower::vpd::manager::editor;
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053045
Santosh Puranik88edeb62020-03-02 12:00:09 +053046/**
Sunny Srivastava37992a62023-07-11 05:18:41 -050047 * @brief API declaration, Populate Dbus.
48 *
49 * This method invokes all the populateInterface functions
50 * and notifies PIM about dbus object.
51 *
52 * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
53 * input.
54 * @param[in] js - Inventory json object
55 * @param[in] filePath - Path of the vpd file
56 * @param[in] preIntrStr - Interface string
57 */
58template <typename T>
59static void populateDbus(T& vpdMap, nlohmann::json& js, const string& filePath);
60
61/**
Santosh Puranike9c57532022-03-15 16:51:51 +053062 * @brief Returns the BMC state
63 */
64static auto getBMCState()
65{
66 std::string bmcState;
67 try
68 {
69 auto bus = sdbusplus::bus::new_default();
70 auto properties = bus.new_method_call(
71 "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
72 "org.freedesktop.DBus.Properties", "Get");
73 properties.append("xyz.openbmc_project.State.BMC");
74 properties.append("CurrentBMCState");
75 auto result = bus.call(properties);
76 std::variant<std::string> val;
77 result.read(val);
78 if (auto pVal = std::get_if<std::string>(&val))
79 {
80 bmcState = *pVal;
81 }
82 }
83 catch (const sdbusplus::exception::SdBusError& e)
84 {
85 // Ignore any error
86 std::cerr << "Failed to get BMC state: " << e.what() << "\n";
Jinu Joy Thomas0b33b342024-02-27 21:44:24 -060087 // Since we failed set to not ready state
88 bmcState = "xyz.openbmc_project.State.BMC.BMCState.NotReady";
Santosh Puranike9c57532022-03-15 16:51:51 +053089 }
90 return bmcState;
91}
92
93/**
94 * @brief Check if the FRU is in the cache
95 *
96 * Checks if the FRU associated with the supplied D-Bus object path is already
97 * on D-Bus. This can be used to test if a VPD collection is required for this
98 * FRU. It uses the "xyz.openbmc_project.Inventory.Item, Present" property to
99 * determine the presence of a FRU in the cache.
100 *
101 * @param objectPath - The D-Bus object path without the PIM prefix.
102 * @return true if the object exists on D-Bus, false otherwise.
103 */
104static auto isFruInVpdCache(const std::string& objectPath)
105{
106 try
107 {
108 auto bus = sdbusplus::bus::new_default();
109 auto invPath = std::string{pimPath} + objectPath;
110 auto props = bus.new_method_call(
111 "xyz.openbmc_project.Inventory.Manager", invPath.c_str(),
112 "org.freedesktop.DBus.Properties", "Get");
113 props.append("xyz.openbmc_project.Inventory.Item");
114 props.append("Present");
115 auto result = bus.call(props);
116 std::variant<bool> present;
117 result.read(present);
118 if (auto pVal = std::get_if<bool>(&present))
119 {
120 return *pVal;
121 }
122 return false;
123 }
124 catch (const sdbusplus::exception::SdBusError& e)
125 {
126 std::cout << "FRU: " << objectPath << " not in D-Bus\n";
127 // Assume not present in case of an error
128 return false;
129 }
130}
131
132/**
133 * @brief Check if VPD recollection is needed for the given EEPROM
134 *
135 * Not all FRUs can be swapped at BMC ready state. This function does the
136 * following:
137 * -- Check if the FRU is marked as "pluggableAtStandby" OR
138 * "concurrentlyMaintainable". If so, return true.
139 * -- Check if we are at BMC NotReady state. If we are, then return true.
140 * -- Else check if the FRU is not present in the VPD cache (to cover for VPD
141 * force collection). If not found in the cache, return true.
142 * -- Else return false.
143 *
144 * @param js - JSON Object.
145 * @param filePath - The EEPROM file.
146 * @return true if collection should be attempted, false otherwise.
147 */
148static auto needsRecollection(const nlohmann::json& js, const string& filePath)
149{
150 if (js["frus"][filePath].at(0).value("pluggableAtStandby", false) ||
151 js["frus"][filePath].at(0).value("concurrentlyMaintainable", false))
152 {
153 return true;
154 }
155 if (getBMCState() == "xyz.openbmc_project.State.BMC.BMCState.NotReady")
156 {
157 return true;
158 }
159 if (!isFruInVpdCache(js["frus"][filePath].at(0).value("inventoryPath", "")))
160 {
161 return true;
162 }
163 return false;
164}
165
166/**
Santosh Puranik88edeb62020-03-02 12:00:09 +0530167 * @brief Expands location codes
168 */
169static auto expandLocationCode(const string& unexpanded, const Parsed& vpdMap,
170 bool isSystemVpd)
171{
172 auto expanded{unexpanded};
173 static constexpr auto SYSTEM_OBJECT = "/system/chassis/motherboard";
174 static constexpr auto VCEN_IF = "com.ibm.ipzvpd.VCEN";
175 static constexpr auto VSYS_IF = "com.ibm.ipzvpd.VSYS";
176 size_t idx = expanded.find("fcs");
177 try
178 {
179 if (idx != string::npos)
180 {
181 string fc{};
182 string se{};
183 if (isSystemVpd)
184 {
185 const auto& fcData = vpdMap.at("VCEN").at("FC");
186 const auto& seData = vpdMap.at("VCEN").at("SE");
187 fc = string(fcData.data(), fcData.size());
188 se = string(seData.data(), seData.size());
189 }
190 else
191 {
192 fc = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "FC");
193 se = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "SE");
194 }
195
Alpana Kumari81671f62021-02-10 02:21:59 -0600196 // TODO: See if ND0 can be placed in the JSON
197 expanded.replace(idx, 3, fc.substr(0, 4) + ".ND0." + se);
Santosh Puranik88edeb62020-03-02 12:00:09 +0530198 }
199 else
200 {
201 idx = expanded.find("mts");
202 if (idx != string::npos)
203 {
204 string mt{};
205 string se{};
206 if (isSystemVpd)
207 {
208 const auto& mtData = vpdMap.at("VSYS").at("TM");
209 const auto& seData = vpdMap.at("VSYS").at("SE");
210 mt = string(mtData.data(), mtData.size());
211 se = string(seData.data(), seData.size());
212 }
213 else
214 {
215 mt = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "TM");
216 se = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "SE");
217 }
218
219 replace(mt.begin(), mt.end(), '-', '.');
220 expanded.replace(idx, 3, mt + "." + se);
221 }
222 }
223 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500224 catch (const exception& e)
Santosh Puranik88edeb62020-03-02 12:00:09 +0530225 {
jinuthomasf457a3e2023-04-13 12:22:48 -0500226 std::cerr << "Failed to expand location code with exception: "
227 << e.what() << "\n";
Santosh Puranik88edeb62020-03-02 12:00:09 +0530228 }
229 return expanded;
230}
Alpana Kumari2f793042020-08-18 05:51:03 -0500231
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530232/**
233 * @brief Populate FRU specific interfaces.
234 *
235 * This is a common method which handles both
236 * ipz and keyword specific interfaces thus,
237 * reducing the code redundancy.
238 * @param[in] map - Reference to the innermost keyword-value map.
239 * @param[in] preIntrStr - Reference to the interface string.
240 * @param[out] interfaces - Reference to interface map.
241 */
242template <typename T>
Patrick Williams08dc31c2024-08-16 15:21:06 -0400243static void populateFruSpecificInterfaces(
244 const T& map, const string& preIntrStr, inventory::InterfaceMap& interfaces)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530245{
246 inventory::PropertyMap prop;
247
248 for (const auto& kwVal : map)
249 {
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530250 auto kw = kwVal.first;
251
252 if (kw[0] == '#')
253 {
Alpana Kumari58e22142020-05-05 00:22:12 -0500254 kw = string("PD_") + kw[1];
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530255 }
Alpana Kumari8ea3f6d2020-04-02 00:26:07 -0500256 else if (isdigit(kw[0]))
257 {
Alpana Kumari58e22142020-05-05 00:22:12 -0500258 kw = string("N_") + kw;
Alpana Kumari8ea3f6d2020-04-02 00:26:07 -0500259 }
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000260 if constexpr (is_same<T, KeywordVpdMap>::value)
261 {
jinuthomasd640f692023-03-28 04:13:23 -0500262 if (auto keywordValue = get_if<Binary>(&kwVal.second))
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000263 {
jinuthomasd640f692023-03-28 04:13:23 -0500264 Binary vec((*keywordValue).begin(), (*keywordValue).end());
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000265 prop.emplace(move(kw), move(vec));
266 }
jinuthomasd640f692023-03-28 04:13:23 -0500267 else if (auto keywordValue = get_if<std::string>(&kwVal.second))
268 {
269 Binary vec((*keywordValue).begin(), (*keywordValue).end());
270 prop.emplace(move(kw), move(vec));
271 }
272 else if (auto keywordValue = get_if<size_t>(&kwVal.second))
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000273 {
274 if (kw == "MemorySizeInKB")
275 {
276 inventory::PropertyMap memProp;
jinuthomasd640f692023-03-28 04:13:23 -0500277 memProp.emplace(move(kw), ((*keywordValue)));
278 interfaces.emplace(
279 "xyz.openbmc_project.Inventory.Item.Dimm",
280 move(memProp));
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000281 }
jinuthomasd640f692023-03-28 04:13:23 -0500282 else
283 {
jinuthomasf457a3e2023-04-13 12:22:48 -0500284 std::cerr << "Unknown Keyword[" << kw << "] found ";
jinuthomasd640f692023-03-28 04:13:23 -0500285 }
286 }
287 else
288 {
jinuthomasf457a3e2023-04-13 12:22:48 -0500289 std::cerr << "Unknown Variant found ";
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000290 }
291 }
292 else
293 {
294 Binary vec(kwVal.second.begin(), kwVal.second.end());
295 prop.emplace(move(kw), move(vec));
296 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530297 }
298
299 interfaces.emplace(preIntrStr, move(prop));
300}
301
302/**
303 * @brief Populate Interfaces.
304 *
305 * This method populates common and extra interfaces to dbus.
306 * @param[in] js - json object
307 * @param[out] interfaces - Reference to interface map
308 * @param[in] vpdMap - Reference to the parsed vpd map.
Santosh Puranik88edeb62020-03-02 12:00:09 +0530309 * @param[in] isSystemVpd - Denotes whether we are collecting the system VPD.
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530310 */
311template <typename T>
312static void populateInterfaces(const nlohmann::json& js,
313 inventory::InterfaceMap& interfaces,
Santosh Puranik88edeb62020-03-02 12:00:09 +0530314 const T& vpdMap, bool isSystemVpd)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530315{
316 for (const auto& ifs : js.items())
317 {
Santosh Puranik88edeb62020-03-02 12:00:09 +0530318 string inf = ifs.key();
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530319 inventory::PropertyMap props;
320
321 for (const auto& itr : ifs.value().items())
322 {
Santosh Puranik88edeb62020-03-02 12:00:09 +0530323 const string& busProp = itr.key();
324
Alpana Kumari31970de2020-02-17 06:49:57 -0600325 if (itr.value().is_boolean())
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530326 {
Santosh Puranik88edeb62020-03-02 12:00:09 +0530327 props.emplace(busProp, itr.value().get<bool>());
328 }
329 else if (itr.value().is_string())
330 {
Priyanga Ramasamy0d61c582022-01-21 04:38:22 -0600331 if (busProp == "LocationCode" && inf == IBM_LOCATION_CODE_INF)
Santosh Puranik88edeb62020-03-02 12:00:09 +0530332 {
Priyanga Ramasamy0d61c582022-01-21 04:38:22 -0600333 std::string prop;
334 if constexpr (is_same<T, Parsed>::value)
Santosh Puranik88edeb62020-03-02 12:00:09 +0530335 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000336 // TODO deprecate the com.ibm interface later
Priyanga Ramasamy0d61c582022-01-21 04:38:22 -0600337 prop = expandLocationCode(itr.value().get<string>(),
338 vpdMap, isSystemVpd);
Santosh Puranik88edeb62020-03-02 12:00:09 +0530339 }
Priyanga Ramasamy0d61c582022-01-21 04:38:22 -0600340 else if constexpr (is_same<T, KeywordVpdMap>::value)
Santosh Puranik88edeb62020-03-02 12:00:09 +0530341 {
Priyanga Ramasamy0d61c582022-01-21 04:38:22 -0600342 // Send empty Parsed object to expandLocationCode api.
343 prop = expandLocationCode(itr.value().get<string>(),
344 Parsed{}, false);
Santosh Puranik88edeb62020-03-02 12:00:09 +0530345 }
Priyanga Ramasamy0d61c582022-01-21 04:38:22 -0600346 props.emplace(busProp, prop);
347 interfaces.emplace(XYZ_LOCATION_CODE_INF, props);
348 interfaces.emplace(IBM_LOCATION_CODE_INF, props);
Santosh Puranik88edeb62020-03-02 12:00:09 +0530349 }
350 else
351 {
352 props.emplace(busProp, itr.value().get<string>());
353 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530354 }
Santosh Puraniked609af2021-06-21 11:30:07 +0530355 else if (itr.value().is_array())
356 {
357 try
358 {
359 props.emplace(busProp, itr.value().get<Binary>());
360 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500361 catch (const nlohmann::detail::type_error& e)
Santosh Puraniked609af2021-06-21 11:30:07 +0530362 {
363 std::cerr << "Type exception: " << e.what() << "\n";
364 // Ignore any type errors
365 }
366 }
Alpana Kumari31970de2020-02-17 06:49:57 -0600367 else if (itr.value().is_object())
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530368 {
Alpana Kumari31970de2020-02-17 06:49:57 -0600369 const string& rec = itr.value().value("recordName", "");
370 const string& kw = itr.value().value("keywordName", "");
371 const string& encoding = itr.value().value("encoding", "");
372
Alpana Kumari58e22142020-05-05 00:22:12 -0500373 if constexpr (is_same<T, Parsed>::value)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530374 {
Santosh Puranik88edeb62020-03-02 12:00:09 +0530375 if (!rec.empty() && !kw.empty() && vpdMap.count(rec) &&
376 vpdMap.at(rec).count(kw))
Alpana Kumari31970de2020-02-17 06:49:57 -0600377 {
Patrick Williams08dc31c2024-08-16 15:21:06 -0400378 auto encoded =
379 encodeKeyword(vpdMap.at(rec).at(kw), encoding);
Santosh Puranik88edeb62020-03-02 12:00:09 +0530380 props.emplace(busProp, encoded);
Alpana Kumari31970de2020-02-17 06:49:57 -0600381 }
382 }
Alpana Kumari58e22142020-05-05 00:22:12 -0500383 else if constexpr (is_same<T, KeywordVpdMap>::value)
Alpana Kumari31970de2020-02-17 06:49:57 -0600384 {
385 if (!kw.empty() && vpdMap.count(kw))
386 {
jinuthomasd640f692023-03-28 04:13:23 -0500387 if (auto kwValue = get_if<Binary>(&vpdMap.at(kw)))
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000388 {
Patrick Williams08dc31c2024-08-16 15:21:06 -0400389 auto prop =
390 string((*kwValue).begin(), (*kwValue).end());
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000391
392 auto encoded = encodeKeyword(prop, encoding);
393
394 props.emplace(busProp, encoded);
395 }
jinuthomasd640f692023-03-28 04:13:23 -0500396 else if (auto kwValue =
397 get_if<std::string>(&vpdMap.at(kw)))
398 {
Patrick Williams08dc31c2024-08-16 15:21:06 -0400399 auto prop =
400 string((*kwValue).begin(), (*kwValue).end());
jinuthomasd640f692023-03-28 04:13:23 -0500401
402 auto encoded = encodeKeyword(prop, encoding);
403
404 props.emplace(busProp, encoded);
405 }
406 else if (auto uintValue =
407 get_if<size_t>(&vpdMap.at(kw)))
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000408 {
409 props.emplace(busProp, *uintValue);
410 }
jinuthomasd640f692023-03-28 04:13:23 -0500411 else
412 {
413 std::cerr << " Unknown Keyword [" << kw
414 << "] Encountered";
415 }
Alpana Kumari31970de2020-02-17 06:49:57 -0600416 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530417 }
418 }
Matt Spinlerb1e64bb2021-09-08 09:57:48 -0500419 else if (itr.value().is_number())
420 {
421 // For now assume the value is a size_t. In the future it would
422 // be nice to come up with a way to get the type from the JSON.
423 props.emplace(busProp, itr.value().get<size_t>());
424 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530425 }
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600426 insertOrMerge(interfaces, inf, move(props));
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530427 }
428}
429
alpana075cb3b1f2021-12-16 11:19:36 -0600430/**
431 * @brief This API checks if this FRU is pcie_devices. If yes then it further
432 * checks whether it is PASS1 planar.
433 */
434static bool isThisPcieOnPass1planar(const nlohmann::json& js,
435 const string& file)
436{
437 auto isThisPCIeDev = false;
438 auto isPASS1 = false;
439
440 // Check if it is a PCIE device
441 if (js["frus"].find(file) != js["frus"].end())
442 {
Santosh Puranikc03f3902022-04-14 10:58:26 +0530443 if ((js["frus"][file].at(0).find("extraInterfaces") !=
444 js["frus"][file].at(0).end()))
alpana075cb3b1f2021-12-16 11:19:36 -0600445 {
Santosh Puranikc03f3902022-04-14 10:58:26 +0530446 if (js["frus"][file].at(0)["extraInterfaces"].find(
alpana075cb3b1f2021-12-16 11:19:36 -0600447 "xyz.openbmc_project.Inventory.Item.PCIeDevice") !=
Santosh Puranikc03f3902022-04-14 10:58:26 +0530448 js["frus"][file].at(0)["extraInterfaces"].end())
alpana075cb3b1f2021-12-16 11:19:36 -0600449 {
450 isThisPCIeDev = true;
451 }
452 }
453 }
454
455 if (isThisPCIeDev)
456 {
Alpana Kumaria6181e22022-05-12 05:01:53 -0500457 // Collect HW version and SystemType to know if it is PASS1 planar.
alpana075cb3b1f2021-12-16 11:19:36 -0600458 auto bus = sdbusplus::bus::new_default();
Alpana Kumaria6181e22022-05-12 05:01:53 -0500459 auto property1 = bus.new_method_call(
alpana075cb3b1f2021-12-16 11:19:36 -0600460 INVENTORY_MANAGER_SERVICE,
461 "/xyz/openbmc_project/inventory/system/chassis/motherboard",
462 "org.freedesktop.DBus.Properties", "Get");
Alpana Kumaria6181e22022-05-12 05:01:53 -0500463 property1.append("com.ibm.ipzvpd.VINI");
464 property1.append("HW");
465 auto result1 = bus.call(property1);
466 inventory::Value hwVal;
467 result1.read(hwVal);
alpana075cb3b1f2021-12-16 11:19:36 -0600468
Alpana Kumaria6181e22022-05-12 05:01:53 -0500469 // SystemType
470 auto property2 = bus.new_method_call(
471 INVENTORY_MANAGER_SERVICE,
472 "/xyz/openbmc_project/inventory/system/chassis/motherboard",
473 "org.freedesktop.DBus.Properties", "Get");
474 property2.append("com.ibm.ipzvpd.VSBP");
475 property2.append("IM");
476 auto result2 = bus.call(property2);
477 inventory::Value imVal;
478 result2.read(imVal);
479
480 auto pVal1 = get_if<Binary>(&hwVal);
481 auto pVal2 = get_if<Binary>(&imVal);
482
483 if (pVal1 && pVal2)
alpana075cb3b1f2021-12-16 11:19:36 -0600484 {
Alpana Kumaria6181e22022-05-12 05:01:53 -0500485 auto hwVersion = *pVal1;
486 auto systemType = *pVal2;
487
488 // IM kw for Everest
489 Binary everestSystem{80, 00, 48, 00};
490
491 if (systemType == everestSystem)
492 {
493 if (hwVersion[1] < 21)
494 {
495 isPASS1 = true;
496 }
497 }
498 else if (hwVersion[1] < 2)
499 {
alpana075cb3b1f2021-12-16 11:19:36 -0600500 isPASS1 = true;
Alpana Kumaria6181e22022-05-12 05:01:53 -0500501 }
alpana075cb3b1f2021-12-16 11:19:36 -0600502 }
503 }
504
505 return (isThisPCIeDev && isPASS1);
506}
507
Alpana Kumari735dee92022-03-25 01:24:40 -0500508/** Performs any pre-action needed to get the FRU setup for collection.
Alpana Kumari2f793042020-08-18 05:51:03 -0500509 *
510 * @param[in] json - json object
511 * @param[in] file - eeprom file path
512 */
513static void preAction(const nlohmann::json& json, const string& file)
514{
Alpana Kumari735dee92022-03-25 01:24:40 -0500515 if ((json["frus"][file].at(0)).find("preAction") ==
Alpana Kumari2f793042020-08-18 05:51:03 -0500516 json["frus"][file].at(0).end())
517 {
Alpana Kumari735dee92022-03-25 01:24:40 -0500518 return;
Alpana Kumari2f793042020-08-18 05:51:03 -0500519 }
520
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500521 try
Alpana Kumari2f793042020-08-18 05:51:03 -0500522 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500523 if (executePreAction(json, file))
Alpana Kumari2f793042020-08-18 05:51:03 -0500524 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500525 if (json["frus"][file].at(0).find("devAddress") !=
526 json["frus"][file].at(0).end())
Alpana Kumari40d1c192022-03-09 21:16:02 -0600527 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500528 // Now bind the device
529 string bind = json["frus"][file].at(0).value("devAddress", "");
jinuthomasf457a3e2023-04-13 12:22:48 -0500530 std::cout << "Binding device " << bind << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500531 string bindCmd = string("echo \"") + bind +
532 string("\" > /sys/bus/i2c/drivers/at24/bind");
jinuthomasf457a3e2023-04-13 12:22:48 -0500533 std::cout << bindCmd << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500534 executeCmd(bindCmd);
535
536 // Check if device showed up (test for file)
537 if (!fs::exists(file))
538 {
Patrick Williams08dc31c2024-08-16 15:21:06 -0400539 std::cerr
540 << "EEPROM " << file
541 << " does not exist. Take failure action" << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500542 // If not, then take failure postAction
543 executePostFailAction(json, file);
544 }
545 }
546 else
547 {
Manojkiran Edaaf921752024-06-17 15:10:21 +0530548 // missing required information
549 std::cerr << "VPD inventory JSON missing basic information of "
jinuthomasf457a3e2023-04-13 12:22:48 -0500550 "preAction "
551 "for this FRU : ["
552 << file << "]. Executing executePostFailAction."
553 << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500554
555 // Take failure postAction
Alpana Kumari40d1c192022-03-09 21:16:02 -0600556 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500557 return;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600558 }
559 }
Santosh Puranikdedb5a62022-12-19 23:58:32 +0530560 else
561 {
562 // If the FRU is not there, clear the VINI/CCIN data.
Manojkiran Edaaf921752024-06-17 15:10:21 +0530563 // Entity manager probes for this keyword to look for this
Santosh Puranikdedb5a62022-12-19 23:58:32 +0530564 // FRU, now if the data is persistent on BMC and FRU is
565 // removed this can lead to ambiguity. Hence clearing this
566 // Keyword if FRU is absent.
567 const auto& invPath =
568 json["frus"][file].at(0).value("inventoryPath", "");
569
570 if (!invPath.empty())
571 {
572 inventory::ObjectMap pimObjMap{
573 {invPath, {{"com.ibm.ipzvpd.VINI", {{"CC", Binary{}}}}}}};
574
575 common::utility::callPIM(move(pimObjMap));
576 }
577 else
578 {
579 throw std::runtime_error("Path empty in Json");
580 }
581 }
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500582 }
583 catch (const GpioException& e)
584 {
585 PelAdditionalData additionalData{};
586 additionalData.emplace("DESCRIPTION", e.what());
587 createPEL(additionalData, PelSeverity::WARNING, errIntfForGpioError,
588 nullptr);
Alpana Kumari2f793042020-08-18 05:51:03 -0500589 }
Alpana Kumari2f793042020-08-18 05:51:03 -0500590}
591
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530592/**
Santosh Puranikf3e69682022-03-31 17:52:38 +0530593 * @brief Fills the Decorator.AssetTag property into the interfaces map
594 *
595 * This function should only be called in cases where we did not find a JSON
596 * symlink. A missing symlink in /var/lib will be considered as a factory reset
597 * and this function will be used to default the AssetTag property.
598 *
599 * @param interfaces A possibly pre-populated map of inetrfaces to properties.
600 * @param vpdMap A VPD map of the system VPD data.
601 */
602static void fillAssetTag(inventory::InterfaceMap& interfaces,
603 const Parsed& vpdMap)
604{
605 // Read the system serial number and MTM
606 // Default asset tag is Server-MTM-System Serial
607 inventory::Interface assetIntf{
608 "xyz.openbmc_project.Inventory.Decorator.AssetTag"};
609 inventory::PropertyMap assetTagProps;
610 std::string defaultAssetTag =
611 std::string{"Server-"} + getKwVal(vpdMap, "VSYS", "TM") +
612 std::string{"-"} + getKwVal(vpdMap, "VSYS", "SE");
613 assetTagProps.emplace("AssetTag", defaultAssetTag);
614 insertOrMerge(interfaces, assetIntf, std::move(assetTagProps));
615}
616
617/**
Santosh Puranikd3a379a2021-08-23 19:12:59 +0530618 * @brief Set certain one time properties in the inventory
619 * Use this function to insert the Functional and Enabled properties into the
620 * inventory map. This function first checks if the object in question already
621 * has these properties hosted on D-Bus, if the property is already there, it is
622 * not modified, hence the name "one time". If the property is not already
623 * present, it will be added to the map with a suitable default value (true for
Santosh Puranikdedb5a62022-12-19 23:58:32 +0530624 * Functional and Enabled)
Santosh Puranikd3a379a2021-08-23 19:12:59 +0530625 *
Manojkiran Edaaf921752024-06-17 15:10:21 +0530626 * @param[in] object - The inventory D-Bus object without the inventory prefix.
627 * @param[in,out] interfaces - Reference to a map of inventory interfaces to
Santosh Puranikd3a379a2021-08-23 19:12:59 +0530628 * which the properties will be attached.
629 */
630static void setOneTimeProperties(const std::string& object,
631 inventory::InterfaceMap& interfaces)
632{
633 auto bus = sdbusplus::bus::new_default();
634 auto objectPath = INVENTORY_PATH + object;
635 auto prop = bus.new_method_call("xyz.openbmc_project.Inventory.Manager",
636 objectPath.c_str(),
637 "org.freedesktop.DBus.Properties", "Get");
638 prop.append("xyz.openbmc_project.State.Decorator.OperationalStatus");
639 prop.append("Functional");
640 try
641 {
642 auto result = bus.call(prop);
643 }
644 catch (const sdbusplus::exception::SdBusError& e)
645 {
646 // Treat as property unavailable
647 inventory::PropertyMap prop;
648 prop.emplace("Functional", true);
649 interfaces.emplace(
650 "xyz.openbmc_project.State.Decorator.OperationalStatus",
651 move(prop));
652 }
653 prop = bus.new_method_call("xyz.openbmc_project.Inventory.Manager",
654 objectPath.c_str(),
655 "org.freedesktop.DBus.Properties", "Get");
656 prop.append("xyz.openbmc_project.Object.Enable");
657 prop.append("Enabled");
658 try
659 {
660 auto result = bus.call(prop);
661 }
662 catch (const sdbusplus::exception::SdBusError& e)
663 {
664 // Treat as property unavailable
665 inventory::PropertyMap prop;
Santosh Puranikdedb5a62022-12-19 23:58:32 +0530666 prop.emplace("Enabled", true);
Santosh Puranikd3a379a2021-08-23 19:12:59 +0530667 interfaces.emplace("xyz.openbmc_project.Object.Enable", move(prop));
668 }
669}
670
671/**
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530672 * @brief Prime the Inventory
673 * Prime the inventory by populating only the location code,
674 * type interface and the inventory object for the frus
675 * which are not system vpd fru.
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530676 *
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530677 * @param[in] jsObject - Reference to vpd inventory json object
678 * @param[in] vpdMap - Reference to the parsed vpd map
679 *
680 * @returns Map of items in extraInterface.
681 */
682template <typename T>
Patrick Williams08dc31c2024-08-16 15:21:06 -0400683inventory::ObjectMap
684 primeInventory(const nlohmann::json& jsObject, const T& vpdMap)
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530685{
686 inventory::ObjectMap objects;
687
688 for (auto& itemFRUS : jsObject["frus"].items())
689 {
690 for (auto& itemEEPROM : itemFRUS.value())
691 {
Alpana Kumari2e6c6f72020-12-03 00:10:03 -0600692 // Take pre actions if needed
693 if (itemEEPROM.find("preAction") != itemEEPROM.end())
694 {
695 preAction(jsObject, itemFRUS.key());
696 }
697
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530698 inventory::InterfaceMap interfaces;
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530699 inventory::Object object(itemEEPROM.at("inventoryPath"));
700
Santosh Puranik50f60bf2021-05-26 17:55:06 +0530701 if ((itemFRUS.key() != systemVpdFilePath) &&
702 !itemEEPROM.value("noprime", false))
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530703 {
Alpana Kumaricfd7a752021-02-07 23:23:01 -0600704 inventory::PropertyMap presProp;
Priyanga Ramasamye358acb2022-03-21 14:21:50 -0500705
706 // Do not populate Present property for frus whose
Priyanga Ramasamyaca61372023-01-24 08:02:28 -0600707 // synthesized=true. synthesized=true says the fru VPD is
708 // synthesized and owned by a separate component.
709 // In some cases, the FRU has its own VPD, but still a separate
710 // application handles the FRU's presence. So VPD parser skips
711 // populating Present property by checking the JSON flag,
712 // "handlePresence".
Priyanga Ramasamye358acb2022-03-21 14:21:50 -0500713 if (!itemEEPROM.value("synthesized", false))
714 {
Priyanga Ramasamyaca61372023-01-24 08:02:28 -0600715 if (itemEEPROM.value("handlePresence", true))
716 {
717 presProp.emplace("Present", false);
718 interfaces.emplace("xyz.openbmc_project.Inventory.Item",
719 presProp);
720 }
Priyanga Ramasamye358acb2022-03-21 14:21:50 -0500721 }
Priyanga Ramasamyaca61372023-01-24 08:02:28 -0600722
Santosh Puranikd3a379a2021-08-23 19:12:59 +0530723 setOneTimeProperties(object, interfaces);
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530724 if (itemEEPROM.find("extraInterfaces") != itemEEPROM.end())
725 {
726 for (const auto& eI : itemEEPROM["extraInterfaces"].items())
727 {
728 inventory::PropertyMap props;
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000729 if (eI.key() == IBM_LOCATION_CODE_INF)
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530730 {
731 if constexpr (std::is_same<T, Parsed>::value)
732 {
733 for (auto& lC : eI.value().items())
734 {
735 auto propVal = expandLocationCode(
736 lC.value().get<string>(), vpdMap, true);
737
738 props.emplace(move(lC.key()),
739 move(propVal));
Santosh Puranikb0f37492021-06-21 09:42:47 +0530740 interfaces.emplace(XYZ_LOCATION_CODE_INF,
741 props);
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530742 interfaces.emplace(move(eI.key()),
743 move(props));
744 }
745 }
746 }
Santosh Puranikd3a379a2021-08-23 19:12:59 +0530747 else if (eI.key() ==
748 "xyz.openbmc_project.Inventory.Item")
749 {
750 for (auto& val : eI.value().items())
751 {
752 if (val.key() == "PrettyName")
753 {
754 presProp.emplace(val.key(),
755 val.value().get<string>());
756 }
757 }
758 // Use insert_or_assign here as we may already have
759 // inserted the present property only earlier in
760 // this function under this same interface.
761 interfaces.insert_or_assign(eI.key(),
762 move(presProp));
763 }
Sunny Srivastava1bb87162024-02-13 00:09:09 -0600764 else
765 {
766 interfaces.emplace(move(eI.key()), move(props));
767 }
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530768 }
769 }
770 objects.emplace(move(object), move(interfaces));
771 }
772 }
773 }
774 return objects;
775}
776
Alpana Kumari65b83602020-09-01 00:24:56 -0500777/**
778 * @brief This API executes command to set environment variable
779 * And then reboot the system
780 * @param[in] key -env key to set new value
781 * @param[in] value -value to set.
782 */
783void setEnvAndReboot(const string& key, const string& value)
784{
785 // set env and reboot and break.
786 executeCmd("/sbin/fw_setenv", key, value);
Andrew Geissler280197e2020-12-08 20:51:49 -0600787 log<level::INFO>("Rebooting BMC to pick up new device tree");
Alpana Kumari65b83602020-09-01 00:24:56 -0500788 // make dbus call to reboot
789 auto bus = sdbusplus::bus::new_default_system();
790 auto method = bus.new_method_call(
791 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
792 "org.freedesktop.systemd1.Manager", "Reboot");
793 bus.call_noreply(method);
794}
795
796/*
797 * @brief This API checks for env var fitconfig.
798 * If not initialised OR updated as per the current system type,
799 * update this env var and reboot the system.
800 *
801 * @param[in] systemType IM kwd in vpd tells about which system type it is.
802 * */
803void setDevTreeEnv(const string& systemType)
804{
Alpana Kumari37e72702021-11-18 11:18:04 -0600805 // Init with default dtb
806 string newDeviceTree = "conf-aspeed-bmc-ibm-rainier-p1.dtb";
Santosh Puranike5f177a2022-01-24 20:14:46 +0530807 static const deviceTreeMap deviceTreeSystemTypeMap = {
808 {RAINIER_2U, "conf-aspeed-bmc-ibm-rainier-p1.dtb"},
809 {RAINIER_2U_V2, "conf-aspeed-bmc-ibm-rainier.dtb"},
810 {RAINIER_4U, "conf-aspeed-bmc-ibm-rainier-4u-p1.dtb"},
811 {RAINIER_4U_V2, "conf-aspeed-bmc-ibm-rainier-4u.dtb"},
812 {RAINIER_1S4U, "conf-aspeed-bmc-ibm-rainier-1s4u.dtb"},
Alpana Kumari1b026112022-03-02 23:41:38 -0600813 {EVEREST, "conf-aspeed-bmc-ibm-everest.dtb"},
Santosh Puranikdedb5a62022-12-19 23:58:32 +0530814 {EVEREST_V2, "conf-aspeed-bmc-ibm-everest.dtb"},
Jinu Joy Thomas3b61ff52024-07-18 23:24:01 -0500815 {BONNELL, "conf-aspeed-bmc-ibm-bonnell.dtb"},
816 {BLUERIDGE_2U, "conf-aspeed-bmc-ibm-blueridge-p1.dtb"},
817 {BLUERIDGE_2U_V2, "conf-aspeed-bmc-ibm-blueridge.dtb"},
818 {BLUERIDGE_4U, "conf-aspeed-bmc-ibm-blueridge-4u-p1.dtb"},
819 {BLUERIDGE_4U_V2, "conf-aspeed-bmc-ibm-blueridge-4u.dtb"},
820 {BLUERIDGE_1S4U, "conf-aspeed-bmc-ibm-blueridge-1s4u.dtb"},
821 {FUJI, "conf-aspeed-bmc-ibm-fuji.dtb"},
Jinu Joy Thomasc023f9b2024-08-25 22:42:34 -0500822 {HUYGENS, "conf-aspeed-bmc-ibm-huygens.dtb"},
Jinu Joy Thomas3b61ff52024-07-18 23:24:01 -0500823 {FUJI_V2, "conf-aspeed-bmc-ibm-fuji.dtb"}};
Alpana Kumari65b83602020-09-01 00:24:56 -0500824
825 if (deviceTreeSystemTypeMap.find(systemType) !=
826 deviceTreeSystemTypeMap.end())
827 {
828 newDeviceTree = deviceTreeSystemTypeMap.at(systemType);
829 }
Alpana Kumari37e72702021-11-18 11:18:04 -0600830 else
831 {
832 // System type not supported
Alpana Kumariab1e22c2021-11-24 11:03:38 -0600833 string err = "This System type not found/supported in dtb table " +
834 systemType +
835 ".Please check the HW and IM keywords in the system "
836 "VPD.Breaking...";
837
838 // map to hold additional data in case of logging pel
839 PelAdditionalData additionalData{};
840 additionalData.emplace("DESCRIPTION", err);
841 createPEL(additionalData, PelSeverity::WARNING,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500842 errIntfForInvalidSystemType, nullptr);
Alpana Kumariab1e22c2021-11-24 11:03:38 -0600843 exit(-1);
Alpana Kumari37e72702021-11-18 11:18:04 -0600844 }
Alpana Kumari65b83602020-09-01 00:24:56 -0500845
846 string readVarValue;
847 bool envVarFound = false;
848
849 vector<string> output = executeCmd("/sbin/fw_printenv");
850 for (const auto& entry : output)
851 {
852 size_t pos = entry.find("=");
853 string key = entry.substr(0, pos);
854 if (key != "fitconfig")
855 {
856 continue;
857 }
858
859 envVarFound = true;
860 if (pos + 1 < entry.size())
861 {
862 readVarValue = entry.substr(pos + 1);
863 if (readVarValue.find(newDeviceTree) != string::npos)
864 {
865 // fitconfig is Updated. No action needed
866 break;
867 }
868 }
869 // set env and reboot and break.
870 setEnvAndReboot(key, newDeviceTree);
871 exit(0);
872 }
873
874 // check If env var Not found
875 if (!envVarFound)
876 {
877 setEnvAndReboot("fitconfig", newDeviceTree);
878 }
879}
880
PriyangaRamasamy8e140a12020-04-13 19:24:03 +0530881/**
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500882 * @brief Parse the given EEPROM file.
883 *
884 * @param[in] vpdFilePath - Path of EEPROM file
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500885 * @param[in] js- Reference to vpd inventory json object
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500886 * @return Parsed VPD map
887 */
888std::variant<KeywordVpdMap, openpower::vpd::Store>
Sunny Srivastava37992a62023-07-11 05:18:41 -0500889 parseVpdFile(const std::string& vpdFilePath, const nlohmann::json& js)
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500890{
891 uint32_t vpdStartOffset = 0;
892 for (const auto& item : js["frus"][vpdFilePath])
893 {
894 if (item.find("offset") != item.end())
895 {
896 vpdStartOffset = item["offset"];
Sunny Srivastava37992a62023-07-11 05:18:41 -0500897 break;
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500898 }
899 }
900
901 Binary vpdVector = getVpdDataInVector(js, vpdFilePath);
902
903 ParserInterface* parser = ParserFactory::getParser(
Sunny Srivastava37992a62023-07-11 05:18:41 -0500904 vpdVector,
905 (pimPath + js["frus"][vpdFilePath][0]["inventoryPath"]
906 .get_ref<const nlohmann::json::string_t&>()),
907 vpdFilePath, vpdStartOffset);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500908
909 auto parseResult = parser->parse();
910
911 // release the parser object
912 ParserFactory::freeParser(parser);
913
914 return parseResult;
915}
916
917/*
918 * @brief This API retrieves the hardware backup in map
919 *
920 * @param[in] systemVpdBackupPath - The path that backs up the system VPD.
921 * @param[in] backupVpdInvPath - FRU inventory path.
922 * @param[in] js - JSON object.
923 * @param[out] backupVpdMap - An IPZ VPD map containing the parsed backup VPD.
924 *
925 * */
926void getBackupVpdInMap(const string& systemVpdBackupPath,
927 const string& backupVpdInvPath, const nlohmann::json& js,
928 Parsed& backupVpdMap)
929{
930 PelAdditionalData additionalData{};
931
932 if (!fs::exists(systemVpdBackupPath))
933 {
934 string errorMsg = "Device path ";
935 errorMsg += systemVpdBackupPath;
936 errorMsg += " does not exist";
937
938 additionalData.emplace("DESCRIPTION", errorMsg);
939
940 additionalData.emplace("CALLOUT_INVENTORY_PATH",
941 INVENTORY_PATH + backupVpdInvPath);
942
943 createPEL(additionalData, PelSeverity::ERROR, errIntfForStreamFail,
944 nullptr);
945 }
946 else
947 {
Sunny Srivastava37992a62023-07-11 05:18:41 -0500948 auto backupVpdParsedResult = parseVpdFile(systemVpdBackupPath, js);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500949
950 if (auto pVal = get_if<Store>(&backupVpdParsedResult))
951 {
952 backupVpdMap = pVal->getVpdMap();
953 }
Sunny Srivastava37992a62023-07-11 05:18:41 -0500954 else
955 {
956 std::cerr << "Invalid format of VPD in back up. Restore aborted."
957 << std::endl;
958 }
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500959 }
960}
961
962void updateVpdDataOnHw(const std::string& vpdFilePath, nlohmann::json& js,
963 const std::string& recName, const std::string& kwName,
964 const Binary& kwdData)
965{
966 const std::string& fruInvPath =
967 js["frus"][vpdFilePath][0]["inventoryPath"]
968 .get_ref<const nlohmann::json::string_t&>();
969
970 EditorImpl edit(vpdFilePath, js, recName, kwName, fruInvPath);
971
972 uint32_t offset = 0;
973 // Setup offset, if any
974 for (const auto& item : js["frus"][vpdFilePath])
975 {
976 if (item.find("offset") != item.end())
977 {
978 offset = item["offset"];
979 break;
980 }
981 }
982
983 // update keyword data on to EEPROM file
984 // Note: Updating keyword data on cache is
985 // handled via PIM Notify call hence passing
986 // the updCache flag value as false here.
987 edit.updateKeyword(kwdData, offset, false);
988}
989
990/**
SunnySrivastava19849094d4f2020-08-05 09:32:29 -0500991 * @brief API to check if we need to restore system VPD
992 * This functionality is only applicable for IPZ VPD data.
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500993
SunnySrivastava19849094d4f2020-08-05 09:32:29 -0500994 * @param[in] vpdMap - IPZ vpd map
995 * @param[in] objectPath - Object path for the FRU
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500996 * @param[in] js - JSON Object
997 * @param[in] isBackupOnCache - Denotes whether the backup is on cache/hardware
SunnySrivastava19849094d4f2020-08-05 09:32:29 -0500998 */
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -0500999void restoreSystemVPD(Parsed& vpdMap, const string& objectPath,
1000 nlohmann::json& js, bool isBackupOnCache = true)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001001{
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001002 std::string systemVpdBackupPath{};
1003 std::string backupVpdInvPath{};
1004 Parsed backupVpdMap{};
1005
1006 if (!isBackupOnCache)
1007 {
1008 // Get the value of systemvpdBackupPath field from json
1009 systemVpdBackupPath = js["frus"][systemVpdFilePath].at(0).value(
1010 "systemVpdBackupPath", "");
1011
1012 backupVpdInvPath = js["frus"][systemVpdBackupPath][0]["inventoryPath"]
1013 .get_ref<const nlohmann::json::string_t&>();
1014
1015 getBackupVpdInMap(systemVpdBackupPath, backupVpdInvPath, js,
1016 backupVpdMap);
1017
1018 if (backupVpdMap.empty())
1019 {
Sunny Srivastava37992a62023-07-11 05:18:41 -05001020 std::cerr << "Backup VPD map is empty" << std::endl;
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001021 return;
1022 }
1023 }
1024
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001025 for (const auto& systemRecKwdPair : svpdKwdMap)
1026 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001027 const string& recordName = systemRecKwdPair.first;
1028 auto it = vpdMap.find(recordName);
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001029
1030 // check if record is found in map we got by parser
1031 if (it != vpdMap.end())
1032 {
1033 const auto& kwdListForRecord = systemRecKwdPair.second;
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -06001034 for (const auto& keywordInfo : kwdListForRecord)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001035 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001036 const auto keywordName = get<0>(keywordInfo);
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -06001037
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001038 DbusPropertyMap& kwdValMap = it->second;
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001039 auto iterator = kwdValMap.find(keywordName);
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001040
1041 if (iterator != kwdValMap.end())
1042 {
1043 string& kwdValue = iterator->second;
1044
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001045 std::string backupValue{};
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -06001046 const auto& defaultValue = get<1>(keywordInfo);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001047 const auto& backupVpdRecName = get<4>(keywordInfo);
1048 const auto& backupVpdKwName = get<5>(keywordInfo);
1049
1050 // If the 'isBackupOnCache' flag is false, we need
1051 // to backup the systemVPD on the specified fru's eeprom
1052 // path or restore it from the specified fru's eeprom path.
1053 if (isBackupOnCache)
1054 {
1055 // check bus data
1056 backupValue = readBusProperty(
1057 objectPath, ipzVpdInf + recordName, keywordName);
1058 }
1059 else
1060 {
Sunny Srivastava37992a62023-07-11 05:18:41 -05001061 backupValue = getKwVal(backupVpdMap, backupVpdRecName,
1062 backupVpdKwName);
1063
1064 if (backupValue.empty())
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001065 {
Sunny Srivastava37992a62023-07-11 05:18:41 -05001066 string errorMsg{};
1067 if (backupVpdMap.find(backupVpdRecName) ==
1068 backupVpdMap.end())
1069 {
1070 errorMsg = backupVpdRecName +
1071 " Record does not exist in "
1072 "the EEPROM file ";
1073 }
1074 else
1075 {
1076 errorMsg = backupVpdKwName +
1077 " Keyword not found or empty.";
1078 }
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001079
1080 errorMsg += systemVpdBackupPath;
1081
1082 PelAdditionalData additionalData;
1083 additionalData.emplace("DESCRIPTION", errorMsg);
1084
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001085 createPEL(additionalData, PelSeverity::ERROR,
1086 errIntfForInvalidVPD, nullptr);
1087
1088 continue;
1089 }
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001090 }
1091
1092 Binary backupDataInBinary(backupValue.begin(),
1093 backupValue.end());
1094
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -06001095 Binary kwdDataInBinary(kwdValue.begin(), kwdValue.end());
Sunny Srivastavaa559c2d2022-05-02 11:56:45 -05001096
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001097 if (backupDataInBinary != defaultValue)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001098 {
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -06001099 if (kwdDataInBinary != defaultValue)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001100 {
1101 // both the data are present, check for mismatch
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001102 if (backupValue != kwdValue)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001103 {
Priyanga Ramasamy24942232023-01-05 04:54:59 -06001104 string errMsg = "Mismatch found between backup "
1105 "and primary VPD for record: ";
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001106 errMsg += (*it).first;
1107 errMsg += " and keyword: ";
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001108 errMsg += keywordName;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001109
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301110 std::ostringstream busStream;
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001111 for (uint16_t byte : backupValue)
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301112 {
Patrick Williams08dc31c2024-08-16 15:21:06 -04001113 busStream
1114 << std::setfill('0') << std::setw(2)
1115 << std::hex << "0x" << byte << " ";
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301116 }
1117
1118 std::ostringstream vpdStream;
1119 for (uint16_t byte : kwdValue)
1120 {
Patrick Williams08dc31c2024-08-16 15:21:06 -04001121 vpdStream
1122 << std::setfill('0') << std::setw(2)
1123 << std::hex << "0x" << byte << " ";
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301124 }
1125
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001126 // data mismatch
1127 PelAdditionalData additionalData;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001128
1129 additionalData.emplace("DESCRIPTION", errMsg);
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301130 additionalData.emplace(
Priyanga Ramasamy24942232023-01-05 04:54:59 -06001131 "Value read from Backup: ",
1132 busStream.str());
1133 additionalData.emplace(
1134 "Value read from Primary: ",
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301135 vpdStream.str());
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001136
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001137 createPEL(additionalData, PelSeverity::WARNING,
Priyanga Ramasamy24942232023-01-05 04:54:59 -06001138 errIntfForVPDMismatch, nullptr);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001139
1140 if (!isBackupOnCache)
1141 {
1142 // Backing up or restoring from a hardware
1143 // path does not requires copying the backup
1144 // data to the VPD map, as this will result
1145 // in a mismatch between the primary VPD and
1146 // its cache.
1147 continue;
1148 }
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001149 }
Sunny Srivastava37992a62023-07-11 05:18:41 -05001150 else
1151 {
1152 // both the backup and primary data is
1153 // non-default and same. Nothing needs to be
1154 // done.
1155 continue;
1156 }
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001157 }
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001158
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001159 // If the backup is on the cache we need to copy the
1160 // backup data to the VPD map to ensure there is no
Manojkiran Edaaf921752024-06-17 15:10:21 +05301161 // mismatch b/n them. So if backup data is not default,
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001162 // then irrespective of primary data(default or other
1163 // than backup), copy the backup data to vpd map as we
1164 // don't need to change the backup data in either case
1165 // in the process of restoring system vpd.
1166 kwdValue = backupValue;
1167
1168 // If the backup data is on the base panel the restoring
1169 // of Backup VPD on to the system backplane VPD
1170 // file is done here not through the VPD manager code
1171 // path. This is to have the logic of restoring data on
1172 // to the cache & hardware in the same code path.
1173 if (!isBackupOnCache)
1174 {
1175 // copy backup VPD on to system backplane
1176 // EEPROM file.
1177 updateVpdDataOnHw(systemVpdFilePath, js, recordName,
1178 keywordName, backupDataInBinary);
1179 }
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001180 }
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -06001181 else if (kwdDataInBinary == defaultValue &&
1182 get<2>(keywordInfo)) // Check isPELRequired is true
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001183 {
Priyanga Ramasamy24942232023-01-05 04:54:59 -06001184 string errMsg = "Found default value on both backup "
1185 "and primary VPD for record: ";
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001186 errMsg += (*it).first;
1187 errMsg += " and keyword: ";
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001188 errMsg += keywordName;
Sunny Srivastava37992a62023-07-11 05:18:41 -05001189 errMsg += ". Update primary VPD.";
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001190
Priyanga Ramasamy24942232023-01-05 04:54:59 -06001191 // mfg default on both backup and primary, log PEL
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001192 PelAdditionalData additionalData;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001193 additionalData.emplace("DESCRIPTION", errMsg);
1194
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001195 createPEL(additionalData, PelSeverity::ERROR,
Priyanga Ramasamy24942232023-01-05 04:54:59 -06001196 errIntfForVPDDefault, nullptr);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001197
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001198 continue;
1199 }
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001200 else if ((kwdDataInBinary != defaultValue) &&
1201 (!isBackupOnCache))
1202 {
1203 // update primary VPD on to backup VPD file
1204 updateVpdDataOnHw(systemVpdBackupPath, js,
1205 backupVpdRecName, backupVpdKwName,
1206 kwdDataInBinary);
1207
1208 // copy primary VPD to backup VPD to publish on
1209 // DBus
1210 backupVpdMap.find(backupVpdRecName)
1211 ->second.find(backupVpdKwName)
1212 ->second = kwdValue;
1213 }
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001214 }
1215 }
1216 }
1217 }
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001218}
1219
1220/**
alpana077ce68722021-07-25 13:23:59 -05001221 * @brief This checks for is this FRU a processor
1222 * And if yes, then checks for is this primary
1223 *
1224 * @param[in] js- vpd json to get the information about this FRU
1225 * @param[in] filePath- FRU vpd
1226 *
1227 * @return true/false
1228 */
1229bool isThisPrimaryProcessor(nlohmann::json& js, const string& filePath)
1230{
1231 bool isProcessor = false;
1232 bool isPrimary = false;
1233
1234 for (const auto& item : js["frus"][filePath])
1235 {
1236 if (item.find("extraInterfaces") != item.end())
1237 {
1238 for (const auto& eI : item["extraInterfaces"].items())
1239 {
1240 if (eI.key().find("Inventory.Item.Cpu") != string::npos)
1241 {
1242 isProcessor = true;
1243 }
1244 }
1245 }
1246
1247 if (isProcessor)
1248 {
1249 string cpuType = item.value("cpuType", "");
1250 if (cpuType == "primary")
1251 {
1252 isPrimary = true;
1253 }
1254 }
1255 }
1256
1257 return (isProcessor && isPrimary);
1258}
1259
1260/**
1261 * @brief This finds DIMM vpd in vpd json and enables them by binding the device
1262 * driver
1263 * @param[in] js- vpd json to iterate through and take action if it is DIMM
1264 */
1265void doEnableAllDimms(nlohmann::json& js)
1266{
1267 // iterate over each fru
1268 for (const auto& eachFru : js["frus"].items())
1269 {
1270 // skip the driver binding if eeprom already exists
1271 if (fs::exists(eachFru.key()))
1272 {
1273 continue;
1274 }
1275
1276 for (const auto& eachInventory : eachFru.value())
1277 {
1278 if (eachInventory.find("extraInterfaces") != eachInventory.end())
1279 {
1280 for (const auto& eI : eachInventory["extraInterfaces"].items())
1281 {
1282 if (eI.key().find("Inventory.Item.Dimm") != string::npos)
1283 {
1284 string dimmVpd = eachFru.key();
1285 // fetch it from
1286 // "/sys/bus/i2c/drivers/at24/414-0050/eeprom"
1287
1288 regex matchPatern("([0-9]+-[0-9]{4})");
1289 smatch matchFound;
1290 if (regex_search(dimmVpd, matchFound, matchPatern))
1291 {
1292 vector<string> i2cReg;
1293 boost::split(i2cReg, matchFound.str(0),
1294 boost::is_any_of("-"));
1295
Manojkiran Edaaf921752024-06-17 15:10:21 +05301296 // remove 0s from beginning
alpana077ce68722021-07-25 13:23:59 -05001297 const regex pattern("^0+(?!$)");
1298 for (auto& i : i2cReg)
1299 {
1300 i = regex_replace(i, pattern, "");
1301 }
1302
Jinu Joy Thomas63cce0f2024-01-29 00:47:47 -06001303 // For ISDIMM which uses ee1004 driver
1304 // the below is done
1305 size_t stringFound = dimmVpd.find("ee1004");
1306 if (stringFound != string::npos)
1307 {
1308 // echo ee1004 0x50 >
1309 // /sys/bus/i2c/devices/i2c-110/new_device
1310 string cmnd = "echo ee1004 0x" + i2cReg[1] +
1311 " > /sys/bus/i2c/devices/i2c-" +
1312 i2cReg[0] + "/new_device";
1313 executeCmd(cmnd);
1314 }
1315 else if (i2cReg.size() == 2)
alpana077ce68722021-07-25 13:23:59 -05001316 {
1317 // echo 24c32 0x50 >
1318 // /sys/bus/i2c/devices/i2c-16/new_device
1319 string cmnd = "echo 24c32 0x" + i2cReg[1] +
1320 " > /sys/bus/i2c/devices/i2c-" +
1321 i2cReg[0] + "/new_device";
alpana077ce68722021-07-25 13:23:59 -05001322 executeCmd(cmnd);
1323 }
1324 }
1325 }
1326 }
1327 }
1328 }
1329 }
1330}
1331
1332/**
Priyanga Ramasamy6abdeb62022-01-09 23:15:11 -06001333 * @brief Check if the given CPU is an IO only chip.
1334 * The CPU is termed as IO, whose all of the cores are bad and can never be
1335 * used. Those CPU chips can be used for IO purpose like connecting PCIe devices
1336 * etc., The CPU whose every cores are bad, can be identified from the CP00
1337 * record's PG keyword, only if all of the 8 EQs' value equals 0xE7F9FF. (1EQ
1338 * has 4 cores grouped together by sharing its cache memory.)
1339 * @param [in] pgKeyword - PG Keyword of CPU.
1340 * @return true if the given cpu is an IO, false otherwise.
1341 */
1342static bool isCPUIOGoodOnly(const string& pgKeyword)
1343{
1344 const unsigned char io[] = {0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9,
1345 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7,
1346 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF};
1347 // EQ0 index (in PG keyword) starts at 97 (with offset starting from 0).
1348 // Each EQ carries 3 bytes of data. Totally there are 8 EQs. If all EQs'
1349 // value equals 0xE7F9FF, then the cpu has no good cores and its treated as
1350 // IO.
1351 if (memcmp(io, pgKeyword.data() + 97, 24) == 0)
1352 {
1353 return true;
1354 }
1355
1356 // The CPU is not an IO
1357 return false;
1358}
1359
1360/**
Jinu Joy Thomas9a60c8b2024-01-16 22:52:25 -06001361 * @brief Function to bring MUX out of idle state
1362 *
1363 * This finds All the MUX defined in the system json and enables
1364 * them by setting the holdidle parameter to 0.
1365 * @param[in] js- system json to iterate through and take action
1366 */
1367void doEnableAllMuxChips(const nlohmann::json& js)
1368{
1369 // Do we have the mandatory "muxes" section?
1370 if (js.find("muxes") != js.end())
1371 {
1372 std::cout << "Enabling all the MUX on the system " << std::endl;
1373 // iterate over each MUX detail and enable them
1374 for (const auto& item : js["muxes"])
1375 {
1376 if (item.find("holdidlepath") != item.end())
1377 {
Jinu Joy Thomas63cce0f2024-01-29 00:47:47 -06001378 const std::string& holdidle = item["holdidlepath"];
Jinu Joy Thomas9a60c8b2024-01-16 22:52:25 -06001379 std::cout << "Setting holdidle state for " << holdidle
1380 << "to 0 " << std::endl;
1381 string cmd = "echo 0 > " + holdidle;
1382 executeCmd(cmd);
1383 }
1384 }
1385 std::cout << "Completed enabling all the MUX on the system "
1386 << std::endl;
1387 }
1388 else
1389 {
1390 std::cout << "No MUX was defined for the system" << std::endl;
1391 }
1392}
1393
1394/**
PriyangaRamasamy8e140a12020-04-13 19:24:03 +05301395 * @brief Populate Dbus.
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301396 * This method invokes all the populateInterface functions
1397 * and notifies PIM about dbus object.
PriyangaRamasamy8e140a12020-04-13 19:24:03 +05301398 * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
1399 * input.
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301400 * @param[in] js - Inventory json object
1401 * @param[in] filePath - Path of the vpd file
1402 * @param[in] preIntrStr - Interface string
1403 */
1404template <typename T>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001405static void populateDbus(T& vpdMap, nlohmann::json& js, const string& filePath)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301406{
1407 inventory::InterfaceMap interfaces;
1408 inventory::ObjectMap objects;
1409 inventory::PropertyMap prop;
Shantappa Teekappanavar6aa54502021-12-09 12:59:56 -06001410 string ccinFromVpd;
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301411
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301412 bool isSystemVpd = (filePath == systemVpdFilePath);
1413 if constexpr (is_same<T, Parsed>::value)
1414 {
Shantappa Teekappanavar6aa54502021-12-09 12:59:56 -06001415 ccinFromVpd = getKwVal(vpdMap, "VINI", "CC");
1416 transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
1417 ::toupper);
1418
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301419 if (isSystemVpd)
1420 {
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301421 string mboardPath =
1422 js["frus"][filePath].at(0).value("inventoryPath", "");
1423
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001424 // Get the value of systemvpdBackupPath field from json
1425 const std::string& systemVpdBackupPath =
1426 js["frus"][filePath].at(0).value("systemVpdBackupPath", "");
1427
1428 if (systemVpdBackupPath.empty())
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301429 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001430 std::vector<std::string> interfaces = {motherBoardInterface};
1431 // call mapper to check for object path creation
1432 MapperResponse subTree =
1433 getObjectSubtreeForInterfaces(pimPath, 0, interfaces);
1434
1435 // Attempt system VPD restore if we have a motherboard
1436 // object in the inventory.
1437 if ((subTree.size() != 0) &&
1438 (subTree.find(pimPath + mboardPath) != subTree.end()))
1439 {
1440 restoreSystemVPD(vpdMap, mboardPath, js);
1441 }
1442 else
1443 {
1444 log<level::ERR>("No object path found");
1445 }
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301446 }
1447 else
1448 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001449 restoreSystemVPD(vpdMap, mboardPath, js, false);
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301450 }
1451 }
alpana077ce68722021-07-25 13:23:59 -05001452 else
1453 {
1454 // check if it is processor vpd.
1455 auto isPrimaryCpu = isThisPrimaryProcessor(js, filePath);
1456
1457 if (isPrimaryCpu)
1458 {
1459 auto ddVersion = getKwVal(vpdMap, "CRP0", "DD");
1460
1461 auto chipVersion = atoi(ddVersion.substr(1, 2).c_str());
1462
1463 if (chipVersion >= 2)
1464 {
1465 doEnableAllDimms(js);
Santosh Puranik253fbe92022-10-06 22:38:09 +05301466 // Sleep for a few seconds to let the DIMM parses start
1467 using namespace std::chrono_literals;
1468 std::this_thread::sleep_for(5s);
alpana077ce68722021-07-25 13:23:59 -05001469 }
1470 }
1471 }
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301472 }
1473
Santosh Puranikf3e69682022-03-31 17:52:38 +05301474 auto processFactoryReset = false;
1475
Priyanga Ramasamy32c687f2022-01-04 23:14:03 -06001476 if (isSystemVpd)
1477 {
1478 string systemJsonName{};
1479 if constexpr (is_same<T, Parsed>::value)
1480 {
1481 // pick the right system json
1482 systemJsonName = getSystemsJson(vpdMap);
1483 }
1484
1485 fs::path target = systemJsonName;
1486 fs::path link = INVENTORY_JSON_SYM_LINK;
1487
Santosh Puranikf3e69682022-03-31 17:52:38 +05301488 // If the symlink does not exist, we treat that as a factory reset
1489 processFactoryReset = !fs::exists(INVENTORY_JSON_SYM_LINK);
1490
Priyanga Ramasamy32c687f2022-01-04 23:14:03 -06001491 // Create the directory for hosting the symlink
1492 fs::create_directories(VPD_FILES_PATH);
1493 // unlink the symlink previously created (if any)
1494 remove(INVENTORY_JSON_SYM_LINK);
1495 // create a new symlink based on the system
1496 fs::create_symlink(target, link);
1497
1498 // Reloading the json
1499 ifstream inventoryJson(link);
1500 js = json::parse(inventoryJson);
1501 inventoryJson.close();
Sunny Srivastava7ef9c8c2024-05-03 00:57:43 -05001502
1503 // enable the muxes again here to cover the case where during first boot
1504 // after reset, system would have come up with default JSON
1505 // configuration and have skipped enabling mux at the beginning.
1506 // Default config JSON does not have mux entries.
1507 doEnableAllMuxChips(js);
Priyanga Ramasamy32c687f2022-01-04 23:14:03 -06001508 }
1509
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301510 for (const auto& item : js["frus"][filePath])
1511 {
1512 const auto& objectPath = item["inventoryPath"];
1513 sdbusplus::message::object_path object(objectPath);
SunnySrivastava19849094d4f2020-08-05 09:32:29 -05001514
Shantappa Teekappanavar6aa54502021-12-09 12:59:56 -06001515 vector<string> ccinList;
1516 if (item.find("ccin") != item.end())
1517 {
1518 for (const auto& cc : item["ccin"])
1519 {
1520 string ccin = cc;
1521 transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
1522 ccinList.push_back(ccin);
1523 }
1524 }
1525
1526 if (!ccinFromVpd.empty() && !ccinList.empty() &&
1527 (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
1528 ccinList.end()))
1529 {
1530 continue;
1531 }
1532
Priyanga Ramasamye3fed702022-01-11 01:05:32 -06001533 if ((isSystemVpd) || (item.value("noprime", false)))
Santosh Puranikd3a379a2021-08-23 19:12:59 +05301534 {
Priyanga Ramasamye3fed702022-01-11 01:05:32 -06001535 // Populate one time properties for the system VPD and its sub-frus
1536 // and for other non-primeable frus.
Santosh Puranikd3a379a2021-08-23 19:12:59 +05301537 // For the remaining FRUs, this will get handled as a part of
1538 // priming the inventory.
1539 setOneTimeProperties(objectPath, interfaces);
1540 }
1541
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301542 // Populate the VPD keywords and the common interfaces only if we
1543 // are asked to inherit that data from the VPD, else only add the
1544 // extraInterfaces.
1545 if (item.value("inherit", true))
1546 {
Alpana Kumari58e22142020-05-05 00:22:12 -05001547 if constexpr (is_same<T, Parsed>::value)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301548 {
PriyangaRamasamy8e140a12020-04-13 19:24:03 +05301549 // Each record in the VPD becomes an interface and all
1550 // keyword within the record are properties under that
1551 // interface.
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301552 for (const auto& record : vpdMap)
1553 {
1554 populateFruSpecificInterfaces(
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05001555 record.second, ipzVpdInf + record.first, interfaces);
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301556 }
1557 }
Alpana Kumari58e22142020-05-05 00:22:12 -05001558 else if constexpr (is_same<T, KeywordVpdMap>::value)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301559 {
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05001560 populateFruSpecificInterfaces(vpdMap, kwdVpdInf, interfaces);
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301561 }
Santosh Puranik88edeb62020-03-02 12:00:09 +05301562 if (js.find("commonInterfaces") != js.end())
1563 {
1564 populateInterfaces(js["commonInterfaces"], interfaces, vpdMap,
1565 isSystemVpd);
1566 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301567 }
Santosh Puranik0859eb62020-03-16 02:56:29 -05001568 else
1569 {
1570 // Check if we have been asked to inherit specific record(s)
Alpana Kumari58e22142020-05-05 00:22:12 -05001571 if constexpr (is_same<T, Parsed>::value)
Santosh Puranik0859eb62020-03-16 02:56:29 -05001572 {
1573 if (item.find("copyRecords") != item.end())
1574 {
1575 for (const auto& record : item["copyRecords"])
1576 {
1577 const string& recordName = record;
1578 if (vpdMap.find(recordName) != vpdMap.end())
1579 {
1580 populateFruSpecificInterfaces(
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05001581 vpdMap.at(recordName), ipzVpdInf + recordName,
Santosh Puranik0859eb62020-03-16 02:56:29 -05001582 interfaces);
1583 }
1584 }
1585 }
1586 }
1587 }
Santosh Puranik32c46502022-02-10 08:55:07 +05301588 // Populate interfaces and properties that are common to every FRU
1589 // and additional interface that might be defined on a per-FRU
1590 // basis.
1591 if (item.find("extraInterfaces") != item.end())
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301592 {
Santosh Puranik32c46502022-02-10 08:55:07 +05301593 populateInterfaces(item["extraInterfaces"], interfaces, vpdMap,
1594 isSystemVpd);
Priyanga Ramasamy6abdeb62022-01-09 23:15:11 -06001595 if constexpr (is_same<T, Parsed>::value)
1596 {
1597 if (item["extraInterfaces"].find(
1598 "xyz.openbmc_project.Inventory.Item.Cpu") !=
1599 item["extraInterfaces"].end())
1600 {
1601 if (isCPUIOGoodOnly(getKwVal(vpdMap, "CP00", "PG")))
1602 {
Priyanga Ramasamy2c607a92022-04-08 00:30:17 -05001603 interfaces[invItemIntf]["PrettyName"] = "IO Module";
Priyanga Ramasamy6abdeb62022-01-09 23:15:11 -06001604 }
1605 }
1606 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301607 }
Priyanga Ramasamye358acb2022-03-21 14:21:50 -05001608
1609 // embedded property(true or false) says whether the subfru is embedded
1610 // into the parent fru (or) not. VPD sets Present property only for
1611 // embedded frus. If the subfru is not an embedded FRU, the subfru may
1612 // or may not be physically present. Those non embedded frus will always
1613 // have Present=false irrespective of its physical presence or absence.
1614 // Eg: nvme drive in nvme slot is not an embedded FRU. So don't set
1615 // Present to true for such sub frus.
1616 // Eg: ethernet port is embedded into bmc card. So set Present to true
Manojkiran Edaaf921752024-06-17 15:10:21 +05301617 // for such sub frus. Also do not populate present property for embedded
Priyanga Ramasamye358acb2022-03-21 14:21:50 -05001618 // subfru which is synthesized. Currently there is no subfru which are
1619 // both embedded and synthesized. But still the case is handled here.
1620 if ((item.value("embedded", true)) &&
1621 (!item.value("synthesized", false)))
1622 {
Priyanga Ramasamyaca61372023-01-24 08:02:28 -06001623 // Check if its required to handle presence for this FRU.
1624 if (item.value("handlePresence", true))
1625 {
1626 inventory::PropertyMap presProp;
1627 presProp.emplace("Present", true);
1628 insertOrMerge(interfaces, invItemIntf, move(presProp));
1629 }
Priyanga Ramasamye358acb2022-03-21 14:21:50 -05001630 }
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -06001631
Santosh Puranikf3e69682022-03-31 17:52:38 +05301632 if constexpr (is_same<T, Parsed>::value)
1633 {
1634 // Restore asset tag, if needed
1635 if (processFactoryReset && objectPath == "/system")
1636 {
1637 fillAssetTag(interfaces, vpdMap);
1638 }
1639 }
1640
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301641 objects.emplace(move(object), move(interfaces));
1642 }
1643
PriyangaRamasamy8e140a12020-04-13 19:24:03 +05301644 if (isSystemVpd)
1645 {
1646 inventory::ObjectMap primeObject = primeInventory(js, vpdMap);
1647 objects.insert(primeObject.begin(), primeObject.end());
Alpana Kumari65b83602020-09-01 00:24:56 -05001648
Alpana Kumarif05effd2021-04-07 07:32:53 -05001649 // set the U-boot environment variable for device-tree
1650 if constexpr (is_same<T, Parsed>::value)
1651 {
Santosh Puranike5f177a2022-01-24 20:14:46 +05301652 setDevTreeEnv(fs::path(getSystemsJson(vpdMap)).filename());
Alpana Kumarif05effd2021-04-07 07:32:53 -05001653 }
PriyangaRamasamy8e140a12020-04-13 19:24:03 +05301654 }
1655
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301656 // Notify PIM
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05001657 common::utility::callPIM(move(objects));
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301658}
1659
1660int main(int argc, char** argv)
1661{
1662 int rc = 0;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001663 json js{};
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -06001664 Binary vpdVector{};
1665 string file{};
jinuthomasf457a3e2023-04-13 12:22:48 -05001666 string driver{};
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001667 // map to hold additional data in case of logging pel
1668 PelAdditionalData additionalData{};
1669
1670 // this is needed to hold base fru inventory path in case there is ECC or
1671 // vpd exception while parsing the file
1672 std::string baseFruInventoryPath = {};
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301673
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001674 // It holds the backup EEPROM file path for the system backplane's critical
1675 // data
1676 std::string systemVpdBackupPath{};
1677
1678 // It holds the inventory path of backup EEPROM file
1679 std::string backupVpdInvPath{};
1680
1681 bool isSystemVpd = false;
1682
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001683 // severity for PEL
1684 PelSeverity pelSeverity = PelSeverity::WARNING;
1685
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301686 try
1687 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001688 App app{"ibm-read-vpd - App to read IPZ/Jedec format VPD, parse it and "
1689 "store it in DBUS"};
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301690
1691 app.add_option("-f, --file", file, "File containing VPD (IPZ/KEYWORD)")
Alpana Kumari2f793042020-08-18 05:51:03 -05001692 ->required();
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301693
jinuthomasf457a3e2023-04-13 12:22:48 -05001694 app.add_option("--driver", driver,
1695 "Driver used by kernel (at24,at25,ee1004)")
1696 ->required();
1697
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301698 CLI11_PARSE(app, argc, argv);
1699
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001700 // PEL severity should be ERROR in case of any system VPD failure
1701 if (file == systemVpdFilePath)
1702 {
1703 pelSeverity = PelSeverity::ERROR;
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001704 isSystemVpd = true;
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001705 }
1706
jinuthomasf457a3e2023-04-13 12:22:48 -05001707 // Check if input file is not empty.
1708 if ((file.empty()) || (driver.empty()))
1709 {
1710 std::cerr << "Encountered empty input parameter file [" << file
1711 << "] driver [" << driver << "]" << std::endl;
1712 return 0;
1713 }
1714
1715 // Check if currently supported driver or not
1716 if ((driver != at24driver) && (driver != at25driver) &&
1717 (driver != ee1004driver))
1718 {
1719 std::cerr << "The driver [" << driver << "] is not supported."
1720 << std::endl;
1721 return 0;
1722 }
1723
Santosh Puranik0246a4d2020-11-04 16:57:39 +05301724 auto jsonToParse = INVENTORY_JSON_DEFAULT;
1725
1726 // If the symlink exists, it means it has been setup for us, switch the
1727 // path
1728 if (fs::exists(INVENTORY_JSON_SYM_LINK))
1729 {
1730 jsonToParse = INVENTORY_JSON_SYM_LINK;
1731 }
1732
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301733 // Make sure that the file path we get is for a supported EEPROM
Santosh Puranik0246a4d2020-11-04 16:57:39 +05301734 ifstream inventoryJson(jsonToParse);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001735 if (!inventoryJson)
1736 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001737 throw(VpdJsonException("Failed to access Json path", jsonToParse));
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001738 }
1739
1740 try
1741 {
1742 js = json::parse(inventoryJson);
1743 }
Patrick Williams8e15b932021-10-06 13:04:22 -05001744 catch (const json::parse_error& ex)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001745 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -05001746 throw(VpdJsonException("Json parsing failed", jsonToParse));
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001747 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301748
Santosh Puranik12e24ff2021-05-11 19:33:50 +05301749 // Do we have the mandatory "frus" section?
1750 if (js.find("frus") == js.end())
1751 {
1752 throw(VpdJsonException("FRUs section not found in JSON",
1753 jsonToParse));
1754 }
1755
Eddie James1da52fa2024-08-27 11:21:43 -05001756 // Check if it's a udev path - patterned as(/ahb/1e780000.apb/ for I2C
1757 // or /ahb/1e790000.apb/ for FSI)
1758 if (file.find("/ahb:apb") != string::npos ||
1759 file.find("/ahb/1e780000.apb") != string::npos ||
1760 file.find("/ahb/1e790000.apb") != string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +05301761 {
1762 // Translate udev path to a generic /sys/bus/.. file path.
jinuthomasf457a3e2023-04-13 12:22:48 -05001763 udevToGenericPath(file, driver);
Santosh Puranik12e24ff2021-05-11 19:33:50 +05301764
1765 if ((js["frus"].find(file) != js["frus"].end()) &&
Santosh Puranik50f60bf2021-05-26 17:55:06 +05301766 (file == systemVpdFilePath))
PriyangaRamasamy647868e2020-09-08 17:03:19 +05301767 {
Manojkiran Edaaf921752024-06-17 15:10:21 +05301768 std::cout << "We have already collected system VPD, skipping."
jinuthomasf457a3e2023-04-13 12:22:48 -05001769 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +05301770 return 0;
1771 }
1772 }
1773
Jinu Joy Thomas2cb67692024-01-30 10:30:26 -06001774 // Enable all mux which are used for connecting to the i2c on the pcie
1775 // slots for pcie cards. These are not enabled by kernel due to an issue
1776 // seen with Castello cards, where the i2c line hangs on a probe.
1777 // To run it only once have kept it under System vpd check.
1778 // we need to run this on all BMC reboots so kept here
1779 if (file == systemVpdFilePath)
1780 {
1781 doEnableAllMuxChips(js);
1782 }
1783
PriyangaRamasamy647868e2020-09-08 17:03:19 +05301784 if (file.empty())
1785 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001786 std::cerr << "The EEPROM path <" << file << "> is not valid.";
PriyangaRamasamy647868e2020-09-08 17:03:19 +05301787 return 0;
1788 }
Santosh Puranik12e24ff2021-05-11 19:33:50 +05301789 if (js["frus"].find(file) == js["frus"].end())
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301790 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001791 std::cerr << "The EEPROM path [" << file
1792 << "] is not found in the json." << std::endl;
Santosh Puranik88edeb62020-03-02 12:00:09 +05301793 return 0;
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301794 }
1795
Alpana Kumari2f793042020-08-18 05:51:03 -05001796 if (!fs::exists(file))
1797 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001798 std::cout << "Device path: " << file
1799 << " does not exist. Spurious udev event? Exiting."
1800 << std::endl;
Alpana Kumari2f793042020-08-18 05:51:03 -05001801 return 0;
1802 }
1803
Santosh Puranikdedb5a62022-12-19 23:58:32 +05301804 // In case of system VPD it will already be filled, Don't have to
1805 // overwrite that.
1806 if (baseFruInventoryPath.empty())
1807 {
1808 baseFruInventoryPath = js["frus"][file][0]["inventoryPath"];
1809 }
1810
Santosh Puranik85893752020-11-10 21:31:43 +05301811 // Check if we can read the VPD file based on the power state
Santosh Puranik27a5e952021-10-07 22:08:01 -05001812 // We skip reading VPD when the power is ON in two scenarios:
Santosh Puranik31d50fa2022-04-04 12:04:37 +05301813 // 1) The eeprom we are trying to read is that of the system VPD and the
1814 // JSON symlink is already setup (the symlink's existence tells us we
1815 // are not coming out of a factory reset)
1816 // 2) The JSON tells us that the FRU EEPROM cannot be
1817 // read when we are powered ON.
Santosh Puranik27a5e952021-10-07 22:08:01 -05001818 if (js["frus"][file].at(0).value("powerOffOnly", false) ||
Santosh Puranik31d50fa2022-04-04 12:04:37 +05301819 (file == systemVpdFilePath && fs::exists(INVENTORY_JSON_SYM_LINK)))
Santosh Puranik85893752020-11-10 21:31:43 +05301820 {
1821 if ("xyz.openbmc_project.State.Chassis.PowerState.On" ==
1822 getPowerState())
1823 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001824 std::cout << "This VPD cannot be read when power is ON"
1825 << std::endl;
Santosh Puranik85893752020-11-10 21:31:43 +05301826 return 0;
1827 }
1828 }
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001829
Santosh Puranike9c57532022-03-15 16:51:51 +05301830 // Check if this VPD should be recollected at all
1831 if (!needsRecollection(js, file))
1832 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001833 std::cout << "Skip VPD recollection for: " << file << std::endl;
Santosh Puranike9c57532022-03-15 16:51:51 +05301834 return 0;
1835 }
1836
Alpana Kumari2f793042020-08-18 05:51:03 -05001837 try
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301838 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001839 variant<KeywordVpdMap, Store> parseResult;
Sunny Srivastava37992a62023-07-11 05:18:41 -05001840 parseResult = parseVpdFile(file, js);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001841
1842 if (isSystemVpd)
girik18bb9852022-11-16 05:48:13 -06001843 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001844 // Get the value of systemVpdBackupPath field from json
1845 systemVpdBackupPath = js["frus"][systemVpdFilePath].at(0).value(
1846 "systemVpdBackupPath", "");
1847
1848 if (!systemVpdBackupPath.empty())
girik18bb9852022-11-16 05:48:13 -06001849 {
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001850 backupVpdInvPath =
1851 js["frus"][systemVpdBackupPath][0]["inventoryPath"]
1852 .get_ref<const nlohmann::json::string_t&>();
girik18bb9852022-11-16 05:48:13 -06001853 }
1854 }
SunnySrivastava19849a195542020-09-07 06:04:50 -05001855
Alpana Kumari2f793042020-08-18 05:51:03 -05001856 if (auto pVal = get_if<Store>(&parseResult))
1857 {
1858 populateDbus(pVal->getVpdMap(), js, file);
1859 }
1860 else if (auto pVal = get_if<KeywordVpdMap>(&parseResult))
1861 {
1862 populateDbus(*pVal, js, file);
1863 }
Alpana Kumari2f793042020-08-18 05:51:03 -05001864 }
Patrick Williams8e15b932021-10-06 13:04:22 -05001865 catch (const exception& e)
Alpana Kumari2f793042020-08-18 05:51:03 -05001866 {
Sunny Srivastava37992a62023-07-11 05:18:41 -05001867 if (!systemVpdBackupPath.empty())
1868 {
1869 file = systemVpdBackupPath;
1870 baseFruInventoryPath = backupVpdInvPath;
1871 }
1872
Alpana Kumari735dee92022-03-25 01:24:40 -05001873 executePostFailAction(js, file);
PriyangaRamasamya504c3e2020-12-06 12:14:52 -06001874 throw;
Alpana Kumari2f793042020-08-18 05:51:03 -05001875 }
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301876 }
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001877 catch (const VpdJsonException& ex)
1878 {
1879 additionalData.emplace("JSON_PATH", ex.getJsonPath());
1880 additionalData.emplace("DESCRIPTION", ex.what());
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -05001881 createPEL(additionalData, pelSeverity, errIntfForJsonFailure, nullptr);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001882
jinuthomasf457a3e2023-04-13 12:22:48 -05001883 std::cerr << ex.what() << "\n";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001884 rc = -1;
1885 }
1886 catch (const VpdEccException& ex)
1887 {
1888 additionalData.emplace("DESCRIPTION", "ECC check failed");
1889 additionalData.emplace("CALLOUT_INVENTORY_PATH",
1890 INVENTORY_PATH + baseFruInventoryPath);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -05001891 createPEL(additionalData, pelSeverity, errIntfForEccCheckFail, nullptr);
Kantesh Nagaradder38ee9c82023-04-07 00:58:12 -05001892
1893 if (systemVpdBackupPath.empty())
1894 {
1895 dumpBadVpd(file, vpdVector);
1896 }
1897
jinuthomasf457a3e2023-04-13 12:22:48 -05001898 std::cerr << ex.what() << "\n";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001899 rc = -1;
1900 }
1901 catch (const VpdDataException& ex)
1902 {
alpana075cb3b1f2021-12-16 11:19:36 -06001903 if (isThisPcieOnPass1planar(js, file))
1904 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001905 std::cout << "Pcie_device [" << file
1906 << "]'s VPD is not valid on PASS1 planar.Ignoring.\n";
alpana075cb3b1f2021-12-16 11:19:36 -06001907 rc = 0;
1908 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +05301909 else if (!(isPresent(js, file).value_or(true)))
1910 {
jinuthomasf457a3e2023-04-13 12:22:48 -05001911 std::cout << "FRU at: " << file
1912 << " is not detected present. Ignore parser error.\n";
Santosh Puranik53b38ed2022-04-10 23:15:22 +05301913 rc = 0;
1914 }
alpana075cb3b1f2021-12-16 11:19:36 -06001915 else
1916 {
1917 string errorMsg =
1918 "VPD file is either empty or invalid. Parser failed for [";
1919 errorMsg += file;
1920 errorMsg += "], with error = " + std::string(ex.what());
1921
1922 additionalData.emplace("DESCRIPTION", errorMsg);
1923 additionalData.emplace("CALLOUT_INVENTORY_PATH",
1924 INVENTORY_PATH + baseFruInventoryPath);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -05001925 createPEL(additionalData, pelSeverity, errIntfForInvalidVPD,
1926 nullptr);
alpana075cb3b1f2021-12-16 11:19:36 -06001927
1928 rc = -1;
1929 }
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -05001930 }
Patrick Williams8e15b932021-10-06 13:04:22 -05001931 catch (const exception& e)
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301932 {
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -06001933 dumpBadVpd(file, vpdVector);
jinuthomasf457a3e2023-04-13 12:22:48 -05001934 std::cerr << e.what() << "\n";
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +05301935 rc = -1;
1936 }
1937
1938 return rc;
Patrick Williamsc78d8872023-05-10 07:50:56 -05001939}