blob: 152cfcaef6f8d9b0ec9587cf851eba978e7a1097 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#include "tool_constants.hpp"
Anupama B R951d6602025-01-18 09:52:33 -06002#include "tool_utils.hpp"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05003#include "vpd_tool.hpp"
4
5#include <CLI/CLI.hpp>
6
7#include <filesystem>
8#include <iostream>
9
10/**
Anupama B R6be2c012025-01-23 02:59:27 -060011 * @brief Resets the VPD on DBus for all the Frus.
12 *
13 * API clears the inventory persisted data and restarts the phosphor inventory
14 * manager(PIM) DBus service and the VPD manager service. VPD manager service
15 * collects the VPD for all the FRU's listed on the system config JSON and calls
16 * PIM to publish VPD on DBus.
17 *
18 * Note: Force reset only happens if chassis is powered off.
19 *
20 * @return On success returns 0, otherwise returns -1.
21 */
22int forceReset()
23{
24 if (vpd::utils::isChassisPowerOff())
25 {
26 vpd::VpdTool l_vpdToolObj;
27 return l_vpdToolObj.resetVpdOnDbus();
28 }
29
30 std::cerr
31 << "The chassis power state is not Off. Force reset operation is not allowed."
32 << std::endl;
33 return vpd::constants::FAILURE;
34}
35
36/**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050037 * @brief API to perform manufacturing clean.
38 *
39 * @param[in] i_mfgCleanConfirmFlag - Confirmation flag to perform manufacturing
40 * clean.
Souvik Roy63089422025-01-23 02:48:21 -060041 * @param[in] i_syncBiosAttributesFlag - Flag which specifies whether
42 * BIOS attribute related keywords need to be synced from BIOS Config Manager
43 * instead of being reset to default value.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050044 *
45 * @return Status returned by cleanSystemVpd operation, success otherwise.
46 */
Souvik Roy63089422025-01-23 02:48:21 -060047int doMfgClean(const auto& i_mfgCleanConfirmFlag,
48 const auto& i_syncBiosAttributesFlag)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050049{
50 if (i_mfgCleanConfirmFlag->empty())
51 {
52 constexpr auto MAX_CONFIRMATION_STR_LENGTH{3};
53 std::string l_confirmation{};
54 std::cout
55 << "This option resets some of the system VPD keywords to their default values. Do you really wish to proceed further?[yes/no]:";
56 std::cin >> std::setw(MAX_CONFIRMATION_STR_LENGTH) >> l_confirmation;
57
58 if (l_confirmation != "yes")
59 {
60 return vpd::constants::SUCCESS;
61 }
62 }
63
64 vpd::VpdTool l_vpdToolObj;
Souvik Roy63089422025-01-23 02:48:21 -060065 return l_vpdToolObj.cleanSystemVpd(!i_syncBiosAttributesFlag->empty());
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050066}
67
68/**
69 * @brief API to write keyword's value.
70 *
71 * @param[in] i_hardwareFlag - Flag to perform write on hardware.
72 * @param[in] i_keywordValueOption - Option to read keyword value from command.
73 * @param[in] i_vpdPath - DBus object path or EEPROM path.
74 * @param[in] i_recordName - Record to be updated.
75 * @param[in] i_keywordName - Keyword to be updated.
76 * @param[in] i_keywordValue - Value to be updated in keyword.
77 *
78 * @return Status of writeKeyword operation, failure otherwise.
79 */
80int writeKeyword(const auto& i_hardwareFlag, const auto& i_keywordValueOption,
81 const std::string& i_vpdPath, const std::string& i_recordName,
82 const std::string& i_keywordName,
83 const std::string& i_keywordValue)
84{
85 std::error_code l_ec;
86
87 if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
88 {
Anupama B R42ca4942025-02-12 00:13:33 -060089 std::cerr << "Given EEPROM file path doesn't exist[" + i_vpdPath << "]."
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050090 << std::endl;
Anupama B R42ca4942025-02-12 00:13:33 -060091 if (l_ec)
92 {
93 std::cerr << "Reason: " + l_ec.message() << std::endl;
94 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050095 return vpd::constants::FAILURE;
96 }
97
98 if (!i_keywordValueOption->empty() && i_keywordValue.empty())
99 {
100 std::cerr
101 << "Please provide keyword value.\nUse --value/--file to give "
102 "keyword value. Refer --help."
103 << std::endl;
104 return vpd::constants::FAILURE;
105 }
106
107 if (i_keywordValueOption->empty())
108 {
109 std::cerr
110 << "Please provide keyword value.\nUse --value/--file to give "
111 "keyword value. Refer --help."
112 << std::endl;
113 return vpd::constants::FAILURE;
114 }
115
Rekha Aparna9f255f52025-04-23 05:25:07 -0500116 if (i_keywordName == vpd::constants::KwdIM)
117 {
118 if (!(i_keywordValue.substr(0, 2).compare("0x") ==
119 vpd::constants::STR_CMP_SUCCESS))
120 {
121 std::cerr << "Please provide IM value in hex format." << std::endl;
122 return vpd::constants::FAILURE;
123 }
124
125 if (std::find(vpd::constants::validImValues.begin(),
126 vpd::constants::validImValues.end(), i_keywordValue) ==
127 vpd::constants::validImValues.end())
128 {
129 std::cerr << "Given IM value [" << i_keywordValue
130 << "] doesn't match with any of the valid system type."
131 << std::endl;
132 return vpd::constants::FAILURE;
133 }
134 }
135
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500136 vpd::VpdTool l_vpdToolObj;
137 return l_vpdToolObj.writeKeyword(i_vpdPath, i_recordName, i_keywordName,
138 i_keywordValue, !i_hardwareFlag->empty());
139}
140
141/**
142 * @brief API to read keyword's value.
143 *
144 * @param[in] i_hardwareFlag - Flag to perform write on hardware.
145 * @param[in] i_vpdPath - DBus object path or EEPROM path.
146 * @param[in] i_recordName - Record to be updated.
147 * @param[in] i_keywordName - Keyword to be updated.
148 * @param[in] i_filePath - File path to save keyword's read value.
149 *
Anupama B Rd3539902025-01-20 05:10:00 -0600150 * @return On success return 0, otherwise return -1.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500151 */
152int readKeyword(const auto& i_hardwareFlag, const std::string& i_vpdPath,
153 const std::string& i_recordName,
154 const std::string& i_keywordName, const std::string& i_filePath)
155{
156 std::error_code l_ec;
157
158 if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
159 {
160 std::string l_errMessage{
161 "Given EEPROM file path doesn't exist : " + i_vpdPath};
162
163 if (l_ec)
164 {
165 l_errMessage += ". filesystem call exists failed, reason: " +
166 l_ec.message();
167 }
168
169 std::cerr << l_errMessage << std::endl;
170 return vpd::constants::FAILURE;
171 }
172
173 bool l_isHardwareOperation = (!i_hardwareFlag->empty() ? true : false);
174
175 vpd::VpdTool l_vpdToolObj;
176 return l_vpdToolObj.readKeyword(i_vpdPath, i_recordName, i_keywordName,
177 l_isHardwareOperation, i_filePath);
178}
179
180/**
181 * @brief API to check option value pair in the tool command.
182 *
183 * In VPD tool command, some of the option(s) mandate values to be passed along
184 * with the option. This API based on option, detects those mandatory value(s).
185 *
186 * @param[in] i_objectOption - Option to pass object path.
187 * @param[in] i_vpdPath - Object path, DBus or EEPROM.
188 * @param[in] i_recordOption - Option to pass record name.
189 * @param[in] i_recordName - Record name.
190 * @param[in] i_keywordOption - Option to pass keyword name.
191 * @param[in] i_keywordName - Keyword name.
Anupama B R951d6602025-01-18 09:52:33 -0600192 * @param[in] i_fileOption - Option to pass file path.
193 * @param[in] i_filePath - File path.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500194 *
195 * @return Success if corresponding value is found against option, failure
196 * otherwise.
197 */
198int checkOptionValuePair(const auto& i_objectOption, const auto& i_vpdPath,
199 const auto& i_recordOption, const auto& i_recordName,
Anupama B R951d6602025-01-18 09:52:33 -0600200 const auto& i_keywordOption, const auto& i_keywordName,
201 const auto& i_fileOption, const auto& i_filePath)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500202{
203 if (!i_objectOption->empty() && i_vpdPath.empty())
204 {
205 std::cout << "Given path is empty." << std::endl;
206 return vpd::constants::FAILURE;
207 }
208
209 if (!i_recordOption->empty() &&
210 (i_recordName.size() != vpd::constants::RECORD_SIZE))
211 {
212 std::cerr << "Record " << i_recordName << " is not supported."
213 << std::endl;
214 return vpd::constants::FAILURE;
215 }
216
217 if (!i_keywordOption->empty() &&
218 (i_keywordName.size() != vpd::constants::KEYWORD_SIZE))
219 {
220 std::cerr << "Keyword " << i_keywordName << " is not supported."
221 << std::endl;
222 return vpd::constants::FAILURE;
223 }
224
Anupama B R951d6602025-01-18 09:52:33 -0600225 if (!i_fileOption->empty() && i_filePath.empty())
226 {
227 std::cout << "File path is empty." << std::endl;
228 return vpd::constants::FAILURE;
229 }
230
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500231 return vpd::constants::SUCCESS;
232}
233
234/**
235 * @brief API to create app footer.
236 *
237 * @param[in] i_app - CLI::App object.
238 */
239void updateFooter(CLI::App& i_app)
240{
241 i_app.footer(
242 "Read:\n"
243 " IPZ Format:\n"
244 " From DBus to console: "
245 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name>\n"
246 " From DBus to file: "
247 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
248 " From hardware to console: "
249 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name>\n"
250 " From hardware to file: "
251 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
252 "Write:\n"
253 " IPZ Format:\n"
254 " On DBus: "
255 "vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
256 " On DBus, take keyword value from file:\n"
257 " vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
258 " On hardware: "
259 "vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
260 " On hardware, take keyword value from file:\n"
261 " vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
262 "Dump Object:\n"
263 " From DBus to console: "
264 "vpd-tool -o -O <DBus Object Path>\n"
265 "Fix System VPD:\n"
266 " vpd-tool --fixSystemVPD\n"
267 "MfgClean:\n"
268 " Flag to clean and reset specific keywords on system VPD to its default value.\n"
269 " vpd-tool --mfgClean\n"
Souvik Roy63089422025-01-23 02:48:21 -0600270 " To sync BIOS attribute related keywords with BIOS Config Manager:\n"
271 " vpd-tool --mfgClean --syncBiosAttributes\n"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500272 "Dump Inventory:\n"
273 " From DBus to console in JSON format: "
274 "vpd-tool -i\n"
275 " From DBus to console in Table format: "
Anupama B R6be2c012025-01-23 02:59:27 -0600276 "vpd-tool -i -t\n"
277 "Force Reset:\n"
278 " vpd-tool --forceReset\n");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500279}
280
281int main(int argc, char** argv)
282{
283 CLI::App l_app{"VPD Command Line Tool"};
284
285 std::string l_vpdPath{};
286 std::string l_recordName{};
287 std::string l_keywordName{};
288 std::string l_filePath{};
289 std::string l_keywordValue{};
290
291 updateFooter(l_app);
292
293 auto l_objectOption =
294 l_app.add_option("--object, -O", l_vpdPath, "File path");
295 auto l_recordOption =
296 l_app.add_option("--record, -R", l_recordName, "Record name");
297 auto l_keywordOption =
298 l_app.add_option("--keyword, -K", l_keywordName, "Keyword name");
299
Anupama B R42914f42025-04-04 01:29:54 -0500300 auto l_fileOption = l_app.add_option(
301 "--file", l_filePath,
302 "Absolute file path,\nNote: For write operation, file should contain keyword’s value in either ascii or in hex format.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500303
304 auto l_keywordValueOption =
305 l_app.add_option("--value, -V", l_keywordValue,
306 "Keyword value in ascii/hex format."
307 " ascii ex: 01234; hex ex: 0x30313233");
308
309 auto l_hardwareFlag =
310 l_app.add_flag("--Hardware, -H", "CAUTION: Developer only option.");
311
312 auto l_readFlag = l_app.add_flag("--readKeyword, -r", "Read keyword")
313 ->needs(l_objectOption)
314 ->needs(l_recordOption)
315 ->needs(l_keywordOption);
316
317 auto l_writeFlag =
318 l_app
319 .add_flag(
320 "--writeKeyword, -w,--updateKeyword, -u",
Anupama B R42914f42025-04-04 01:29:54 -0500321 "Write keyword,\nNote: In case DBus path is provided, both EEPROM and DBus are updated with the given keyword's value.\nIn case EEPROM path is provided, only the given EEPROM is updated with the given keyword's value.")
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500322 ->needs(l_objectOption)
323 ->needs(l_recordOption)
324 ->needs(l_keywordOption);
325
326 // ToDo: Take offset value from user for hardware path.
327
328 auto l_dumpObjFlag =
329 l_app
330 .add_flag("--dumpObject, -o",
331 "Dump specific properties of an inventory object")
332 ->needs(l_objectOption);
333
334 auto l_fixSystemVpdFlag = l_app.add_flag(
335 "--fixSystemVPD",
336 "Use this option to interactively fix critical system VPD keywords");
337 auto l_dumpInventoryFlag =
338 l_app.add_flag("--dumpInventory, -i", "Dump all the inventory objects");
339
340 auto l_mfgCleanFlag = l_app.add_flag(
341 "--mfgClean", "Manufacturing clean on system VPD keyword");
342
343 auto l_mfgCleanConfirmFlag = l_app.add_flag(
344 "--yes", "Using this flag with --mfgClean option, assumes "
345 "yes to proceed without confirmation.");
346
347 auto l_dumpInventoryTableFlag =
348 l_app.add_flag("--table, -t", "Dump inventory in table format");
349
Souvik Roy63089422025-01-23 02:48:21 -0600350 auto l_mfgCleanSyncBiosAttributesFlag = l_app.add_flag(
351 "--syncBiosAttributes, -s",
352 "Using this flag with --mfgClean option, Syncs the BIOS attribute related keywords from BIOS Config Manager service instead resetting keyword's value to default value");
353
Anupama B R6be2c012025-01-23 02:59:27 -0600354 auto l_forceResetFlag = l_app.add_flag(
355 "--forceReset, -f, -F",
356 "Force collect for hardware. CAUTION: Developer only option.");
357
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500358 CLI11_PARSE(l_app, argc, argv);
359
360 if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
Anupama B R951d6602025-01-18 09:52:33 -0600361 l_recordName, l_keywordOption, l_keywordName,
362 l_fileOption, l_filePath) ==
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500363 vpd::constants::FAILURE)
364 {
365 return vpd::constants::FAILURE;
366 }
367
368 if (!l_readFlag->empty())
369 {
370 return readKeyword(l_hardwareFlag, l_vpdPath, l_recordName,
371 l_keywordName, l_filePath);
372 }
373
374 if (!l_writeFlag->empty())
375 {
Anupama B R951d6602025-01-18 09:52:33 -0600376 if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
377 (!l_keywordValueOption->empty() && !l_fileOption->empty()))
378 {
379 std::cerr
380 << "Please provide keyword value.\nUse --value/--file to give "
381 "keyword value. Refer --help."
382 << std::endl;
383 return vpd::constants::FAILURE;
384 }
385
386 if (!l_fileOption->empty())
387 {
388 l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
389 if (l_keywordValue.empty())
390 {
391 return vpd::constants::FAILURE;
392 }
393
394 return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
395 l_recordName, l_keywordName, l_keywordValue);
396 }
397
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500398 return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
399 l_recordName, l_keywordName, l_keywordValue);
400 }
401
402 if (!l_dumpObjFlag->empty())
403 {
404 vpd::VpdTool l_vpdToolObj;
405 return l_vpdToolObj.dumpObject(l_vpdPath);
406 }
407
408 if (!l_fixSystemVpdFlag->empty())
409 {
410 vpd::VpdTool l_vpdToolObj;
411 return l_vpdToolObj.fixSystemVpd();
412 }
413
414 if (!l_mfgCleanFlag->empty())
415 {
Souvik Roy63089422025-01-23 02:48:21 -0600416 return doMfgClean(l_mfgCleanConfirmFlag,
417 l_mfgCleanSyncBiosAttributesFlag);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500418 }
419
420 if (!l_dumpInventoryFlag->empty())
421 {
422 vpd::VpdTool l_vpdToolObj;
423 return l_vpdToolObj.dumpInventory(!l_dumpInventoryTableFlag->empty());
424 }
425
Anupama B R6be2c012025-01-23 02:59:27 -0600426 if (!l_forceResetFlag->empty())
427 {
428 return forceReset();
429 }
430
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500431 std::cout << l_app.help() << std::endl;
432 return vpd::constants::FAILURE;
433}