blob: 18d71efd90035626aa6c9d10f4bd135746471217 [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
116 vpd::VpdTool l_vpdToolObj;
117 return l_vpdToolObj.writeKeyword(i_vpdPath, i_recordName, i_keywordName,
118 i_keywordValue, !i_hardwareFlag->empty());
119}
120
121/**
122 * @brief API to read keyword's value.
123 *
124 * @param[in] i_hardwareFlag - Flag to perform write on hardware.
125 * @param[in] i_vpdPath - DBus object path or EEPROM path.
126 * @param[in] i_recordName - Record to be updated.
127 * @param[in] i_keywordName - Keyword to be updated.
128 * @param[in] i_filePath - File path to save keyword's read value.
129 *
Anupama B Rd3539902025-01-20 05:10:00 -0600130 * @return On success return 0, otherwise return -1.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500131 */
132int readKeyword(const auto& i_hardwareFlag, const std::string& i_vpdPath,
133 const std::string& i_recordName,
134 const std::string& i_keywordName, const std::string& i_filePath)
135{
136 std::error_code l_ec;
137
138 if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
139 {
140 std::string l_errMessage{
141 "Given EEPROM file path doesn't exist : " + i_vpdPath};
142
143 if (l_ec)
144 {
145 l_errMessage += ". filesystem call exists failed, reason: " +
146 l_ec.message();
147 }
148
149 std::cerr << l_errMessage << std::endl;
150 return vpd::constants::FAILURE;
151 }
152
153 bool l_isHardwareOperation = (!i_hardwareFlag->empty() ? true : false);
154
155 vpd::VpdTool l_vpdToolObj;
156 return l_vpdToolObj.readKeyword(i_vpdPath, i_recordName, i_keywordName,
157 l_isHardwareOperation, i_filePath);
158}
159
160/**
161 * @brief API to check option value pair in the tool command.
162 *
163 * In VPD tool command, some of the option(s) mandate values to be passed along
164 * with the option. This API based on option, detects those mandatory value(s).
165 *
166 * @param[in] i_objectOption - Option to pass object path.
167 * @param[in] i_vpdPath - Object path, DBus or EEPROM.
168 * @param[in] i_recordOption - Option to pass record name.
169 * @param[in] i_recordName - Record name.
170 * @param[in] i_keywordOption - Option to pass keyword name.
171 * @param[in] i_keywordName - Keyword name.
Anupama B R951d6602025-01-18 09:52:33 -0600172 * @param[in] i_fileOption - Option to pass file path.
173 * @param[in] i_filePath - File path.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500174 *
175 * @return Success if corresponding value is found against option, failure
176 * otherwise.
177 */
178int checkOptionValuePair(const auto& i_objectOption, const auto& i_vpdPath,
179 const auto& i_recordOption, const auto& i_recordName,
Anupama B R951d6602025-01-18 09:52:33 -0600180 const auto& i_keywordOption, const auto& i_keywordName,
181 const auto& i_fileOption, const auto& i_filePath)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500182{
183 if (!i_objectOption->empty() && i_vpdPath.empty())
184 {
185 std::cout << "Given path is empty." << std::endl;
186 return vpd::constants::FAILURE;
187 }
188
189 if (!i_recordOption->empty() &&
190 (i_recordName.size() != vpd::constants::RECORD_SIZE))
191 {
192 std::cerr << "Record " << i_recordName << " is not supported."
193 << std::endl;
194 return vpd::constants::FAILURE;
195 }
196
197 if (!i_keywordOption->empty() &&
198 (i_keywordName.size() != vpd::constants::KEYWORD_SIZE))
199 {
200 std::cerr << "Keyword " << i_keywordName << " is not supported."
201 << std::endl;
202 return vpd::constants::FAILURE;
203 }
204
Anupama B R951d6602025-01-18 09:52:33 -0600205 if (!i_fileOption->empty() && i_filePath.empty())
206 {
207 std::cout << "File path is empty." << std::endl;
208 return vpd::constants::FAILURE;
209 }
210
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500211 return vpd::constants::SUCCESS;
212}
213
214/**
215 * @brief API to create app footer.
216 *
217 * @param[in] i_app - CLI::App object.
218 */
219void updateFooter(CLI::App& i_app)
220{
221 i_app.footer(
222 "Read:\n"
223 " IPZ Format:\n"
224 " From DBus to console: "
225 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name>\n"
226 " From DBus to file: "
227 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
228 " From hardware to console: "
229 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name>\n"
230 " From hardware to file: "
231 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
232 "Write:\n"
233 " IPZ Format:\n"
234 " On DBus: "
235 "vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
236 " On DBus, take keyword value from file:\n"
237 " vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
238 " On hardware: "
239 "vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
240 " On hardware, take keyword value from file:\n"
241 " vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
242 "Dump Object:\n"
243 " From DBus to console: "
244 "vpd-tool -o -O <DBus Object Path>\n"
245 "Fix System VPD:\n"
246 " vpd-tool --fixSystemVPD\n"
247 "MfgClean:\n"
248 " Flag to clean and reset specific keywords on system VPD to its default value.\n"
249 " vpd-tool --mfgClean\n"
Souvik Roy63089422025-01-23 02:48:21 -0600250 " To sync BIOS attribute related keywords with BIOS Config Manager:\n"
251 " vpd-tool --mfgClean --syncBiosAttributes\n"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500252 "Dump Inventory:\n"
253 " From DBus to console in JSON format: "
254 "vpd-tool -i\n"
255 " From DBus to console in Table format: "
Anupama B R6be2c012025-01-23 02:59:27 -0600256 "vpd-tool -i -t\n"
257 "Force Reset:\n"
258 " vpd-tool --forceReset\n");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500259}
260
261int main(int argc, char** argv)
262{
263 CLI::App l_app{"VPD Command Line Tool"};
264
265 std::string l_vpdPath{};
266 std::string l_recordName{};
267 std::string l_keywordName{};
268 std::string l_filePath{};
269 std::string l_keywordValue{};
270
271 updateFooter(l_app);
272
273 auto l_objectOption =
274 l_app.add_option("--object, -O", l_vpdPath, "File path");
275 auto l_recordOption =
276 l_app.add_option("--record, -R", l_recordName, "Record name");
277 auto l_keywordOption =
278 l_app.add_option("--keyword, -K", l_keywordName, "Keyword name");
279
Anupama B R42914f42025-04-04 01:29:54 -0500280 auto l_fileOption = l_app.add_option(
281 "--file", l_filePath,
282 "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 -0500283
284 auto l_keywordValueOption =
285 l_app.add_option("--value, -V", l_keywordValue,
286 "Keyword value in ascii/hex format."
287 " ascii ex: 01234; hex ex: 0x30313233");
288
289 auto l_hardwareFlag =
290 l_app.add_flag("--Hardware, -H", "CAUTION: Developer only option.");
291
292 auto l_readFlag = l_app.add_flag("--readKeyword, -r", "Read keyword")
293 ->needs(l_objectOption)
294 ->needs(l_recordOption)
295 ->needs(l_keywordOption);
296
297 auto l_writeFlag =
298 l_app
299 .add_flag(
300 "--writeKeyword, -w,--updateKeyword, -u",
Anupama B R42914f42025-04-04 01:29:54 -0500301 "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 -0500302 ->needs(l_objectOption)
303 ->needs(l_recordOption)
304 ->needs(l_keywordOption);
305
306 // ToDo: Take offset value from user for hardware path.
307
308 auto l_dumpObjFlag =
309 l_app
310 .add_flag("--dumpObject, -o",
311 "Dump specific properties of an inventory object")
312 ->needs(l_objectOption);
313
314 auto l_fixSystemVpdFlag = l_app.add_flag(
315 "--fixSystemVPD",
316 "Use this option to interactively fix critical system VPD keywords");
317 auto l_dumpInventoryFlag =
318 l_app.add_flag("--dumpInventory, -i", "Dump all the inventory objects");
319
320 auto l_mfgCleanFlag = l_app.add_flag(
321 "--mfgClean", "Manufacturing clean on system VPD keyword");
322
323 auto l_mfgCleanConfirmFlag = l_app.add_flag(
324 "--yes", "Using this flag with --mfgClean option, assumes "
325 "yes to proceed without confirmation.");
326
327 auto l_dumpInventoryTableFlag =
328 l_app.add_flag("--table, -t", "Dump inventory in table format");
329
Souvik Roy63089422025-01-23 02:48:21 -0600330 auto l_mfgCleanSyncBiosAttributesFlag = l_app.add_flag(
331 "--syncBiosAttributes, -s",
332 "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");
333
Anupama B R6be2c012025-01-23 02:59:27 -0600334 auto l_forceResetFlag = l_app.add_flag(
335 "--forceReset, -f, -F",
336 "Force collect for hardware. CAUTION: Developer only option.");
337
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500338 CLI11_PARSE(l_app, argc, argv);
339
340 if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
Anupama B R951d6602025-01-18 09:52:33 -0600341 l_recordName, l_keywordOption, l_keywordName,
342 l_fileOption, l_filePath) ==
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500343 vpd::constants::FAILURE)
344 {
345 return vpd::constants::FAILURE;
346 }
347
348 if (!l_readFlag->empty())
349 {
350 return readKeyword(l_hardwareFlag, l_vpdPath, l_recordName,
351 l_keywordName, l_filePath);
352 }
353
354 if (!l_writeFlag->empty())
355 {
Anupama B R951d6602025-01-18 09:52:33 -0600356 if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
357 (!l_keywordValueOption->empty() && !l_fileOption->empty()))
358 {
359 std::cerr
360 << "Please provide keyword value.\nUse --value/--file to give "
361 "keyword value. Refer --help."
362 << std::endl;
363 return vpd::constants::FAILURE;
364 }
365
366 if (!l_fileOption->empty())
367 {
368 l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
369 if (l_keywordValue.empty())
370 {
371 return vpd::constants::FAILURE;
372 }
373
374 return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
375 l_recordName, l_keywordName, l_keywordValue);
376 }
377
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500378 return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
379 l_recordName, l_keywordName, l_keywordValue);
380 }
381
382 if (!l_dumpObjFlag->empty())
383 {
384 vpd::VpdTool l_vpdToolObj;
385 return l_vpdToolObj.dumpObject(l_vpdPath);
386 }
387
388 if (!l_fixSystemVpdFlag->empty())
389 {
390 vpd::VpdTool l_vpdToolObj;
391 return l_vpdToolObj.fixSystemVpd();
392 }
393
394 if (!l_mfgCleanFlag->empty())
395 {
Souvik Roy63089422025-01-23 02:48:21 -0600396 return doMfgClean(l_mfgCleanConfirmFlag,
397 l_mfgCleanSyncBiosAttributesFlag);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500398 }
399
400 if (!l_dumpInventoryFlag->empty())
401 {
402 vpd::VpdTool l_vpdToolObj;
403 return l_vpdToolObj.dumpInventory(!l_dumpInventoryTableFlag->empty());
404 }
405
Anupama B R6be2c012025-01-23 02:59:27 -0600406 if (!l_forceResetFlag->empty())
407 {
408 return forceReset();
409 }
410
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500411 std::cout << l_app.help() << std::endl;
412 return vpd::constants::FAILURE;
413}