xref: /openbmc/openpower-vpd-parser/vpd-tool/include/tool_utils.hpp (revision 7f749a6f3d581ec2fd573ff940f91770a6660dde)
1fa5e4d32SSunny Srivastava #pragma once
2fa5e4d32SSunny Srivastava 
3fa5e4d32SSunny Srivastava #include "tool_constants.hpp"
4fa5e4d32SSunny Srivastava #include "tool_types.hpp"
5fa5e4d32SSunny Srivastava 
6fa5e4d32SSunny Srivastava #include <nlohmann/json.hpp>
7fa5e4d32SSunny Srivastava #include <sdbusplus/bus.hpp>
8fa5e4d32SSunny Srivastava #include <sdbusplus/exception.hpp>
9fa5e4d32SSunny Srivastava 
10fa5e4d32SSunny Srivastava #include <fstream>
11fa5e4d32SSunny Srivastava #include <iostream>
12fa5e4d32SSunny Srivastava 
13fa5e4d32SSunny Srivastava namespace vpd
14fa5e4d32SSunny Srivastava {
15fa5e4d32SSunny Srivastava namespace utils
16fa5e4d32SSunny Srivastava {
17fa5e4d32SSunny Srivastava /**
18fa5e4d32SSunny Srivastava  * @brief An API to read property from Dbus.
19fa5e4d32SSunny Srivastava  *
20fa5e4d32SSunny Srivastava  * API reads the property value for the specified interface and object path from
21fa5e4d32SSunny Srivastava  * the given Dbus service.
22fa5e4d32SSunny Srivastava  *
23fa5e4d32SSunny Srivastava  * The caller of the API needs to validate the validity and correctness of the
24fa5e4d32SSunny Srivastava  * type and value of data returned. The API will just fetch and return the data
25fa5e4d32SSunny Srivastava  * without any data validation.
26fa5e4d32SSunny Srivastava  *
27fa5e4d32SSunny Srivastava  * Note: It will be caller's responsibility to check for empty value returned
28fa5e4d32SSunny Srivastava  * and generate appropriate error if required.
29fa5e4d32SSunny Srivastava  *
30fa5e4d32SSunny Srivastava  * @param[in] i_serviceName - Name of the Dbus service.
31fa5e4d32SSunny Srivastava  * @param[in] i_objectPath - Object path under the service.
32fa5e4d32SSunny Srivastava  * @param[in] i_interface - Interface under which property exist.
33fa5e4d32SSunny Srivastava  * @param[in] i_property - Property whose value is to be read.
34fa5e4d32SSunny Srivastava  *
35fa5e4d32SSunny Srivastava  * @return - Value read from Dbus.
36fa5e4d32SSunny Srivastava  *
37fa5e4d32SSunny Srivastava  * @throw std::runtime_error
38fa5e4d32SSunny Srivastava  */
readDbusProperty(const std::string & i_serviceName,const std::string & i_objectPath,const std::string & i_interface,const std::string & i_property)39fa5e4d32SSunny Srivastava inline types::DbusVariantType readDbusProperty(
40fa5e4d32SSunny Srivastava     const std::string& i_serviceName, const std::string& i_objectPath,
41fa5e4d32SSunny Srivastava     const std::string& i_interface, const std::string& i_property)
42fa5e4d32SSunny Srivastava {
43fa5e4d32SSunny Srivastava     types::DbusVariantType l_propertyValue;
44fa5e4d32SSunny Srivastava 
45fa5e4d32SSunny Srivastava     // Mandatory fields to make a dbus call.
46fa5e4d32SSunny Srivastava     if (i_serviceName.empty() || i_objectPath.empty() || i_interface.empty() ||
47fa5e4d32SSunny Srivastava         i_property.empty())
48fa5e4d32SSunny Srivastava     {
49fa5e4d32SSunny Srivastava         // TODO: Enable logging when verbose is enabled.
50fa5e4d32SSunny Srivastava         /*std::cout << "One of the parameter to make Dbus read call is empty."
51fa5e4d32SSunny Srivastava                   << std::endl;*/
52fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty Parameter");
53fa5e4d32SSunny Srivastava     }
54fa5e4d32SSunny Srivastava 
55fa5e4d32SSunny Srivastava     try
56fa5e4d32SSunny Srivastava     {
57fa5e4d32SSunny Srivastava         auto l_bus = sdbusplus::bus::new_default();
58fa5e4d32SSunny Srivastava         auto l_method =
59fa5e4d32SSunny Srivastava             l_bus.new_method_call(i_serviceName.c_str(), i_objectPath.c_str(),
60fa5e4d32SSunny Srivastava                                   "org.freedesktop.DBus.Properties", "Get");
61fa5e4d32SSunny Srivastava         l_method.append(i_interface, i_property);
62fa5e4d32SSunny Srivastava 
63fa5e4d32SSunny Srivastava         auto result = l_bus.call(l_method);
64fa5e4d32SSunny Srivastava         result.read(l_propertyValue);
65fa5e4d32SSunny Srivastava     }
66fa5e4d32SSunny Srivastava     catch (const sdbusplus::exception::SdBusError& l_ex)
67fa5e4d32SSunny Srivastava     {
68fa5e4d32SSunny Srivastava         // TODO: Enable logging when verbose is enabled.
69fa5e4d32SSunny Srivastava         // std::cout << std::string(l_ex.what()) << std::endl;
70fa5e4d32SSunny Srivastava         throw std::runtime_error(std::string(l_ex.what()));
71fa5e4d32SSunny Srivastava     }
72fa5e4d32SSunny Srivastava     return l_propertyValue;
73fa5e4d32SSunny Srivastava }
74fa5e4d32SSunny Srivastava 
75fa5e4d32SSunny Srivastava /**
76a8bb1663SSouvik Roy  * @brief An API to get property map for an interface.
77a8bb1663SSouvik Roy  *
78a8bb1663SSouvik Roy  * This API returns a map of property and its value with respect to a particular
79a8bb1663SSouvik Roy  * interface.
80a8bb1663SSouvik Roy  *
81a8bb1663SSouvik Roy  * Note: It will be caller's responsibility to check for empty map returned and
82a8bb1663SSouvik Roy  * generate appropriate error.
83a8bb1663SSouvik Roy  *
84a8bb1663SSouvik Roy  * @param[in] i_service - Service name.
85a8bb1663SSouvik Roy  * @param[in] i_objectPath - object path.
86a8bb1663SSouvik Roy  * @param[in] i_interface - Interface, for the properties to be listed.
87a8bb1663SSouvik Roy  *
88a8bb1663SSouvik Roy  * @return - A map of property and value of an interface, if success.
89a8bb1663SSouvik Roy  *           if failed, empty map.
90a8bb1663SSouvik Roy  */
getPropertyMap(const std::string & i_service,const std::string & i_objectPath,const std::string & i_interface)91a8bb1663SSouvik Roy inline types::PropertyMap getPropertyMap(
92a8bb1663SSouvik Roy     const std::string& i_service, const std::string& i_objectPath,
93a8bb1663SSouvik Roy     const std::string& i_interface) noexcept
94a8bb1663SSouvik Roy {
95a8bb1663SSouvik Roy     types::PropertyMap l_propertyValueMap;
96a8bb1663SSouvik Roy     if (i_service.empty() || i_objectPath.empty() || i_interface.empty())
97a8bb1663SSouvik Roy     {
98a8bb1663SSouvik Roy         // TODO: Enable logging when verbose is enabled.
99a8bb1663SSouvik Roy         // std::cout << "Invalid parameters to get property map" << std::endl;
100a8bb1663SSouvik Roy         return l_propertyValueMap;
101a8bb1663SSouvik Roy     }
102a8bb1663SSouvik Roy 
103a8bb1663SSouvik Roy     try
104a8bb1663SSouvik Roy     {
105a8bb1663SSouvik Roy         auto l_bus = sdbusplus::bus::new_default();
106a8bb1663SSouvik Roy         auto l_method =
107a8bb1663SSouvik Roy             l_bus.new_method_call(i_service.c_str(), i_objectPath.c_str(),
108a8bb1663SSouvik Roy                                   "org.freedesktop.DBus.Properties", "GetAll");
109a8bb1663SSouvik Roy         l_method.append(i_interface);
110a8bb1663SSouvik Roy         auto l_result = l_bus.call(l_method);
111a8bb1663SSouvik Roy         l_result.read(l_propertyValueMap);
112a8bb1663SSouvik Roy     }
113a8bb1663SSouvik Roy     catch (const sdbusplus::exception::SdBusError& l_ex)
114a8bb1663SSouvik Roy     {
115a8bb1663SSouvik Roy         // TODO: Enable logging when verbose is enabled.
116a8bb1663SSouvik Roy         // std::cerr << "Failed to get property map for service: [" << i_service
117a8bb1663SSouvik Roy         //           << "], object path: [" << i_objectPath
118a8bb1663SSouvik Roy         //           << "] Error : " << l_ex.what() << std::endl;
119a8bb1663SSouvik Roy     }
120a8bb1663SSouvik Roy 
121a8bb1663SSouvik Roy     return l_propertyValueMap;
122a8bb1663SSouvik Roy }
123a8bb1663SSouvik Roy 
124a8bb1663SSouvik Roy /**
125fa5e4d32SSunny Srivastava  * @brief An API to print json data on stdout.
126fa5e4d32SSunny Srivastava  *
127fa5e4d32SSunny Srivastava  * @param[in] i_jsonData - JSON object.
128fa5e4d32SSunny Srivastava  */
printJson(const nlohmann::json & i_jsonData)129fa5e4d32SSunny Srivastava inline void printJson(const nlohmann::json& i_jsonData)
130fa5e4d32SSunny Srivastava {
131fa5e4d32SSunny Srivastava     try
132fa5e4d32SSunny Srivastava     {
133fa5e4d32SSunny Srivastava         std::cout << i_jsonData.dump(constants::INDENTATION) << std::endl;
134fa5e4d32SSunny Srivastava     }
135fa5e4d32SSunny Srivastava     catch (const nlohmann::json::type_error& l_ex)
136fa5e4d32SSunny Srivastava     {
137fa5e4d32SSunny Srivastava         throw std::runtime_error(
138fa5e4d32SSunny Srivastava             "Failed to dump JSON data, error: " + std::string(l_ex.what()));
139fa5e4d32SSunny Srivastava     }
140fa5e4d32SSunny Srivastava }
141fa5e4d32SSunny Srivastava 
142fa5e4d32SSunny Srivastava /**
143fa5e4d32SSunny Srivastava  * @brief An API to convert binary value into ascii/hex representation.
144fa5e4d32SSunny Srivastava  *
145fa5e4d32SSunny Srivastava  * If given data contains printable characters, ASCII formated string value of
146fa5e4d32SSunny Srivastava  * the input data will be returned. Otherwise if the data has any non-printable
147fa5e4d32SSunny Srivastava  * value, returns the hex represented value of the given data in string format.
148fa5e4d32SSunny Srivastava  *
149fa5e4d32SSunny Srivastava  * @param[in] i_keywordValue - Data in binary format.
150fa5e4d32SSunny Srivastava  *
151fa5e4d32SSunny Srivastava  * @throw - Throws std::bad_alloc or std::terminate in case of error.
152fa5e4d32SSunny Srivastava  *
153fa5e4d32SSunny Srivastava  * @return - Returns the converted string value.
154fa5e4d32SSunny Srivastava  */
getPrintableValue(const types::BinaryVector & i_keywordValue)155fa5e4d32SSunny Srivastava inline std::string getPrintableValue(const types::BinaryVector& i_keywordValue)
156fa5e4d32SSunny Srivastava {
157fa5e4d32SSunny Srivastava     bool l_allPrintable =
158fa5e4d32SSunny Srivastava         std::all_of(i_keywordValue.begin(), i_keywordValue.end(),
159fa5e4d32SSunny Srivastava                     [](const auto& l_byte) { return std::isprint(l_byte); });
160fa5e4d32SSunny Srivastava 
161fa5e4d32SSunny Srivastava     std::ostringstream l_oss;
162fa5e4d32SSunny Srivastava     if (l_allPrintable)
163fa5e4d32SSunny Srivastava     {
164fa5e4d32SSunny Srivastava         l_oss << std::string(i_keywordValue.begin(), i_keywordValue.end());
165fa5e4d32SSunny Srivastava     }
166fa5e4d32SSunny Srivastava     else
167fa5e4d32SSunny Srivastava     {
168fa5e4d32SSunny Srivastava         l_oss << "0x";
169fa5e4d32SSunny Srivastava         for (const auto& l_byte : i_keywordValue)
170fa5e4d32SSunny Srivastava         {
171fa5e4d32SSunny Srivastava             l_oss << std::setfill('0') << std::setw(2) << std::hex
172fa5e4d32SSunny Srivastava                   << static_cast<int>(l_byte);
173fa5e4d32SSunny Srivastava         }
174fa5e4d32SSunny Srivastava     }
175fa5e4d32SSunny Srivastava 
176fa5e4d32SSunny Srivastava     return l_oss.str();
177fa5e4d32SSunny Srivastava }
178fa5e4d32SSunny Srivastava 
179fa5e4d32SSunny Srivastava /**
180fa5e4d32SSunny Srivastava  * @brief API to read keyword's value from hardware.
181fa5e4d32SSunny Srivastava  *
182fa5e4d32SSunny Srivastava  * This API reads keyword's value by requesting DBus service(vpd-manager) who
183fa5e4d32SSunny Srivastava  * hosts the 'ReadKeyword' method to read keyword's value.
184fa5e4d32SSunny Srivastava  *
185fa5e4d32SSunny Srivastava  * @param[in] i_eepromPath - EEPROM file path.
186fa5e4d32SSunny Srivastava  * @param[in] i_paramsToReadData - Property whose value has to be read.
187fa5e4d32SSunny Srivastava  *
188fa5e4d32SSunny Srivastava  * @return - Value read from hardware
189fa5e4d32SSunny Srivastava  *
190fa5e4d32SSunny Srivastava  * @throw std::runtime_error, sdbusplus::exception::SdBusError
191fa5e4d32SSunny Srivastava  */
readKeywordFromHardware(const std::string & i_eepromPath,const types::ReadVpdParams i_paramsToReadData)19243fedabcSPatrick Williams inline types::DbusVariantType readKeywordFromHardware(
19343fedabcSPatrick Williams     const std::string& i_eepromPath,
194fa5e4d32SSunny Srivastava     const types::ReadVpdParams i_paramsToReadData)
195fa5e4d32SSunny Srivastava {
196fa5e4d32SSunny Srivastava     if (i_eepromPath.empty())
197fa5e4d32SSunny Srivastava     {
198fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty EEPROM path");
199fa5e4d32SSunny Srivastava     }
200fa5e4d32SSunny Srivastava 
201fa5e4d32SSunny Srivastava     try
202fa5e4d32SSunny Srivastava     {
203fa5e4d32SSunny Srivastava         types::DbusVariantType l_propertyValue;
204fa5e4d32SSunny Srivastava 
205fa5e4d32SSunny Srivastava         auto l_bus = sdbusplus::bus::new_default();
206fa5e4d32SSunny Srivastava 
207fa5e4d32SSunny Srivastava         auto l_method = l_bus.new_method_call(
208fa5e4d32SSunny Srivastava             constants::vpdManagerService, constants::vpdManagerObjectPath,
209fa5e4d32SSunny Srivastava             constants::vpdManagerInfName, "ReadKeyword");
210fa5e4d32SSunny Srivastava 
211fa5e4d32SSunny Srivastava         l_method.append(i_eepromPath, i_paramsToReadData);
212fa5e4d32SSunny Srivastava         auto l_result = l_bus.call(l_method);
213fa5e4d32SSunny Srivastava 
214fa5e4d32SSunny Srivastava         l_result.read(l_propertyValue);
215fa5e4d32SSunny Srivastava 
216fa5e4d32SSunny Srivastava         return l_propertyValue;
217fa5e4d32SSunny Srivastava     }
218fa5e4d32SSunny Srivastava     catch (const sdbusplus::exception::SdBusError& l_error)
219fa5e4d32SSunny Srivastava     {
220fa5e4d32SSunny Srivastava         throw;
221fa5e4d32SSunny Srivastava     }
222fa5e4d32SSunny Srivastava }
223fa5e4d32SSunny Srivastava 
224fa5e4d32SSunny Srivastava /**
225fa5e4d32SSunny Srivastava  * @brief API to save keyword's value on file.
226fa5e4d32SSunny Srivastava  *
227fa5e4d32SSunny Srivastava  * API writes keyword's value on the given file path. If the data is in hex
228fa5e4d32SSunny Srivastava  * format, API strips '0x' and saves the value on the given file.
229fa5e4d32SSunny Srivastava  *
230fa5e4d32SSunny Srivastava  * @param[in] i_filePath - File path.
231fa5e4d32SSunny Srivastava  * @param[in] i_keywordValue - Keyword's value.
232fa5e4d32SSunny Srivastava  *
233fa5e4d32SSunny Srivastava  * @return - true on successfully writing to file, false otherwise.
234fa5e4d32SSunny Srivastava  */
saveToFile(const std::string & i_filePath,const std::string & i_keywordValue)235fa5e4d32SSunny Srivastava inline bool saveToFile(const std::string& i_filePath,
236fa5e4d32SSunny Srivastava                        const std::string& i_keywordValue)
237fa5e4d32SSunny Srivastava {
238fa5e4d32SSunny Srivastava     bool l_returnStatus = false;
239fa5e4d32SSunny Srivastava 
240fa5e4d32SSunny Srivastava     if (i_keywordValue.empty())
241fa5e4d32SSunny Srivastava     {
242fa5e4d32SSunny Srivastava         // ToDo: log only when verbose is enabled
243fa5e4d32SSunny Srivastava         std::cerr << "Save to file[ " << i_filePath
244fa5e4d32SSunny Srivastava                   << "] failed, reason: Empty keyword's value received"
245fa5e4d32SSunny Srivastava                   << std::endl;
246fa5e4d32SSunny Srivastava         return l_returnStatus;
247fa5e4d32SSunny Srivastava     }
248fa5e4d32SSunny Srivastava 
249fa5e4d32SSunny Srivastava     std::string l_keywordValue{i_keywordValue};
250fa5e4d32SSunny Srivastava     if (i_keywordValue.substr(0, 2).compare("0x") == constants::STR_CMP_SUCCESS)
251fa5e4d32SSunny Srivastava     {
252fa5e4d32SSunny Srivastava         l_keywordValue = i_keywordValue.substr(2);
253fa5e4d32SSunny Srivastava     }
254fa5e4d32SSunny Srivastava 
255fa5e4d32SSunny Srivastava     std::ofstream l_outPutFileStream;
256fa5e4d32SSunny Srivastava     l_outPutFileStream.exceptions(
257fa5e4d32SSunny Srivastava         std::ifstream::badbit | std::ifstream::failbit);
258fa5e4d32SSunny Srivastava     try
259fa5e4d32SSunny Srivastava     {
260fa5e4d32SSunny Srivastava         l_outPutFileStream.open(i_filePath);
261fa5e4d32SSunny Srivastava 
262fa5e4d32SSunny Srivastava         if (l_outPutFileStream.is_open())
263fa5e4d32SSunny Srivastava         {
264fa5e4d32SSunny Srivastava             l_outPutFileStream.write(l_keywordValue.c_str(),
265fa5e4d32SSunny Srivastava                                      l_keywordValue.size());
266fa5e4d32SSunny Srivastava             l_returnStatus = true;
267fa5e4d32SSunny Srivastava         }
268fa5e4d32SSunny Srivastava         else
269fa5e4d32SSunny Srivastava         {
270fa5e4d32SSunny Srivastava             // ToDo: log only when verbose is enabled
271fa5e4d32SSunny Srivastava             std::cerr << "Error opening output file " << i_filePath
272fa5e4d32SSunny Srivastava                       << std::endl;
273fa5e4d32SSunny Srivastava         }
274fa5e4d32SSunny Srivastava     }
275fa5e4d32SSunny Srivastava     catch (const std::ios_base::failure& l_ex)
276fa5e4d32SSunny Srivastava     {
277fa5e4d32SSunny Srivastava         // ToDo: log only when verbose is enabled
278fa5e4d32SSunny Srivastava         std::cerr
279fa5e4d32SSunny Srivastava             << "Failed to write to file: " << i_filePath
280fa5e4d32SSunny Srivastava             << ", either base folder path doesn't exist or internal error occured, error: "
281fa5e4d32SSunny Srivastava             << l_ex.what() << '\n';
282fa5e4d32SSunny Srivastava     }
283fa5e4d32SSunny Srivastava 
284fa5e4d32SSunny Srivastava     return l_returnStatus;
285fa5e4d32SSunny Srivastava }
286fa5e4d32SSunny Srivastava 
287fa5e4d32SSunny Srivastava /**
288fa5e4d32SSunny Srivastava  * @brief API to print data in JSON format on console
289fa5e4d32SSunny Srivastava  *
290fa5e4d32SSunny Srivastava  * @param[in] i_fruPath - FRU path.
291fa5e4d32SSunny Srivastava  * @param[in] i_keywordName - Keyword name.
292fa5e4d32SSunny Srivastava  * @param[in] i_keywordStrValue - Keyword's value.
293fa5e4d32SSunny Srivastava  */
displayOnConsole(const std::string & i_fruPath,const std::string & i_keywordName,const std::string & i_keywordStrValue)294fa5e4d32SSunny Srivastava inline void displayOnConsole(const std::string& i_fruPath,
295fa5e4d32SSunny Srivastava                              const std::string& i_keywordName,
296fa5e4d32SSunny Srivastava                              const std::string& i_keywordStrValue)
297fa5e4d32SSunny Srivastava {
298fa5e4d32SSunny Srivastava     nlohmann::json l_resultInJson = nlohmann::json::object({});
299fa5e4d32SSunny Srivastava     nlohmann::json l_keywordValInJson = nlohmann::json::object({});
300fa5e4d32SSunny Srivastava 
301fa5e4d32SSunny Srivastava     l_keywordValInJson.emplace(i_keywordName, i_keywordStrValue);
302fa5e4d32SSunny Srivastava     l_resultInJson.emplace(i_fruPath, l_keywordValInJson);
303fa5e4d32SSunny Srivastava 
304fa5e4d32SSunny Srivastava     printJson(l_resultInJson);
305fa5e4d32SSunny Srivastava }
306fa5e4d32SSunny Srivastava 
307fa5e4d32SSunny Srivastava /**
308fa5e4d32SSunny Srivastava  * @brief API to write keyword's value.
309fa5e4d32SSunny Srivastava  *
310fa5e4d32SSunny Srivastava  * This API writes keyword's value by requesting DBus service(vpd-manager) who
311fa5e4d32SSunny Srivastava  * hosts the 'UpdateKeyword' method to update keyword's value.
312fa5e4d32SSunny Srivastava  *
313fa5e4d32SSunny Srivastava  * @param[in] i_vpdPath - EEPROM or object path, where keyword is present.
314fa5e4d32SSunny Srivastava  * @param[in] i_paramsToWriteData - Data required to update keyword's value.
315fa5e4d32SSunny Srivastava  *
316fa5e4d32SSunny Srivastava  * @return - Number of bytes written on success, -1 on failure.
317fa5e4d32SSunny Srivastava  *
318fa5e4d32SSunny Srivastava  * @throw - std::runtime_error, sdbusplus::exception::SdBusError
319fa5e4d32SSunny Srivastava  */
writeKeyword(const std::string & i_vpdPath,const types::WriteVpdParams & i_paramsToWriteData)320fa5e4d32SSunny Srivastava inline int writeKeyword(const std::string& i_vpdPath,
321fa5e4d32SSunny Srivastava                         const types::WriteVpdParams& i_paramsToWriteData)
322fa5e4d32SSunny Srivastava {
323fa5e4d32SSunny Srivastava     if (i_vpdPath.empty())
324fa5e4d32SSunny Srivastava     {
325fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty path");
326fa5e4d32SSunny Srivastava     }
327fa5e4d32SSunny Srivastava 
328fa5e4d32SSunny Srivastava     int l_rc = constants::FAILURE;
329fa5e4d32SSunny Srivastava     auto l_bus = sdbusplus::bus::new_default();
330fa5e4d32SSunny Srivastava 
331fa5e4d32SSunny Srivastava     auto l_method = l_bus.new_method_call(
332fa5e4d32SSunny Srivastava         constants::vpdManagerService, constants::vpdManagerObjectPath,
333fa5e4d32SSunny Srivastava         constants::vpdManagerInfName, "UpdateKeyword");
334fa5e4d32SSunny Srivastava 
335fa5e4d32SSunny Srivastava     l_method.append(i_vpdPath, i_paramsToWriteData);
336fa5e4d32SSunny Srivastava     auto l_result = l_bus.call(l_method);
337fa5e4d32SSunny Srivastava 
338fa5e4d32SSunny Srivastava     l_result.read(l_rc);
339fa5e4d32SSunny Srivastava     return l_rc;
340fa5e4d32SSunny Srivastava }
341fa5e4d32SSunny Srivastava 
342fa5e4d32SSunny Srivastava /**
343fa5e4d32SSunny Srivastava  * @brief API to write keyword's value on hardware.
344fa5e4d32SSunny Srivastava  *
345fa5e4d32SSunny Srivastava  * This API writes keyword's value by requesting DBus service(vpd-manager) who
346fa5e4d32SSunny Srivastava  * hosts the 'WriteKeywordOnHardware' method to update keyword's value.
347fa5e4d32SSunny Srivastava  *
348fa5e4d32SSunny Srivastava  * Note: This API updates keyword's value only on the given hardware path, any
349fa5e4d32SSunny Srivastava  * backup or redundant EEPROM (if exists) paths won't get updated.
350fa5e4d32SSunny Srivastava  *
351fa5e4d32SSunny Srivastava  * @param[in] i_eepromPath - EEPROM where keyword is present.
352fa5e4d32SSunny Srivastava  * @param[in] i_paramsToWriteData - Data required to update keyword's value.
353fa5e4d32SSunny Srivastava  *
354fa5e4d32SSunny Srivastava  * @return - Number of bytes written on success, -1 on failure.
355fa5e4d32SSunny Srivastava  *
356fa5e4d32SSunny Srivastava  * @throw - std::runtime_error, sdbusplus::exception::SdBusError
357fa5e4d32SSunny Srivastava  */
writeKeywordOnHardware(const std::string & i_eepromPath,const types::WriteVpdParams & i_paramsToWriteData)35843fedabcSPatrick Williams inline int writeKeywordOnHardware(
35943fedabcSPatrick Williams     const std::string& i_eepromPath,
360fa5e4d32SSunny Srivastava     const types::WriteVpdParams& i_paramsToWriteData)
361fa5e4d32SSunny Srivastava {
362fa5e4d32SSunny Srivastava     if (i_eepromPath.empty())
363fa5e4d32SSunny Srivastava     {
364fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty path");
365fa5e4d32SSunny Srivastava     }
366fa5e4d32SSunny Srivastava 
367fa5e4d32SSunny Srivastava     int l_rc = constants::FAILURE;
368fa5e4d32SSunny Srivastava     auto l_bus = sdbusplus::bus::new_default();
369fa5e4d32SSunny Srivastava 
370fa5e4d32SSunny Srivastava     auto l_method = l_bus.new_method_call(
371fa5e4d32SSunny Srivastava         constants::vpdManagerService, constants::vpdManagerObjectPath,
372fa5e4d32SSunny Srivastava         constants::vpdManagerInfName, "WriteKeywordOnHardware");
373fa5e4d32SSunny Srivastava 
374fa5e4d32SSunny Srivastava     l_method.append(i_eepromPath, i_paramsToWriteData);
375fa5e4d32SSunny Srivastava     auto l_result = l_bus.call(l_method);
376fa5e4d32SSunny Srivastava 
377fa5e4d32SSunny Srivastava     l_result.read(l_rc);
378fa5e4d32SSunny Srivastava 
379fa5e4d32SSunny Srivastava     return l_rc;
380fa5e4d32SSunny Srivastava }
381fa5e4d32SSunny Srivastava 
382fa5e4d32SSunny Srivastava /**
383fa5e4d32SSunny Srivastava  * @brief API to get data in binary format.
384fa5e4d32SSunny Srivastava  *
385fa5e4d32SSunny Srivastava  * This API converts given string value into array of binary data.
386fa5e4d32SSunny Srivastava  *
387fa5e4d32SSunny Srivastava  * @param[in] i_value - Input data.
388fa5e4d32SSunny Srivastava  *
389fa5e4d32SSunny Srivastava  * @return - Array of binary data on success, throws as exception in case
390fa5e4d32SSunny Srivastava  * of any error.
391fa5e4d32SSunny Srivastava  *
392fa5e4d32SSunny Srivastava  * @throw std::runtime_error, std::out_of_range, std::bad_alloc,
393fa5e4d32SSunny Srivastava  * std::invalid_argument
394fa5e4d32SSunny Srivastava  */
convertToBinary(const std::string & i_value)395fa5e4d32SSunny Srivastava inline types::BinaryVector convertToBinary(const std::string& i_value)
396fa5e4d32SSunny Srivastava {
397fa5e4d32SSunny Srivastava     if (i_value.empty())
398fa5e4d32SSunny Srivastava     {
399fa5e4d32SSunny Srivastava         throw std::runtime_error(
400fa5e4d32SSunny Srivastava             "Provide a valid hexadecimal input. (Ex. 0x30313233)");
401fa5e4d32SSunny Srivastava     }
402fa5e4d32SSunny Srivastava 
403fa5e4d32SSunny Srivastava     std::vector<uint8_t> l_binaryValue{};
404fa5e4d32SSunny Srivastava 
405fa5e4d32SSunny Srivastava     if (i_value.substr(0, 2).compare("0x") == constants::STR_CMP_SUCCESS)
406fa5e4d32SSunny Srivastava     {
407fa5e4d32SSunny Srivastava         if (i_value.length() % 2 != 0)
408fa5e4d32SSunny Srivastava         {
409fa5e4d32SSunny Srivastava             throw std::runtime_error(
410fa5e4d32SSunny Srivastava                 "Write option accepts 2 digit hex numbers. (Ex. 0x1 "
411fa5e4d32SSunny Srivastava                 "should be given as 0x01).");
412fa5e4d32SSunny Srivastava         }
413fa5e4d32SSunny Srivastava 
414fa5e4d32SSunny Srivastava         auto l_value = i_value.substr(2);
415fa5e4d32SSunny Srivastava 
416fa5e4d32SSunny Srivastava         if (l_value.empty())
417fa5e4d32SSunny Srivastava         {
418fa5e4d32SSunny Srivastava             throw std::runtime_error(
419fa5e4d32SSunny Srivastava                 "Provide a valid hexadecimal input. (Ex. 0x30313233)");
420fa5e4d32SSunny Srivastava         }
421fa5e4d32SSunny Srivastava 
422fa5e4d32SSunny Srivastava         if (l_value.find_first_not_of("0123456789abcdefABCDEF") !=
423fa5e4d32SSunny Srivastava             std::string::npos)
424fa5e4d32SSunny Srivastava         {
425fa5e4d32SSunny Srivastava             throw std::runtime_error("Provide a valid hexadecimal input.");
426fa5e4d32SSunny Srivastava         }
427fa5e4d32SSunny Srivastava 
428fa5e4d32SSunny Srivastava         for (size_t l_pos = 0; l_pos < l_value.length(); l_pos += 2)
429fa5e4d32SSunny Srivastava         {
430fa5e4d32SSunny Srivastava             uint8_t l_byte = static_cast<uint8_t>(
431fa5e4d32SSunny Srivastava                 std::stoi(l_value.substr(l_pos, 2), nullptr, 16));
432fa5e4d32SSunny Srivastava             l_binaryValue.push_back(l_byte);
433fa5e4d32SSunny Srivastava         }
434fa5e4d32SSunny Srivastava     }
435fa5e4d32SSunny Srivastava     else
436fa5e4d32SSunny Srivastava     {
437fa5e4d32SSunny Srivastava         l_binaryValue.assign(i_value.begin(), i_value.end());
438fa5e4d32SSunny Srivastava     }
439fa5e4d32SSunny Srivastava     return l_binaryValue;
440fa5e4d32SSunny Srivastava }
441fa5e4d32SSunny Srivastava 
442fa5e4d32SSunny Srivastava /**
443fa5e4d32SSunny Srivastava  * @brief API to parse respective JSON.
444fa5e4d32SSunny Srivastava  *
445fa5e4d32SSunny Srivastava  * @param[in] i_pathToJson - Path to JSON.
446fa5e4d32SSunny Srivastava  *
447fa5e4d32SSunny Srivastava  * @return Parsed JSON, throws exception in case of error.
448fa5e4d32SSunny Srivastava  *
449fa5e4d32SSunny Srivastava  * @throw std::runtime_error
450fa5e4d32SSunny Srivastava  */
getParsedJson(const std::string & i_pathToJson)451fa5e4d32SSunny Srivastava inline nlohmann::json getParsedJson(const std::string& i_pathToJson)
452fa5e4d32SSunny Srivastava {
453fa5e4d32SSunny Srivastava     if (i_pathToJson.empty())
454fa5e4d32SSunny Srivastava     {
455fa5e4d32SSunny Srivastava         throw std::runtime_error("Path to JSON is missing");
456fa5e4d32SSunny Srivastava     }
457fa5e4d32SSunny Srivastava 
458fa5e4d32SSunny Srivastava     std::error_code l_ec;
459fa5e4d32SSunny Srivastava     if (!std::filesystem::exists(i_pathToJson, l_ec))
460fa5e4d32SSunny Srivastava     {
461fa5e4d32SSunny Srivastava         std::string l_message{
462fa5e4d32SSunny Srivastava             "file system call failed for file: " + i_pathToJson};
463fa5e4d32SSunny Srivastava 
464fa5e4d32SSunny Srivastava         if (l_ec)
465fa5e4d32SSunny Srivastava         {
466fa5e4d32SSunny Srivastava             l_message += ", error: " + l_ec.message();
467fa5e4d32SSunny Srivastava         }
468fa5e4d32SSunny Srivastava         throw std::runtime_error(l_message);
469fa5e4d32SSunny Srivastava     }
470fa5e4d32SSunny Srivastava 
471fa5e4d32SSunny Srivastava     if (std::filesystem::is_empty(i_pathToJson, l_ec))
472fa5e4d32SSunny Srivastava     {
473fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty file: " + i_pathToJson);
474fa5e4d32SSunny Srivastava     }
475fa5e4d32SSunny Srivastava     else if (l_ec)
476fa5e4d32SSunny Srivastava     {
477fa5e4d32SSunny Srivastava         throw std::runtime_error("is_empty file system call failed for file: " +
478fa5e4d32SSunny Srivastava                                  i_pathToJson + ", error: " + l_ec.message());
479fa5e4d32SSunny Srivastava     }
480fa5e4d32SSunny Srivastava 
481fa5e4d32SSunny Srivastava     std::ifstream l_jsonFile(i_pathToJson);
482fa5e4d32SSunny Srivastava     if (!l_jsonFile)
483fa5e4d32SSunny Srivastava     {
484fa5e4d32SSunny Srivastava         throw std::runtime_error("Failed to access Json path: " + i_pathToJson);
485fa5e4d32SSunny Srivastava     }
486fa5e4d32SSunny Srivastava 
487fa5e4d32SSunny Srivastava     try
488fa5e4d32SSunny Srivastava     {
489fa5e4d32SSunny Srivastava         return nlohmann::json::parse(l_jsonFile);
490fa5e4d32SSunny Srivastava     }
491fa5e4d32SSunny Srivastava     catch (const nlohmann::json::parse_error& l_ex)
492fa5e4d32SSunny Srivastava     {
493fa5e4d32SSunny Srivastava         throw std::runtime_error("Failed to parse JSON file: " + i_pathToJson);
494fa5e4d32SSunny Srivastava     }
495fa5e4d32SSunny Srivastava }
496fa5e4d32SSunny Srivastava 
497fa5e4d32SSunny Srivastava /**
498fa5e4d32SSunny Srivastava  * @brief API to get list of interfaces under a given object path.
499fa5e4d32SSunny Srivastava  *
500fa5e4d32SSunny Srivastava  * Given a DBus object path, this API returns a map of service -> implemented
501fa5e4d32SSunny Srivastava  * interface(s) under that object path. This API calls DBus method GetObject
502fa5e4d32SSunny Srivastava  * hosted by ObjectMapper DBus service.
503fa5e4d32SSunny Srivastava  *
504fa5e4d32SSunny Srivastava  * @param[in] i_objectPath - DBus object path.
505fa5e4d32SSunny Srivastava  * @param[in] i_constrainingInterfaces - An array of result set constraining
506fa5e4d32SSunny Srivastava  * interfaces.
507fa5e4d32SSunny Srivastava  *
508fa5e4d32SSunny Srivastava  * @return On success, returns a map of service -> implemented interface(s),
509fa5e4d32SSunny Srivastava  * else returns an empty map. The caller of this
510fa5e4d32SSunny Srivastava  * API should check for empty map.
511fa5e4d32SSunny Srivastava  */
GetServiceInterfacesForObject(const std::string & i_objectPath,const std::vector<std::string> & i_constrainingInterfaces)512fa5e4d32SSunny Srivastava inline types::MapperGetObject GetServiceInterfacesForObject(
513fa5e4d32SSunny Srivastava     const std::string& i_objectPath,
514fa5e4d32SSunny Srivastava     const std::vector<std::string>& i_constrainingInterfaces) noexcept
515fa5e4d32SSunny Srivastava {
516fa5e4d32SSunny Srivastava     types::MapperGetObject l_serviceInfMap;
517fa5e4d32SSunny Srivastava     if (i_objectPath.empty())
518fa5e4d32SSunny Srivastava     {
519fa5e4d32SSunny Srivastava         // TODO: log only when verbose is enabled
520fa5e4d32SSunny Srivastava         std::cerr << "Object path is empty." << std::endl;
521fa5e4d32SSunny Srivastava         return l_serviceInfMap;
522fa5e4d32SSunny Srivastava     }
523fa5e4d32SSunny Srivastava 
524fa5e4d32SSunny Srivastava     try
525fa5e4d32SSunny Srivastava     {
526fa5e4d32SSunny Srivastava         auto l_bus = sdbusplus::bus::new_default();
527fa5e4d32SSunny Srivastava         auto l_method = l_bus.new_method_call(
528fa5e4d32SSunny Srivastava             constants::objectMapperService, constants::objectMapperObjectPath,
529fa5e4d32SSunny Srivastava             constants::objectMapperInfName, "GetObject");
530fa5e4d32SSunny Srivastava 
531fa5e4d32SSunny Srivastava         l_method.append(i_objectPath, i_constrainingInterfaces);
532fa5e4d32SSunny Srivastava 
533fa5e4d32SSunny Srivastava         auto l_result = l_bus.call(l_method);
534fa5e4d32SSunny Srivastava         l_result.read(l_serviceInfMap);
535fa5e4d32SSunny Srivastava     }
536fa5e4d32SSunny Srivastava     catch (const sdbusplus::exception::SdBusError& l_ex)
537fa5e4d32SSunny Srivastava     {
538fa5e4d32SSunny Srivastava         // TODO: log only when verbose is enabled
539d353990eSAnupama B R         std::cerr << std::string(l_ex.what()) << std::endl;
540fa5e4d32SSunny Srivastava     }
541fa5e4d32SSunny Srivastava     return l_serviceInfMap;
542fa5e4d32SSunny Srivastava }
543fa5e4d32SSunny Srivastava 
544fa5e4d32SSunny Srivastava /** @brief API to get list of sub tree paths for a given object path
545fa5e4d32SSunny Srivastava  *
546fa5e4d32SSunny Srivastava  * Given a DBus object path, this API returns a list of object paths under that
547fa5e4d32SSunny Srivastava  * object path in the DBus tree. This API calls DBus method GetSubTreePaths
548fa5e4d32SSunny Srivastava  * hosted by ObjectMapper DBus service.
549fa5e4d32SSunny Srivastava  *
550fa5e4d32SSunny Srivastava  * @param[in] i_objectPath - DBus object path.
551fa5e4d32SSunny Srivastava  * @param[in] i_constrainingInterfaces - An array of result set constraining
552fa5e4d32SSunny Srivastava  * interfaces.
553fa5e4d32SSunny Srivastava  * @param[in] i_depth - The maximum subtree depth for which results should be
554fa5e4d32SSunny Srivastava  * fetched. For unconstrained fetches use a depth of zero.
555fa5e4d32SSunny Srivastava  *
556fa5e4d32SSunny Srivastava  * @return On success, returns a std::vector<std::string> of object paths in
557fa5e4d32SSunny Srivastava  * Phosphor Inventory Manager DBus service's tree, else returns an empty vector.
558fa5e4d32SSunny Srivastava  * The caller of this API should check for empty vector.
559fa5e4d32SSunny Srivastava  */
GetSubTreePaths(const std::string i_objectPath,const int i_depth=0,const std::vector<std::string> & i_constrainingInterfaces={})560fa5e4d32SSunny Srivastava inline std::vector<std::string> GetSubTreePaths(
561fa5e4d32SSunny Srivastava     const std::string i_objectPath, const int i_depth = 0,
562fa5e4d32SSunny Srivastava     const std::vector<std::string>& i_constrainingInterfaces = {}) noexcept
563fa5e4d32SSunny Srivastava {
564fa5e4d32SSunny Srivastava     std::vector<std::string> l_objectPaths;
565fa5e4d32SSunny Srivastava 
566fa5e4d32SSunny Srivastava     try
567fa5e4d32SSunny Srivastava     {
568fa5e4d32SSunny Srivastava         auto l_bus = sdbusplus::bus::new_default();
569fa5e4d32SSunny Srivastava         auto l_method = l_bus.new_method_call(
570fa5e4d32SSunny Srivastava             constants::objectMapperService, constants::objectMapperObjectPath,
571fa5e4d32SSunny Srivastava             constants::objectMapperInfName, "GetSubTreePaths");
572fa5e4d32SSunny Srivastava 
573fa5e4d32SSunny Srivastava         l_method.append(i_objectPath, i_depth, i_constrainingInterfaces);
574fa5e4d32SSunny Srivastava 
575fa5e4d32SSunny Srivastava         auto l_result = l_bus.call(l_method);
576fa5e4d32SSunny Srivastava         l_result.read(l_objectPaths);
577fa5e4d32SSunny Srivastava     }
578fa5e4d32SSunny Srivastava     catch (const sdbusplus::exception::SdBusError& l_ex)
579fa5e4d32SSunny Srivastava     {
580fa5e4d32SSunny Srivastava         // TODO: log only when verbose is enabled
581fa5e4d32SSunny Srivastava         std::cerr << std::string(l_ex.what()) << std::endl;
582fa5e4d32SSunny Srivastava     }
583fa5e4d32SSunny Srivastava     return l_objectPaths;
584fa5e4d32SSunny Srivastava }
585fa5e4d32SSunny Srivastava 
586fa5e4d32SSunny Srivastava /**
587fa5e4d32SSunny Srivastava  * @brief A class to print data in tabular format
588fa5e4d32SSunny Srivastava  *
589fa5e4d32SSunny Srivastava  * This class implements methods to print data in a two dimensional tabular
590fa5e4d32SSunny Srivastava  * format. All entries in the table must be in string format.
591fa5e4d32SSunny Srivastava  *
592fa5e4d32SSunny Srivastava  */
593fa5e4d32SSunny Srivastava class Table
594fa5e4d32SSunny Srivastava {
595fa5e4d32SSunny Srivastava     class Column : public types::TableColumnNameSizePair
596fa5e4d32SSunny Srivastava     {
597fa5e4d32SSunny Srivastava       public:
598fa5e4d32SSunny Srivastava         /**
599fa5e4d32SSunny Srivastava          * @brief API to get the name of the Column
600fa5e4d32SSunny Srivastava          *
601fa5e4d32SSunny Srivastava          * @return Name of the Column.
602fa5e4d32SSunny Srivastava          */
Name() const603fa5e4d32SSunny Srivastava         const std::string& Name() const
604fa5e4d32SSunny Srivastava         {
605fa5e4d32SSunny Srivastava             return this->first;
606fa5e4d32SSunny Srivastava         }
607fa5e4d32SSunny Srivastava 
608fa5e4d32SSunny Srivastava         /**
609fa5e4d32SSunny Srivastava          * @brief API to get the width of the Column
610fa5e4d32SSunny Srivastava          *
611fa5e4d32SSunny Srivastava          * @return Width of the Column.
612fa5e4d32SSunny Srivastava          */
Width() const613fa5e4d32SSunny Srivastava         std::size_t Width() const
614fa5e4d32SSunny Srivastava         {
615fa5e4d32SSunny Srivastava             return this->second;
616fa5e4d32SSunny Srivastava         }
617fa5e4d32SSunny Srivastava     };
618fa5e4d32SSunny Srivastava 
619fa5e4d32SSunny Srivastava     // Current width of the table
620fa5e4d32SSunny Srivastava     std::size_t m_currentWidth;
621fa5e4d32SSunny Srivastava 
622fa5e4d32SSunny Srivastava     // Character to be used as fill character between entries
623fa5e4d32SSunny Srivastava     char m_fillCharacter;
624fa5e4d32SSunny Srivastava 
625fa5e4d32SSunny Srivastava     // Separator character to be used between columns
626fa5e4d32SSunny Srivastava     char m_separator;
627fa5e4d32SSunny Srivastava 
628fa5e4d32SSunny Srivastava     // Array of columns
629fa5e4d32SSunny Srivastava     std::vector<Column> m_columns;
630fa5e4d32SSunny Srivastava 
631fa5e4d32SSunny Srivastava     /**
632fa5e4d32SSunny Srivastava      * @brief API to Print Header
633fa5e4d32SSunny Srivastava      *
634fa5e4d32SSunny Srivastava      * Header line prints the names of the Column headers separated by the
635fa5e4d32SSunny Srivastava      * specified separator character and spaced accordingly.
636fa5e4d32SSunny Srivastava      *
637fa5e4d32SSunny Srivastava      * @throw std::out_of_range, std::length_error, std::bad_alloc
638fa5e4d32SSunny Srivastava      */
PrintHeader() const639fa5e4d32SSunny Srivastava     void PrintHeader() const
640fa5e4d32SSunny Srivastava     {
641fa5e4d32SSunny Srivastava         for (const auto& l_column : m_columns)
642fa5e4d32SSunny Srivastava         {
643fa5e4d32SSunny Srivastava             PrintEntry(l_column.Name(), l_column.Width());
644fa5e4d32SSunny Srivastava         }
645fa5e4d32SSunny Srivastava         std::cout << m_separator << std::endl;
646fa5e4d32SSunny Srivastava     }
647fa5e4d32SSunny Srivastava 
648fa5e4d32SSunny Srivastava     /**
649fa5e4d32SSunny Srivastava      * @brief API to Print Horizontal Line
650fa5e4d32SSunny Srivastava      *
651fa5e4d32SSunny Srivastava      * A horizontal line is a sequence of '*'s.
652fa5e4d32SSunny Srivastava      *
653fa5e4d32SSunny Srivastava      * @throw std::out_of_range, std::length_error, std::bad_alloc
654fa5e4d32SSunny Srivastava      */
PrintHorizontalLine() const655fa5e4d32SSunny Srivastava     void PrintHorizontalLine() const
656fa5e4d32SSunny Srivastava     {
657fa5e4d32SSunny Srivastava         std::cout << std::string(m_currentWidth, '*') << std::endl;
658fa5e4d32SSunny Srivastava     }
659fa5e4d32SSunny Srivastava 
660fa5e4d32SSunny Srivastava     /**
661fa5e4d32SSunny Srivastava      * @brief API to print an entry in the table
662fa5e4d32SSunny Srivastava      *
663fa5e4d32SSunny Srivastava      * An entry is a separator character followed by the text to print.
664fa5e4d32SSunny Srivastava      * The text is centre-aligned.
665fa5e4d32SSunny Srivastava      *
666fa5e4d32SSunny Srivastava      * @param[in] i_text - text to print
667fa5e4d32SSunny Srivastava      * @param[in] i_columnWidth - width of the column
668fa5e4d32SSunny Srivastava      *
669fa5e4d32SSunny Srivastava      * @throw std::out_of_range, std::length_error, std::bad_alloc
670fa5e4d32SSunny Srivastava      */
PrintEntry(const std::string & i_text,std::size_t i_columnWidth) const671fa5e4d32SSunny Srivastava     void PrintEntry(const std::string& i_text, std::size_t i_columnWidth) const
672fa5e4d32SSunny Srivastava     {
673fa5e4d32SSunny Srivastava         const std::size_t l_textLength{i_text.length()};
674fa5e4d32SSunny Srivastava 
675fa5e4d32SSunny Srivastava         constexpr std::size_t l_minFillChars{3};
676fa5e4d32SSunny Srivastava         const std::size_t l_numFillChars =
677fa5e4d32SSunny Srivastava             ((l_textLength >= i_columnWidth ? l_minFillChars
678fa5e4d32SSunny Srivastava                                             : i_columnWidth - l_textLength)) -
679fa5e4d32SSunny Srivastava             1; // -1 for the separator character
680fa5e4d32SSunny Srivastava 
681fa5e4d32SSunny Srivastava         const unsigned l_oddFill = l_numFillChars % 2;
682fa5e4d32SSunny Srivastava 
683fa5e4d32SSunny Srivastava         std::cout << m_separator
684fa5e4d32SSunny Srivastava                   << std::string((l_numFillChars / 2) + l_oddFill,
685fa5e4d32SSunny Srivastava                                  m_fillCharacter)
686fa5e4d32SSunny Srivastava                   << i_text << std::string(l_numFillChars / 2, m_fillCharacter);
687fa5e4d32SSunny Srivastava     }
688fa5e4d32SSunny Srivastava 
689fa5e4d32SSunny Srivastava   public:
690fa5e4d32SSunny Srivastava     /**
691fa5e4d32SSunny Srivastava      * @brief Table Constructor
692fa5e4d32SSunny Srivastava      *
693fa5e4d32SSunny Srivastava      * Parameterized constructor for a Table object
694fa5e4d32SSunny Srivastava      *
695fa5e4d32SSunny Srivastava      */
Table(const char i_fillCharacter=' ',const char i_separator='|')696fa5e4d32SSunny Srivastava     constexpr explicit Table(const char i_fillCharacter = ' ',
697fa5e4d32SSunny Srivastava                              const char i_separator = '|') noexcept :
698fa5e4d32SSunny Srivastava         m_currentWidth{0}, m_fillCharacter{i_fillCharacter},
699fa5e4d32SSunny Srivastava         m_separator{i_separator}
700fa5e4d32SSunny Srivastava     {}
701fa5e4d32SSunny Srivastava 
702fa5e4d32SSunny Srivastava     // deleted methods
703fa5e4d32SSunny Srivastava     Table(const Table&) = delete;
704fa5e4d32SSunny Srivastava     Table operator=(const Table&) = delete;
705fa5e4d32SSunny Srivastava     Table(const Table&&) = delete;
706fa5e4d32SSunny Srivastava     Table operator=(const Table&&) = delete;
707fa5e4d32SSunny Srivastava 
708fa5e4d32SSunny Srivastava     ~Table() = default;
709fa5e4d32SSunny Srivastava 
710fa5e4d32SSunny Srivastava     /**
711fa5e4d32SSunny Srivastava      * @brief API to add column to Table
712fa5e4d32SSunny Srivastava      *
713fa5e4d32SSunny Srivastava      * @param[in] i_name - Name of the column.
714fa5e4d32SSunny Srivastava      *
715fa5e4d32SSunny Srivastava      * @param[in] i_width - Width to allocate for the column.
716fa5e4d32SSunny Srivastava      *
717fa5e4d32SSunny Srivastava      * @return On success returns 0, otherwise returns -1.
718fa5e4d32SSunny Srivastava      */
AddColumn(const std::string & i_name,std::size_t i_width)719fa5e4d32SSunny Srivastava     int AddColumn(const std::string& i_name, std::size_t i_width)
720fa5e4d32SSunny Srivastava     {
721fa5e4d32SSunny Srivastava         if (i_width < i_name.length())
722fa5e4d32SSunny Srivastava             return constants::FAILURE;
723fa5e4d32SSunny Srivastava         m_columns.emplace_back(types::TableColumnNameSizePair(i_name, i_width));
724fa5e4d32SSunny Srivastava         m_currentWidth += i_width;
725fa5e4d32SSunny Srivastava         return constants::SUCCESS;
726fa5e4d32SSunny Srivastava     }
727fa5e4d32SSunny Srivastava 
728fa5e4d32SSunny Srivastava     /**
729fa5e4d32SSunny Srivastava      * @brief API to print the Table to console.
730fa5e4d32SSunny Srivastava      *
731fa5e4d32SSunny Srivastava      * This API prints the table data to console.
732fa5e4d32SSunny Srivastava      *
733fa5e4d32SSunny Srivastava      * @param[in] i_tableData - The data to be printed.
734fa5e4d32SSunny Srivastava      *
735fa5e4d32SSunny Srivastava      * @return On success returns 0, otherwise returns -1.
736fa5e4d32SSunny Srivastava      *
737fa5e4d32SSunny Srivastava      * @throw std::out_of_range, std::length_error, std::bad_alloc
738fa5e4d32SSunny Srivastava      */
Print(const types::TableInputData & i_tableData) const739fa5e4d32SSunny Srivastava     int Print(const types::TableInputData& i_tableData) const
740fa5e4d32SSunny Srivastava     {
741fa5e4d32SSunny Srivastava         PrintHorizontalLine();
742fa5e4d32SSunny Srivastava         PrintHeader();
743fa5e4d32SSunny Srivastava         PrintHorizontalLine();
744fa5e4d32SSunny Srivastava 
745fa5e4d32SSunny Srivastava         // print the table data
746fa5e4d32SSunny Srivastava         for (const auto& l_row : i_tableData)
747fa5e4d32SSunny Srivastava         {
748fa5e4d32SSunny Srivastava             unsigned l_columnNumber{0};
749fa5e4d32SSunny Srivastava 
750fa5e4d32SSunny Srivastava             // number of columns in input data is greater than the number of
751fa5e4d32SSunny Srivastava             // columns specified in Table
752fa5e4d32SSunny Srivastava             if (l_row.size() > m_columns.size())
753fa5e4d32SSunny Srivastava             {
754fa5e4d32SSunny Srivastava                 return constants::FAILURE;
755fa5e4d32SSunny Srivastava             }
756fa5e4d32SSunny Srivastava 
757fa5e4d32SSunny Srivastava             for (const auto& l_entry : l_row)
758fa5e4d32SSunny Srivastava             {
759fa5e4d32SSunny Srivastava                 PrintEntry(l_entry, m_columns[l_columnNumber].Width());
760fa5e4d32SSunny Srivastava 
761fa5e4d32SSunny Srivastava                 ++l_columnNumber;
762fa5e4d32SSunny Srivastava             }
763fa5e4d32SSunny Srivastava             std::cout << m_separator << std::endl;
764fa5e4d32SSunny Srivastava         }
765fa5e4d32SSunny Srivastava         PrintHorizontalLine();
766fa5e4d32SSunny Srivastava         return constants::SUCCESS;
767fa5e4d32SSunny Srivastava     }
768fa5e4d32SSunny Srivastava };
769fa5e4d32SSunny Srivastava 
770951d6609SAnupama B R /**
771951d6609SAnupama B R  * @brief API to read value from file.
772951d6609SAnupama B R  *
773951d6609SAnupama B R  * The API reads the file and returns the read value.
774951d6609SAnupama B R  *
775951d6609SAnupama B R  * @param[in] i_filePath - File path.
776951d6609SAnupama B R  *
777951d6609SAnupama B R  * @return - Data from file if any in string format, else empty string.
778951d6609SAnupama B R  *
779951d6609SAnupama B R  */
readValueFromFile(const std::string & i_filePath)780951d6609SAnupama B R inline std::string readValueFromFile(const std::string& i_filePath)
781951d6609SAnupama B R {
782951d6609SAnupama B R     std::string l_valueRead{};
783951d6609SAnupama B R 
784951d6609SAnupama B R     std::error_code l_ec;
785951d6609SAnupama B R     if (!std::filesystem::exists(i_filePath, l_ec))
786951d6609SAnupama B R     {
787951d6609SAnupama B R         std::string l_message{
788951d6609SAnupama B R             "filesystem call exists failed for file [" + i_filePath + "]."};
789951d6609SAnupama B R 
790951d6609SAnupama B R         if (l_ec)
791951d6609SAnupama B R         {
792951d6609SAnupama B R             l_message += " Error: " + l_ec.message();
793951d6609SAnupama B R         }
794951d6609SAnupama B R 
795951d6609SAnupama B R         std::cerr << l_message << std::endl;
796951d6609SAnupama B R         return l_valueRead;
797951d6609SAnupama B R     }
798951d6609SAnupama B R 
799951d6609SAnupama B R     if (std::filesystem::is_empty(i_filePath, l_ec))
800951d6609SAnupama B R     {
801951d6609SAnupama B R         std::cerr << "File[" << i_filePath << "] is empty." << std::endl;
802951d6609SAnupama B R         return l_valueRead;
803951d6609SAnupama B R     }
804951d6609SAnupama B R     else if (l_ec)
805951d6609SAnupama B R     {
806951d6609SAnupama B R         std::cerr << "is_empty file system call failed for file[" << i_filePath
807951d6609SAnupama B R                   << "] , error: " << l_ec.message() << std::endl;
808951d6609SAnupama B R 
809951d6609SAnupama B R         return l_valueRead;
810951d6609SAnupama B R     }
811951d6609SAnupama B R 
812951d6609SAnupama B R     std::ifstream l_fileStream;
813951d6609SAnupama B R     l_fileStream.exceptions(std::ifstream::badbit | std::ifstream::failbit);
814951d6609SAnupama B R     try
815951d6609SAnupama B R     {
816951d6609SAnupama B R         l_fileStream.open(i_filePath, std::ifstream::in);
817951d6609SAnupama B R 
818951d6609SAnupama B R         std::getline(l_fileStream, l_valueRead);
819951d6609SAnupama B R 
820951d6609SAnupama B R         l_fileStream.close();
821951d6609SAnupama B R         return l_valueRead;
822951d6609SAnupama B R     }
823951d6609SAnupama B R     catch (const std::ifstream::failure& l_ex)
824951d6609SAnupama B R     {
825951d6609SAnupama B R         if (l_fileStream.is_open())
826951d6609SAnupama B R         {
827951d6609SAnupama B R             l_fileStream.close();
828951d6609SAnupama B R         }
829951d6609SAnupama B R 
830951d6609SAnupama B R         std::cerr << "File read operation failed for path[" << i_filePath
831951d6609SAnupama B R                   << "], error: " << l_ex.what() << std::endl;
832951d6609SAnupama B R     }
833951d6609SAnupama B R 
834951d6609SAnupama B R     return l_valueRead;
835951d6609SAnupama B R }
836951d6609SAnupama B R 
8376be2c015SAnupama B R /**
8386be2c015SAnupama B R  * @brief API to check if chassis is powered off.
8396be2c015SAnupama B R  *
8406be2c015SAnupama B R  * This API queries Phosphor Chassis State Manager to know whether
8416be2c015SAnupama B R  * chassis is powered off.
8426be2c015SAnupama B R  *
8436be2c015SAnupama B R  * @return true if chassis is powered off, false otherwise.
8446be2c015SAnupama B R  */
isChassisPowerOff()8456be2c015SAnupama B R inline bool isChassisPowerOff()
8466be2c015SAnupama B R {
8476be2c015SAnupama B R     try
8486be2c015SAnupama B R     {
8496be2c015SAnupama B R         // ToDo: Handle in case system has multiple chassis
8506be2c015SAnupama B R         auto l_powerState = readDbusProperty(
8516be2c015SAnupama B R             constants::chassisStateManagerService,
8526be2c015SAnupama B R             constants::chassisStateManagerObjectPath,
8536be2c015SAnupama B R             constants::chassisStateManagerInfName, "CurrentPowerState");
8546be2c015SAnupama B R 
8556be2c015SAnupama B R         if (auto l_curPowerState = std::get_if<std::string>(&l_powerState);
8566be2c015SAnupama B R             l_curPowerState &&
8576be2c015SAnupama B R             ("xyz.openbmc_project.State.Chassis.PowerState.Off" ==
8586be2c015SAnupama B R              *l_curPowerState))
8596be2c015SAnupama B R         {
8606be2c015SAnupama B R             return true;
8616be2c015SAnupama B R         }
8626be2c015SAnupama B R     }
8636be2c015SAnupama B R     catch (const std::exception& l_ex)
8646be2c015SAnupama B R     {
8656be2c015SAnupama B R         // Todo: Enale log when verbose is enabled
8666be2c015SAnupama B R         std::cerr << l_ex.what() << std::endl;
8676be2c015SAnupama B R     }
8686be2c015SAnupama B R     return false;
8696be2c015SAnupama B R }
8706be2c015SAnupama B R 
871*7f749a6fSSouvik Roy /**
872*7f749a6fSSouvik Roy  * @brief API to check if a D-Bus service is running or not.
873*7f749a6fSSouvik Roy  *
874*7f749a6fSSouvik Roy  * Any failure in calling the method "NameHasOwner" implies that the service
875*7f749a6fSSouvik Roy  * is not in a running state. Hence the API returns false in case of any
876*7f749a6fSSouvik Roy  * exception as well.
877*7f749a6fSSouvik Roy  *
878*7f749a6fSSouvik Roy  * @param[in] i_serviceName - D-Bus service name whose status is to be
879*7f749a6fSSouvik Roy  * checked.
880*7f749a6fSSouvik Roy  * @return bool - True if the service is running, false otherwise.
881*7f749a6fSSouvik Roy  */
isServiceRunning(const std::string & i_serviceName)882*7f749a6fSSouvik Roy inline bool isServiceRunning(const std::string& i_serviceName) noexcept
883*7f749a6fSSouvik Roy {
884*7f749a6fSSouvik Roy     bool l_retVal = false;
885*7f749a6fSSouvik Roy 
886*7f749a6fSSouvik Roy     try
887*7f749a6fSSouvik Roy     {
888*7f749a6fSSouvik Roy         auto l_bus = sdbusplus::bus::new_default();
889*7f749a6fSSouvik Roy         auto l_method = l_bus.new_method_call(
890*7f749a6fSSouvik Roy             constants::dbusService, constants::dbusObjectPath,
891*7f749a6fSSouvik Roy             constants::dbusInterface, "NameHasOwner");
892*7f749a6fSSouvik Roy         l_method.append(i_serviceName);
893*7f749a6fSSouvik Roy 
894*7f749a6fSSouvik Roy         l_bus.call(l_method).read(l_retVal);
895*7f749a6fSSouvik Roy     }
896*7f749a6fSSouvik Roy     catch (const sdbusplus::exception::SdBusError& l_ex)
897*7f749a6fSSouvik Roy     {
898*7f749a6fSSouvik Roy         std::cout << "Call to check service status failed with exception: " +
899*7f749a6fSSouvik Roy                          std::string(l_ex.what())
900*7f749a6fSSouvik Roy                   << std::endl;
901*7f749a6fSSouvik Roy     }
902*7f749a6fSSouvik Roy 
903*7f749a6fSSouvik Roy     return l_retVal;
904*7f749a6fSSouvik Roy }
905*7f749a6fSSouvik Roy 
906fa5e4d32SSunny Srivastava } // namespace utils
907fa5e4d32SSunny Srivastava } // namespace vpd
908