blob: 4dde248389fbaccdac484468cd3803dd63186342 [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 {
89 std::cerr << "Given EEPROM file path doesn't exist : " + i_vpdPath
90 << std::endl;
91 return vpd::constants::FAILURE;
92 }
93
94 if (l_ec)
95 {
96 std::cerr << "filesystem call exists failed for file: " << i_vpdPath
97 << ", reason: " + l_ec.message() << std::endl;
98 return vpd::constants::FAILURE;
99 }
100
101 if (!i_keywordValueOption->empty() && i_keywordValue.empty())
102 {
103 std::cerr
104 << "Please provide keyword value.\nUse --value/--file to give "
105 "keyword value. Refer --help."
106 << std::endl;
107 return vpd::constants::FAILURE;
108 }
109
110 if (i_keywordValueOption->empty())
111 {
112 std::cerr
113 << "Please provide keyword value.\nUse --value/--file to give "
114 "keyword value. Refer --help."
115 << std::endl;
116 return vpd::constants::FAILURE;
117 }
118
119 vpd::VpdTool l_vpdToolObj;
120 return l_vpdToolObj.writeKeyword(i_vpdPath, i_recordName, i_keywordName,
121 i_keywordValue, !i_hardwareFlag->empty());
122}
123
124/**
125 * @brief API to read keyword's value.
126 *
127 * @param[in] i_hardwareFlag - Flag to perform write on hardware.
128 * @param[in] i_vpdPath - DBus object path or EEPROM path.
129 * @param[in] i_recordName - Record to be updated.
130 * @param[in] i_keywordName - Keyword to be updated.
131 * @param[in] i_filePath - File path to save keyword's read value.
132 *
Anupama B Rd3539902025-01-20 05:10:00 -0600133 * @return On success return 0, otherwise return -1.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500134 */
135int readKeyword(const auto& i_hardwareFlag, const std::string& i_vpdPath,
136 const std::string& i_recordName,
137 const std::string& i_keywordName, const std::string& i_filePath)
138{
139 std::error_code l_ec;
140
141 if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
142 {
143 std::string l_errMessage{
144 "Given EEPROM file path doesn't exist : " + i_vpdPath};
145
146 if (l_ec)
147 {
148 l_errMessage += ". filesystem call exists failed, reason: " +
149 l_ec.message();
150 }
151
152 std::cerr << l_errMessage << std::endl;
153 return vpd::constants::FAILURE;
154 }
155
156 bool l_isHardwareOperation = (!i_hardwareFlag->empty() ? true : false);
157
158 vpd::VpdTool l_vpdToolObj;
159 return l_vpdToolObj.readKeyword(i_vpdPath, i_recordName, i_keywordName,
160 l_isHardwareOperation, i_filePath);
161}
162
163/**
164 * @brief API to check option value pair in the tool command.
165 *
166 * In VPD tool command, some of the option(s) mandate values to be passed along
167 * with the option. This API based on option, detects those mandatory value(s).
168 *
169 * @param[in] i_objectOption - Option to pass object path.
170 * @param[in] i_vpdPath - Object path, DBus or EEPROM.
171 * @param[in] i_recordOption - Option to pass record name.
172 * @param[in] i_recordName - Record name.
173 * @param[in] i_keywordOption - Option to pass keyword name.
174 * @param[in] i_keywordName - Keyword name.
Anupama B R951d6602025-01-18 09:52:33 -0600175 * @param[in] i_fileOption - Option to pass file path.
176 * @param[in] i_filePath - File path.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500177 *
178 * @return Success if corresponding value is found against option, failure
179 * otherwise.
180 */
181int checkOptionValuePair(const auto& i_objectOption, const auto& i_vpdPath,
182 const auto& i_recordOption, const auto& i_recordName,
Anupama B R951d6602025-01-18 09:52:33 -0600183 const auto& i_keywordOption, const auto& i_keywordName,
184 const auto& i_fileOption, const auto& i_filePath)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500185{
186 if (!i_objectOption->empty() && i_vpdPath.empty())
187 {
188 std::cout << "Given path is empty." << std::endl;
189 return vpd::constants::FAILURE;
190 }
191
192 if (!i_recordOption->empty() &&
193 (i_recordName.size() != vpd::constants::RECORD_SIZE))
194 {
195 std::cerr << "Record " << i_recordName << " is not supported."
196 << std::endl;
197 return vpd::constants::FAILURE;
198 }
199
200 if (!i_keywordOption->empty() &&
201 (i_keywordName.size() != vpd::constants::KEYWORD_SIZE))
202 {
203 std::cerr << "Keyword " << i_keywordName << " is not supported."
204 << std::endl;
205 return vpd::constants::FAILURE;
206 }
207
Anupama B R951d6602025-01-18 09:52:33 -0600208 if (!i_fileOption->empty() && i_filePath.empty())
209 {
210 std::cout << "File path is empty." << std::endl;
211 return vpd::constants::FAILURE;
212 }
213
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500214 return vpd::constants::SUCCESS;
215}
216
217/**
218 * @brief API to create app footer.
219 *
220 * @param[in] i_app - CLI::App object.
221 */
222void updateFooter(CLI::App& i_app)
223{
224 i_app.footer(
225 "Read:\n"
226 " IPZ Format:\n"
227 " From DBus to console: "
228 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name>\n"
229 " From DBus to file: "
230 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
231 " From hardware to console: "
232 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name>\n"
233 " From hardware to file: "
234 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
235 "Write:\n"
236 " IPZ Format:\n"
237 " On DBus: "
238 "vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
239 " On DBus, take keyword value from file:\n"
240 " vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
241 " On hardware: "
242 "vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
243 " On hardware, take keyword value from file:\n"
244 " vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
245 "Dump Object:\n"
246 " From DBus to console: "
247 "vpd-tool -o -O <DBus Object Path>\n"
248 "Fix System VPD:\n"
249 " vpd-tool --fixSystemVPD\n"
250 "MfgClean:\n"
251 " Flag to clean and reset specific keywords on system VPD to its default value.\n"
252 " vpd-tool --mfgClean\n"
Souvik Roy63089422025-01-23 02:48:21 -0600253 " To sync BIOS attribute related keywords with BIOS Config Manager:\n"
254 " vpd-tool --mfgClean --syncBiosAttributes\n"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500255 "Dump Inventory:\n"
256 " From DBus to console in JSON format: "
257 "vpd-tool -i\n"
258 " From DBus to console in Table format: "
Anupama B R6be2c012025-01-23 02:59:27 -0600259 "vpd-tool -i -t\n"
260 "Force Reset:\n"
261 " vpd-tool --forceReset\n");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500262}
263
264int main(int argc, char** argv)
265{
266 CLI::App l_app{"VPD Command Line Tool"};
267
268 std::string l_vpdPath{};
269 std::string l_recordName{};
270 std::string l_keywordName{};
271 std::string l_filePath{};
272 std::string l_keywordValue{};
273
274 updateFooter(l_app);
275
276 auto l_objectOption =
277 l_app.add_option("--object, -O", l_vpdPath, "File path");
278 auto l_recordOption =
279 l_app.add_option("--record, -R", l_recordName, "Record name");
280 auto l_keywordOption =
281 l_app.add_option("--keyword, -K", l_keywordName, "Keyword name");
282
Anupama B R951d6602025-01-18 09:52:33 -0600283 auto l_fileOption =
284 l_app.add_option("--file", l_filePath, "Absolute file path");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500285
286 auto l_keywordValueOption =
287 l_app.add_option("--value, -V", l_keywordValue,
288 "Keyword value in ascii/hex format."
289 " ascii ex: 01234; hex ex: 0x30313233");
290
291 auto l_hardwareFlag =
292 l_app.add_flag("--Hardware, -H", "CAUTION: Developer only option.");
293
294 auto l_readFlag = l_app.add_flag("--readKeyword, -r", "Read keyword")
295 ->needs(l_objectOption)
296 ->needs(l_recordOption)
297 ->needs(l_keywordOption);
298
299 auto l_writeFlag =
300 l_app
301 .add_flag(
302 "--writeKeyword, -w,--updateKeyword, -u",
303 "Write keyword, Note: Irrespective of DBus or hardware path provided, primary and backup, redundant EEPROM(if any) paths will get updated with given key value")
304 ->needs(l_objectOption)
305 ->needs(l_recordOption)
306 ->needs(l_keywordOption);
307
308 // ToDo: Take offset value from user for hardware path.
309
310 auto l_dumpObjFlag =
311 l_app
312 .add_flag("--dumpObject, -o",
313 "Dump specific properties of an inventory object")
314 ->needs(l_objectOption);
315
316 auto l_fixSystemVpdFlag = l_app.add_flag(
317 "--fixSystemVPD",
318 "Use this option to interactively fix critical system VPD keywords");
319 auto l_dumpInventoryFlag =
320 l_app.add_flag("--dumpInventory, -i", "Dump all the inventory objects");
321
322 auto l_mfgCleanFlag = l_app.add_flag(
323 "--mfgClean", "Manufacturing clean on system VPD keyword");
324
325 auto l_mfgCleanConfirmFlag = l_app.add_flag(
326 "--yes", "Using this flag with --mfgClean option, assumes "
327 "yes to proceed without confirmation.");
328
329 auto l_dumpInventoryTableFlag =
330 l_app.add_flag("--table, -t", "Dump inventory in table format");
331
Souvik Roy63089422025-01-23 02:48:21 -0600332 auto l_mfgCleanSyncBiosAttributesFlag = l_app.add_flag(
333 "--syncBiosAttributes, -s",
334 "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");
335
Anupama B R6be2c012025-01-23 02:59:27 -0600336 auto l_forceResetFlag = l_app.add_flag(
337 "--forceReset, -f, -F",
338 "Force collect for hardware. CAUTION: Developer only option.");
339
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500340 CLI11_PARSE(l_app, argc, argv);
341
342 if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
Anupama B R951d6602025-01-18 09:52:33 -0600343 l_recordName, l_keywordOption, l_keywordName,
344 l_fileOption, l_filePath) ==
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500345 vpd::constants::FAILURE)
346 {
347 return vpd::constants::FAILURE;
348 }
349
350 if (!l_readFlag->empty())
351 {
352 return readKeyword(l_hardwareFlag, l_vpdPath, l_recordName,
353 l_keywordName, l_filePath);
354 }
355
356 if (!l_writeFlag->empty())
357 {
Anupama B R951d6602025-01-18 09:52:33 -0600358 if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
359 (!l_keywordValueOption->empty() && !l_fileOption->empty()))
360 {
361 std::cerr
362 << "Please provide keyword value.\nUse --value/--file to give "
363 "keyword value. Refer --help."
364 << std::endl;
365 return vpd::constants::FAILURE;
366 }
367
368 if (!l_fileOption->empty())
369 {
370 l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
371 if (l_keywordValue.empty())
372 {
373 return vpd::constants::FAILURE;
374 }
375
376 return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
377 l_recordName, l_keywordName, l_keywordValue);
378 }
379
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500380 return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
381 l_recordName, l_keywordName, l_keywordValue);
382 }
383
384 if (!l_dumpObjFlag->empty())
385 {
386 vpd::VpdTool l_vpdToolObj;
387 return l_vpdToolObj.dumpObject(l_vpdPath);
388 }
389
390 if (!l_fixSystemVpdFlag->empty())
391 {
392 vpd::VpdTool l_vpdToolObj;
393 return l_vpdToolObj.fixSystemVpd();
394 }
395
396 if (!l_mfgCleanFlag->empty())
397 {
Souvik Roy63089422025-01-23 02:48:21 -0600398 return doMfgClean(l_mfgCleanConfirmFlag,
399 l_mfgCleanSyncBiosAttributesFlag);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500400 }
401
402 if (!l_dumpInventoryFlag->empty())
403 {
404 vpd::VpdTool l_vpdToolObj;
405 return l_vpdToolObj.dumpInventory(!l_dumpInventoryTableFlag->empty());
406 }
407
Anupama B R6be2c012025-01-23 02:59:27 -0600408 if (!l_forceResetFlag->empty())
409 {
410 return forceReset();
411 }
412
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500413 std::cout << l_app.help() << std::endl;
414 return vpd::constants::FAILURE;
415}