blob: fa99c3bf60d0997a5eeb4593a8e851bbf14677b8 [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 R951d6602025-01-18 09:52:33 -0600280 auto l_fileOption =
281 l_app.add_option("--file", l_filePath, "Absolute file path");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500282
283 auto l_keywordValueOption =
284 l_app.add_option("--value, -V", l_keywordValue,
285 "Keyword value in ascii/hex format."
286 " ascii ex: 01234; hex ex: 0x30313233");
287
288 auto l_hardwareFlag =
289 l_app.add_flag("--Hardware, -H", "CAUTION: Developer only option.");
290
291 auto l_readFlag = l_app.add_flag("--readKeyword, -r", "Read keyword")
292 ->needs(l_objectOption)
293 ->needs(l_recordOption)
294 ->needs(l_keywordOption);
295
296 auto l_writeFlag =
297 l_app
298 .add_flag(
299 "--writeKeyword, -w,--updateKeyword, -u",
300 "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")
301 ->needs(l_objectOption)
302 ->needs(l_recordOption)
303 ->needs(l_keywordOption);
304
305 // ToDo: Take offset value from user for hardware path.
306
307 auto l_dumpObjFlag =
308 l_app
309 .add_flag("--dumpObject, -o",
310 "Dump specific properties of an inventory object")
311 ->needs(l_objectOption);
312
313 auto l_fixSystemVpdFlag = l_app.add_flag(
314 "--fixSystemVPD",
315 "Use this option to interactively fix critical system VPD keywords");
316 auto l_dumpInventoryFlag =
317 l_app.add_flag("--dumpInventory, -i", "Dump all the inventory objects");
318
319 auto l_mfgCleanFlag = l_app.add_flag(
320 "--mfgClean", "Manufacturing clean on system VPD keyword");
321
322 auto l_mfgCleanConfirmFlag = l_app.add_flag(
323 "--yes", "Using this flag with --mfgClean option, assumes "
324 "yes to proceed without confirmation.");
325
326 auto l_dumpInventoryTableFlag =
327 l_app.add_flag("--table, -t", "Dump inventory in table format");
328
Souvik Roy63089422025-01-23 02:48:21 -0600329 auto l_mfgCleanSyncBiosAttributesFlag = l_app.add_flag(
330 "--syncBiosAttributes, -s",
331 "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");
332
Anupama B R6be2c012025-01-23 02:59:27 -0600333 auto l_forceResetFlag = l_app.add_flag(
334 "--forceReset, -f, -F",
335 "Force collect for hardware. CAUTION: Developer only option.");
336
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500337 CLI11_PARSE(l_app, argc, argv);
338
339 if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
Anupama B R951d6602025-01-18 09:52:33 -0600340 l_recordName, l_keywordOption, l_keywordName,
341 l_fileOption, l_filePath) ==
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500342 vpd::constants::FAILURE)
343 {
344 return vpd::constants::FAILURE;
345 }
346
347 if (!l_readFlag->empty())
348 {
349 return readKeyword(l_hardwareFlag, l_vpdPath, l_recordName,
350 l_keywordName, l_filePath);
351 }
352
353 if (!l_writeFlag->empty())
354 {
Anupama B R951d6602025-01-18 09:52:33 -0600355 if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
356 (!l_keywordValueOption->empty() && !l_fileOption->empty()))
357 {
358 std::cerr
359 << "Please provide keyword value.\nUse --value/--file to give "
360 "keyword value. Refer --help."
361 << std::endl;
362 return vpd::constants::FAILURE;
363 }
364
365 if (!l_fileOption->empty())
366 {
367 l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
368 if (l_keywordValue.empty())
369 {
370 return vpd::constants::FAILURE;
371 }
372
373 return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
374 l_recordName, l_keywordName, l_keywordValue);
375 }
376
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500377 return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
378 l_recordName, l_keywordName, l_keywordValue);
379 }
380
381 if (!l_dumpObjFlag->empty())
382 {
383 vpd::VpdTool l_vpdToolObj;
384 return l_vpdToolObj.dumpObject(l_vpdPath);
385 }
386
387 if (!l_fixSystemVpdFlag->empty())
388 {
389 vpd::VpdTool l_vpdToolObj;
390 return l_vpdToolObj.fixSystemVpd();
391 }
392
393 if (!l_mfgCleanFlag->empty())
394 {
Souvik Roy63089422025-01-23 02:48:21 -0600395 return doMfgClean(l_mfgCleanConfirmFlag,
396 l_mfgCleanSyncBiosAttributesFlag);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500397 }
398
399 if (!l_dumpInventoryFlag->empty())
400 {
401 vpd::VpdTool l_vpdToolObj;
402 return l_vpdToolObj.dumpInventory(!l_dumpInventoryTableFlag->empty());
403 }
404
Anupama B R6be2c012025-01-23 02:59:27 -0600405 if (!l_forceResetFlag->empty())
406 {
407 return forceReset();
408 }
409
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500410 std::cout << l_app.help() << std::endl;
411 return vpd::constants::FAILURE;
412}