blob: 8a64d161108abb791f22b6cd11e0adfed5025ecc [file] [log] [blame]
Deepak Kodihalli76794492017-02-16 23:48:18 -06001#pragma once
2
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06003#include "const.hpp"
Alpana Kumarif05effd2021-04-07 07:32:53 -05004#include "store.hpp"
Deepak Kodihalli76794492017-02-16 23:48:18 -06005#include "types.hpp"
6
SunnySrivastava1984d076da82020-03-05 05:33:35 -06007#include <iostream>
Alpana Kumari735dee92022-03-25 01:24:40 -05008#include <nlohmann/json.hpp>
Santosh Puranik53b38ed2022-04-10 23:15:22 +05309#include <optional>
SunnySrivastava1984d076da82020-03-05 05:33:35 -060010
Deepak Kodihalli76794492017-02-16 23:48:18 -060011namespace openpower
12{
13namespace vpd
14{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050015
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -060016// Map which holds system vpd keywords which can be restored at standby and via
17// vpd-tool and also can be used to reset keywords to its defaults at
18// manufacturing. The list of keywords for VSYS record is as per the S0 system.
19// Should be updated for another type of systems For those keywords whose
20// default value is system specific, the default value field is left empty.
21// Record : {Keyword, Default value, Is PEL required on restore failure, Is MFG
22// reset required}
23static const inventory::SystemKeywordsMap svpdKwdMap{
24 {"VSYS",
25 {inventory::SystemKeywordInfo("BR", Binary(2, 0x20), true, true),
26 inventory::SystemKeywordInfo("TM", Binary(8, 0x20), true, true),
27 inventory::SystemKeywordInfo("SE", Binary(7, 0x20), true, true),
28 inventory::SystemKeywordInfo("SU", Binary(6, 0x20), true, true),
29 inventory::SystemKeywordInfo("RB", Binary(4, 0x20), true, true),
30 inventory::SystemKeywordInfo("WN", Binary(12, 0x20), true, true),
31 inventory::SystemKeywordInfo("RG", Binary(4, 0x20), true, true),
32 inventory::SystemKeywordInfo("FV", Binary(32, 0x20), false, true)}},
33 {"VCEN",
34 {inventory::SystemKeywordInfo("FC", Binary(), true, false),
35 inventory::SystemKeywordInfo("SE", Binary(7, 0x20), true, true)}},
36 {"LXR0", {inventory::SystemKeywordInfo("LX", Binary(), true, false)}},
37 {"UTIL",
Priyanga Ramasamy6d5c6b52023-01-27 09:06:26 -060038 {inventory::SystemKeywordInfo("D0", Binary(1, 0x00), true, true),
39 inventory::SystemKeywordInfo("F5", Binary(16, 0x00), false, true),
40 inventory::SystemKeywordInfo("F6", Binary(16, 0x00), false, true)}}};
Santosh Puranik6b2b5372022-06-02 20:49:02 +053041
Santosh Puranikbd011b22020-01-23 04:05:25 -060042/** @brief Return the hex representation of the incoming byte
43 *
44 * @param [in] c - The input byte
45 * @returns The hex representation of the byte as a character.
46 */
47constexpr auto toHex(size_t c)
48{
49 constexpr auto map = "0123456789abcdef";
50 return map[c];
51}
Deepak Kodihalli76794492017-02-16 23:48:18 -060052
53namespace inventory
54{
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -060055/** @brief API to obtain a dictionary of path -> services
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050056 * where path is in subtree and services is of the type
57 * returned by the GetObject method.
58 *
59 * @param [in] root - Root path for object subtree
60 * @param [in] depth - Maximum subtree depth required
61 * @param [in] interfaces - Array to interfaces for which
62 * result is required.
63 * @return A dictionary of Path -> services
64 */
65MapperResponse
66 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
67 const std::vector<std::string>& interfaces);
68
Deepak Kodihalli76794492017-02-16 23:48:18 -060069} // namespace inventory
70
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060071/**@brief This API reads 2 Bytes of data and swap the read data
72 * @param[in] iterator- Pointer pointing to the data to be read
73 * @return returns 2 Byte data read at the given pointer
74 */
75openpower::vpd::constants::LE2ByteData
76 readUInt16LE(Binary::const_iterator iterator);
77
SunnySrivastava1984d076da82020-03-05 05:33:35 -060078/** @brief Encodes a keyword for D-Bus.
79 * @param[in] kw - kwd data in string format
80 * @param[in] encoding - required for kwd data
81 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -050082std::string encodeKeyword(const std::string& kw, const std::string& encoding);
SunnySrivastava198443306542020-04-01 02:50:20 -050083
84/** @brief Reads a property from the inventory manager given object path,
85 * intreface and property.
86 * @param[in] obj - object path
87 * @param[in] inf - interface
88 * @param[in] prop - property whose value is fetched
89 * @return [out] - value of the property
90 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -050091std::string readBusProperty(const std::string& obj, const std::string& inf,
92 const std::string& prop);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050093
Priyanga Ramasamyf1449cd2022-07-13 04:28:30 -050094/** @brief A templated function to read D-Bus properties.
95 *
96 * @param[in] service - Service path
97 * @param[in] object - object path
98 * @param[in] inf - interface
99 * @param[in] prop - property whose value is fetched
100 * @return The property value of its own type.
101 */
102template <typename T>
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500103T readDBusProperty(const std::string& service, const std::string& object,
104 const std::string& inf, const std::string& prop)
Priyanga Ramasamyf1449cd2022-07-13 04:28:30 -0500105{
106 T retVal{};
107 try
108 {
109 auto bus = sdbusplus::bus::new_default();
110 auto properties =
111 bus.new_method_call(service.c_str(), object.c_str(),
112 "org.freedesktop.DBus.Properties", "Get");
113 properties.append(inf);
114 properties.append(prop);
115 auto result = bus.call(properties);
116 result.read(retVal);
117 }
118 catch (const sdbusplus::exception::SdBusError& e)
119 {
120 std::cerr << e.what();
121 }
122 return retVal;
123}
124
Priyanga Ramasamy43ffcf72022-06-08 14:10:11 -0500125/** @brief A templated method to get all D-Bus properties
126 *
127 * @param[in] service - Service path
128 * @param[in] object - Object path
129 * @param[in] inf - Interface
130 *
131 * @return All properties under the given interface.
132 */
133template <typename T>
134T getAllDBusProperty(const std::string& service, const std::string& object,
135 const std::string& inf)
136{
137 T retVal{};
138 try
139 {
140 auto bus = sdbusplus::bus::new_default();
141 auto allProperties =
142 bus.new_method_call(service.c_str(), object.c_str(),
143 "org.freedesktop.DBus.Properties", "GetAll");
144 allProperties.append(inf);
145
146 auto result = bus.call(allProperties);
147 result.read(retVal);
148 }
149 catch (const sdbusplus::exception::SdBusError& e)
150 {
151 std::cerr << e.what();
152 }
153 return retVal;
154}
155
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500156/**
157 * @brief API to create PEL entry
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500158 * The api makes synchronous call to phosphor-logging create api.
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500159 * @param[in] additionalData - Map holding the additional data
160 * @param[in] sev - Severity
161 * @param[in] errIntf - error interface
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500162 */
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500163void createSyncPEL(const std::map<std::string, std::string>& additionalData,
164 const constants::PelSeverity& sev,
165 const std::string& errIntf);
166
167/**
168 * @brief Api to create PEL.
169 * A wrapper api through which sync/async call to phosphor-logging create api
170 * can be made as and when required.
171 * sdBus as nullptr will result in sync call else async call will be made with
172 * just "DESCRIPTION" key/value pair in additional data.
173 * To make asyn call with more fields in additional data call
174 * "sd_bus_call_method_async" in place.
175 *
176 * @param[in] additionalData - Map of additional data.
177 * @param[in] sev - severity of the PEL.
178 * @param[in] errIntf - Error interface to be used in PEL.
179 * @param[in] sdBus - Pointer to Sd-Bus
180 */
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500181void createPEL(const std::map<std::string, std::string>& additionalData,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500182 const constants::PelSeverity& sev, const std::string& errIntf,
183 sd_bus* sdBus);
SunnySrivastava19849094d4f2020-08-05 09:32:29 -0500184
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530185/**
186 * @brief getVpdFilePath
187 * Get vpd file path corresponding to the given object path.
188 * @param[in] - json file path
189 * @param[in] - Object path
190 * @return - Vpd file path
191 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500192inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530193 const std::string& ObjPath);
194
195/**
196 * @brief isPathInJson
197 * API which checks for the presence of the given eeprom path in the given json.
198 * @param[in] - eepromPath
199 * @return - true if the eeprom is present in the json; false otherwise
200 */
201bool isPathInJson(const std::string& eepromPath);
202
203/**
204 * @brief isRecKwInDbusJson
205 * API which checks whether the given keyword under the given record is to be
206 * published on dbus or not. Checks against the keywords present in
207 * dbus_property.json.
208 * @param[in] - record name
209 * @param[in] - keyword name
210 * @return - true if the record-keyword pair is present in dbus_property.json;
211 * false otherwise.
212 */
213bool isRecKwInDbusJson(const std::string& record, const std::string& keyword);
214
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500215/**
216 * @brief Check the type of VPD.
217 *
218 * Checks the type of vpd based on the start tag.
219 * @param[in] vector - Vpd data in vector format
220 *
221 * @return enum of type vpdType
222 */
223constants::vpdType vpdTypeCheck(const Binary& vector);
224
SunnySrivastava19849a195542020-09-07 06:04:50 -0500225/*
226 * @brief This method does nothing. Just an empty function to return null
227 * at the end of variadic template args
228 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500229inline std::string getCommand()
SunnySrivastava19849a195542020-09-07 06:04:50 -0500230{
231 return "";
232}
233
234/**
235 * @brief This function to arrange all arguments to make commandy
236 * @param[in] arguments to create the command
237 * @return cmd - command string
238 */
239template <typename T, typename... Types>
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500240inline std::string getCommand(T arg1, Types... args)
SunnySrivastava19849a195542020-09-07 06:04:50 -0500241{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500242 std::string cmd = " " + arg1 + getCommand(args...);
SunnySrivastava19849a195542020-09-07 06:04:50 -0500243
244 return cmd;
245}
246
247/**
248 * @brief This API takes arguments, creates a shell command line and executes
249 * them.
250 * @param[in] arguments for command
251 * @returns output of that command
252 */
253template <typename T, typename... Types>
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500254inline std::vector<std::string> executeCmd(T&& path, Types... args)
SunnySrivastava19849a195542020-09-07 06:04:50 -0500255{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500256 std::vector<std::string> stdOutput;
257 std::array<char, 128> buffer;
SunnySrivastava19849a195542020-09-07 06:04:50 -0500258
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500259 std::string cmd = path + getCommand(args...);
SunnySrivastava19849a195542020-09-07 06:04:50 -0500260
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500261 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"),
262 pclose);
SunnySrivastava19849a195542020-09-07 06:04:50 -0500263 if (!pipe)
264 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500265 throw std::runtime_error("popen() failed!");
SunnySrivastava19849a195542020-09-07 06:04:50 -0500266 }
267 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
268 {
269 stdOutput.emplace_back(buffer.data());
270 }
271
272 return stdOutput;
273}
274
Alpana Kumarif05effd2021-04-07 07:32:53 -0500275/** @brief This API checks for IM and HW keywords, and based
276 * on these values decides which system json to be used.
277 * @param[in] vpdMap - parsed vpd
278 * @returns System json path
279 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500280std::string getSystemsJson(const Parsed& vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500281
282/** @brief Reads HW Keyword from the vpd
283 * @param[in] vpdMap - parsed vpd
284 * @returns value of HW Keyword
285 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500286const std::string getHW(const Parsed& vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500287
288/** @brief Reads IM Keyword from the vpd
289 * @param[in] vpdMap - parsed vpd
290 * @returns value of IM Keyword
291 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500292const std::string getIM(const Parsed& vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500293
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530294/** @brief Translate udev event generated path to a generic /sys/bus eeprom path
295 * @param[io] file - path generated from udev event.
296 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500297void udevToGenericPath(std::string& file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600298
299/**
300 * @brief API to generate a vpd name in some pattern.
301 * This vpd-name denotes name of the bad vpd file.
302 * For i2c eeproms - the pattern of the vpd-name will be
303 * i2c-<bus-number>-<eeprom-address>. For spi eeproms - the pattern of the
304 * vpd-name will be spi-<spi-number>.
305 *
306 * @param[in] file - file path of the vpd
307 * @return the vpd-name.
308 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500309std::string getBadVpdName(const std::string& file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600310
311/**
312 * @brief API which dumps the broken/bad vpd in a directory
313 * When the vpd is bad, this api places the bad vpd file inside
314 * "/tmp/bad-vpd" in BMC, in order to collect bad VPD data as a part of user
315 * initiated BMC dump.
316 *
317 * @param[in] file - bad vpd file path
318 * @param[in] vpdVector - bad vpd vector
319 */
320void dumpBadVpd(const std::string& file, const Binary& vpdVector);
alpana077ce68722021-07-25 13:23:59 -0500321
322/*
323 * @brief This function fetches the value for given keyword in the given record
324 * from vpd data and returns this value.
325 *
326 * @param[in] vpdMap - vpd to find out the data
327 * @param[in] rec - Record under which desired keyword exists
328 * @param[in] kwd - keyword to read the data from
329 *
330 * @returns keyword value if record/keyword combination found
331 * empty string if record or keyword is not found.
332 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500333const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
334 const std::string& kwd);
alpana077ce68722021-07-25 13:23:59 -0500335
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500336/** @brief This creates a complete command using all it's input parameters,
337 * to bind or unbind the driver.
338 * @param[in] devNameAddr - device address on that bus
339 * @param[in] busType - i2c, spi
340 * @param[in] driverType - type of driver like at24
341 * @param[in] bindOrUnbind - either bind or unbind
342 * @returns Command to bind or unbind the driver.
343 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500344inline std::string createBindUnbindDriverCmnd(const std::string& devNameAddr,
345 const std::string& busType,
346 const std::string& driverType,
347 const std::string& bindOrUnbind)
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500348{
349 return ("echo " + devNameAddr + " > /sys/bus/" + busType + "/drivers/" +
350 driverType + "/" + bindOrUnbind);
351}
352
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500353/**
354 * @brief Get Printable Value
355 *
356 * Checks if the vector value has non printable characters.
357 * Returns hex value if non printable char is found else
358 * returns ascii value.
359 *
360 * @param[in] vector - Reference of the Binary vector
361 * @return printable value - either in hex or in ascii.
362 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500363std::string getPrintableValue(const Binary& vec);
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500364
365/**
366 * @brief Convert byte array to hex string.
367 * @param[in] vec - byte array
368 * @return hexadecimal string of bytes.
369 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500370std::string byteArrayToHexString(const Binary& vec);
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500371
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600372/**
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530373 * @brief Return presence of the FRU.
374 *
375 * This API returns the presence information of the FRU corresponding to the
376 * given EEPROM. If the JSON contains no information about presence detect, this
377 * will return an empty optional. Else it will get the presence GPIO information
378 * from the JSON and return the appropriate present status.
379 * In case of GPIO find/read errors, it will return false.
380 *
381 * @param[in] json - The VPD JSON
382 * @param[in] file - EEPROM file path
383 * @return Empty optional if there is no presence info. Else returns presence
384 * based on the GPIO read.
385 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500386std::optional<bool> isPresent(const nlohmann::json& json,
387 const std::string& file);
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530388
389/**
390 * @brief Performs any pre-action needed to get the FRU setup for
391 * collection.
Alpana Kumari735dee92022-03-25 01:24:40 -0500392 *
393 * @param[in] json - json object
394 * @param[in] file - eeprom file path
395 * @return - success or failure
396 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500397bool executePreAction(const nlohmann::json& json, const std::string& file);
Alpana Kumari735dee92022-03-25 01:24:40 -0500398
399/**
400 * @brief This API will be called at the end of VPD collection to perform any
401 * post actions.
402 *
403 * @param[in] json - json object
404 * @param[in] file - eeprom file path
405 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500406void executePostFailAction(const nlohmann::json& json, const std::string& file);
Alpana Kumari735dee92022-03-25 01:24:40 -0500407
408/**
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600409 * @brief Helper function to insert or merge in map.
410 *
411 * This method checks in the given inventory::InterfaceMap if the given
412 * interface key is existing or not. If the interface key already exists, given
413 * property map is inserted into it. If the key does'nt exist then given
414 * interface and property map pair is newly created. If the property present in
415 * propertymap already exist in the InterfaceMap, then the new property value is
416 * ignored.
417 *
418 * @param[in,out] map - map object of type inventory::InterfaceMap only.
419 * @param[in] interface - Interface name.
420 * @param[in] property - new property map that needs to be emplaced.
421 */
422void insertOrMerge(inventory::InterfaceMap& map,
423 const inventory::Interface& interface,
424 inventory::PropertyMap&& property);
425
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500426/**
427 * @brief Utility API to set a D-Bus property
428 *
429 * This calls org.freedesktop.DBus.Properties;Set method with the supplied
430 * arguments
431 *
432 * @tparam T Template type of the D-Bus property
433 * @param service[in] - The D-Bus service name.
434 * @param object[in] - The D-Bus object on which the property is to be set.
435 * @param interface[in] - The D-Bus interface to which the property belongs.
436 * @param propertyName[in] - The name of the property to set.
437 * @param propertyValue[in] - The value of the property.
438 */
439template <typename T>
440void setBusProperty(const std::string& service, const std::string& object,
441 const std::string& interface,
442 const std::string& propertyName,
443 const std::variant<T>& propertyValue)
444{
445 try
446 {
447 auto bus = sdbusplus::bus::new_default();
448 auto method =
449 bus.new_method_call(service.c_str(), object.c_str(),
450 "org.freedesktop.DBus.Properties", "Set");
451 method.append(interface);
452 method.append(propertyName);
453 method.append(propertyValue);
454
455 bus.call(method);
456 }
457 catch (const sdbusplus::exception::SdBusError& e)
458 {
459 std::cerr << e.what() << std::endl;
460 }
461}
462
463/**
464 * @brief Reads BIOS Attribute by name.
465 *
466 * @param attrName[in] - The BIOS attribute name.
467 * @return std::variant<int64_t, std::string> - The BIOS attribute value.
468 */
469std::variant<int64_t, std::string>
470 readBIOSAttribute(const std::string& attrName);
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500471
472/**
473 * @brief Returns the power state for chassis0
474 * @return The chassis power state.
475 */
476std::string getPowerState();
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530477
478/**
479 * @brief Reads VPD from the supplied EEPROM
480 *
481 * This function reads the given VPD EEPROM file and returns its contents as a
482 * byte array. It handles any offsets into the file that need to be taken care
483 * of by looking up the VPD JSON for a possible offset key.
484 *
485 * @param js[in] - The VPD JSON Object
486 * @param file[in] - The path to the EEPROM to read
487 * @return A byte array containing the raw VPD.
488 */
489Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700490} // namespace vpd
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500491} // namespace openpower