blob: c7a846f8a56c16d4490847de0ec30cf4b1c20157 [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/**
11 * @brief API to perform manufacturing clean.
12 *
13 * @param[in] i_mfgCleanConfirmFlag - Confirmation flag to perform manufacturing
14 * clean.
Souvik Roy63089422025-01-23 02:48:21 -060015 * @param[in] i_syncBiosAttributesFlag - Flag which specifies whether
16 * BIOS attribute related keywords need to be synced from BIOS Config Manager
17 * instead of being reset to default value.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050018 *
19 * @return Status returned by cleanSystemVpd operation, success otherwise.
20 */
Souvik Roy63089422025-01-23 02:48:21 -060021int doMfgClean(const auto& i_mfgCleanConfirmFlag,
22 const auto& i_syncBiosAttributesFlag)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050023{
24 if (i_mfgCleanConfirmFlag->empty())
25 {
26 constexpr auto MAX_CONFIRMATION_STR_LENGTH{3};
27 std::string l_confirmation{};
28 std::cout
29 << "This option resets some of the system VPD keywords to their default values. Do you really wish to proceed further?[yes/no]:";
30 std::cin >> std::setw(MAX_CONFIRMATION_STR_LENGTH) >> l_confirmation;
31
32 if (l_confirmation != "yes")
33 {
34 return vpd::constants::SUCCESS;
35 }
36 }
37
38 vpd::VpdTool l_vpdToolObj;
Souvik Roy63089422025-01-23 02:48:21 -060039 return l_vpdToolObj.cleanSystemVpd(!i_syncBiosAttributesFlag->empty());
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050040}
41
42/**
43 * @brief API to write keyword's value.
44 *
45 * @param[in] i_hardwareFlag - Flag to perform write on hardware.
46 * @param[in] i_keywordValueOption - Option to read keyword value from command.
47 * @param[in] i_vpdPath - DBus object path or EEPROM path.
48 * @param[in] i_recordName - Record to be updated.
49 * @param[in] i_keywordName - Keyword to be updated.
50 * @param[in] i_keywordValue - Value to be updated in keyword.
51 *
52 * @return Status of writeKeyword operation, failure otherwise.
53 */
54int writeKeyword(const auto& i_hardwareFlag, const auto& i_keywordValueOption,
55 const std::string& i_vpdPath, const std::string& i_recordName,
56 const std::string& i_keywordName,
57 const std::string& i_keywordValue)
58{
59 std::error_code l_ec;
60
61 if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
62 {
63 std::cerr << "Given EEPROM file path doesn't exist : " + i_vpdPath
64 << std::endl;
65 return vpd::constants::FAILURE;
66 }
67
68 if (l_ec)
69 {
70 std::cerr << "filesystem call exists failed for file: " << i_vpdPath
71 << ", reason: " + l_ec.message() << std::endl;
72 return vpd::constants::FAILURE;
73 }
74
75 if (!i_keywordValueOption->empty() && i_keywordValue.empty())
76 {
77 std::cerr
78 << "Please provide keyword value.\nUse --value/--file to give "
79 "keyword value. Refer --help."
80 << std::endl;
81 return vpd::constants::FAILURE;
82 }
83
84 if (i_keywordValueOption->empty())
85 {
86 std::cerr
87 << "Please provide keyword value.\nUse --value/--file to give "
88 "keyword value. Refer --help."
89 << std::endl;
90 return vpd::constants::FAILURE;
91 }
92
93 vpd::VpdTool l_vpdToolObj;
94 return l_vpdToolObj.writeKeyword(i_vpdPath, i_recordName, i_keywordName,
95 i_keywordValue, !i_hardwareFlag->empty());
96}
97
98/**
99 * @brief API to read keyword's value.
100 *
101 * @param[in] i_hardwareFlag - Flag to perform write on hardware.
102 * @param[in] i_vpdPath - DBus object path or EEPROM path.
103 * @param[in] i_recordName - Record to be updated.
104 * @param[in] i_keywordName - Keyword to be updated.
105 * @param[in] i_filePath - File path to save keyword's read value.
106 *
Anupama B Rd3539902025-01-20 05:10:00 -0600107 * @return On success return 0, otherwise return -1.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500108 */
109int readKeyword(const auto& i_hardwareFlag, const std::string& i_vpdPath,
110 const std::string& i_recordName,
111 const std::string& i_keywordName, const std::string& i_filePath)
112{
113 std::error_code l_ec;
114
115 if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
116 {
117 std::string l_errMessage{
118 "Given EEPROM file path doesn't exist : " + i_vpdPath};
119
120 if (l_ec)
121 {
122 l_errMessage += ". filesystem call exists failed, reason: " +
123 l_ec.message();
124 }
125
126 std::cerr << l_errMessage << std::endl;
127 return vpd::constants::FAILURE;
128 }
129
130 bool l_isHardwareOperation = (!i_hardwareFlag->empty() ? true : false);
131
132 vpd::VpdTool l_vpdToolObj;
133 return l_vpdToolObj.readKeyword(i_vpdPath, i_recordName, i_keywordName,
134 l_isHardwareOperation, i_filePath);
135}
136
137/**
138 * @brief API to check option value pair in the tool command.
139 *
140 * In VPD tool command, some of the option(s) mandate values to be passed along
141 * with the option. This API based on option, detects those mandatory value(s).
142 *
143 * @param[in] i_objectOption - Option to pass object path.
144 * @param[in] i_vpdPath - Object path, DBus or EEPROM.
145 * @param[in] i_recordOption - Option to pass record name.
146 * @param[in] i_recordName - Record name.
147 * @param[in] i_keywordOption - Option to pass keyword name.
148 * @param[in] i_keywordName - Keyword name.
Anupama B R951d6602025-01-18 09:52:33 -0600149 * @param[in] i_fileOption - Option to pass file path.
150 * @param[in] i_filePath - File path.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500151 *
152 * @return Success if corresponding value is found against option, failure
153 * otherwise.
154 */
155int checkOptionValuePair(const auto& i_objectOption, const auto& i_vpdPath,
156 const auto& i_recordOption, const auto& i_recordName,
Anupama B R951d6602025-01-18 09:52:33 -0600157 const auto& i_keywordOption, const auto& i_keywordName,
158 const auto& i_fileOption, const auto& i_filePath)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500159{
160 if (!i_objectOption->empty() && i_vpdPath.empty())
161 {
162 std::cout << "Given path is empty." << std::endl;
163 return vpd::constants::FAILURE;
164 }
165
166 if (!i_recordOption->empty() &&
167 (i_recordName.size() != vpd::constants::RECORD_SIZE))
168 {
169 std::cerr << "Record " << i_recordName << " is not supported."
170 << std::endl;
171 return vpd::constants::FAILURE;
172 }
173
174 if (!i_keywordOption->empty() &&
175 (i_keywordName.size() != vpd::constants::KEYWORD_SIZE))
176 {
177 std::cerr << "Keyword " << i_keywordName << " is not supported."
178 << std::endl;
179 return vpd::constants::FAILURE;
180 }
181
Anupama B R951d6602025-01-18 09:52:33 -0600182 if (!i_fileOption->empty() && i_filePath.empty())
183 {
184 std::cout << "File path is empty." << std::endl;
185 return vpd::constants::FAILURE;
186 }
187
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500188 return vpd::constants::SUCCESS;
189}
190
191/**
192 * @brief API to create app footer.
193 *
194 * @param[in] i_app - CLI::App object.
195 */
196void updateFooter(CLI::App& i_app)
197{
198 i_app.footer(
199 "Read:\n"
200 " IPZ Format:\n"
201 " From DBus to console: "
202 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name>\n"
203 " From DBus to file: "
204 "vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
205 " From hardware to console: "
206 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name>\n"
207 " From hardware to file: "
208 "vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
209 "Write:\n"
210 " IPZ Format:\n"
211 " On DBus: "
212 "vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
213 " On DBus, take keyword value from file:\n"
214 " vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
215 " On hardware: "
216 "vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
217 " On hardware, take keyword value from file:\n"
218 " vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
219 "Dump Object:\n"
220 " From DBus to console: "
221 "vpd-tool -o -O <DBus Object Path>\n"
222 "Fix System VPD:\n"
223 " vpd-tool --fixSystemVPD\n"
224 "MfgClean:\n"
225 " Flag to clean and reset specific keywords on system VPD to its default value.\n"
226 " vpd-tool --mfgClean\n"
Souvik Roy63089422025-01-23 02:48:21 -0600227 " To sync BIOS attribute related keywords with BIOS Config Manager:\n"
228 " vpd-tool --mfgClean --syncBiosAttributes\n"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500229 "Dump Inventory:\n"
230 " From DBus to console in JSON format: "
231 "vpd-tool -i\n"
232 " From DBus to console in Table format: "
233 "vpd-tool -i -t\n");
234}
235
236int main(int argc, char** argv)
237{
238 CLI::App l_app{"VPD Command Line Tool"};
239
240 std::string l_vpdPath{};
241 std::string l_recordName{};
242 std::string l_keywordName{};
243 std::string l_filePath{};
244 std::string l_keywordValue{};
245
246 updateFooter(l_app);
247
248 auto l_objectOption =
249 l_app.add_option("--object, -O", l_vpdPath, "File path");
250 auto l_recordOption =
251 l_app.add_option("--record, -R", l_recordName, "Record name");
252 auto l_keywordOption =
253 l_app.add_option("--keyword, -K", l_keywordName, "Keyword name");
254
Anupama B R951d6602025-01-18 09:52:33 -0600255 auto l_fileOption =
256 l_app.add_option("--file", l_filePath, "Absolute file path");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500257
258 auto l_keywordValueOption =
259 l_app.add_option("--value, -V", l_keywordValue,
260 "Keyword value in ascii/hex format."
261 " ascii ex: 01234; hex ex: 0x30313233");
262
263 auto l_hardwareFlag =
264 l_app.add_flag("--Hardware, -H", "CAUTION: Developer only option.");
265
266 auto l_readFlag = l_app.add_flag("--readKeyword, -r", "Read keyword")
267 ->needs(l_objectOption)
268 ->needs(l_recordOption)
269 ->needs(l_keywordOption);
270
271 auto l_writeFlag =
272 l_app
273 .add_flag(
274 "--writeKeyword, -w,--updateKeyword, -u",
275 "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")
276 ->needs(l_objectOption)
277 ->needs(l_recordOption)
278 ->needs(l_keywordOption);
279
280 // ToDo: Take offset value from user for hardware path.
281
282 auto l_dumpObjFlag =
283 l_app
284 .add_flag("--dumpObject, -o",
285 "Dump specific properties of an inventory object")
286 ->needs(l_objectOption);
287
288 auto l_fixSystemVpdFlag = l_app.add_flag(
289 "--fixSystemVPD",
290 "Use this option to interactively fix critical system VPD keywords");
291 auto l_dumpInventoryFlag =
292 l_app.add_flag("--dumpInventory, -i", "Dump all the inventory objects");
293
294 auto l_mfgCleanFlag = l_app.add_flag(
295 "--mfgClean", "Manufacturing clean on system VPD keyword");
296
297 auto l_mfgCleanConfirmFlag = l_app.add_flag(
298 "--yes", "Using this flag with --mfgClean option, assumes "
299 "yes to proceed without confirmation.");
300
301 auto l_dumpInventoryTableFlag =
302 l_app.add_flag("--table, -t", "Dump inventory in table format");
303
Souvik Roy63089422025-01-23 02:48:21 -0600304 auto l_mfgCleanSyncBiosAttributesFlag = l_app.add_flag(
305 "--syncBiosAttributes, -s",
306 "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");
307
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500308 CLI11_PARSE(l_app, argc, argv);
309
310 if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
Anupama B R951d6602025-01-18 09:52:33 -0600311 l_recordName, l_keywordOption, l_keywordName,
312 l_fileOption, l_filePath) ==
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500313 vpd::constants::FAILURE)
314 {
315 return vpd::constants::FAILURE;
316 }
317
318 if (!l_readFlag->empty())
319 {
320 return readKeyword(l_hardwareFlag, l_vpdPath, l_recordName,
321 l_keywordName, l_filePath);
322 }
323
324 if (!l_writeFlag->empty())
325 {
Anupama B R951d6602025-01-18 09:52:33 -0600326 if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
327 (!l_keywordValueOption->empty() && !l_fileOption->empty()))
328 {
329 std::cerr
330 << "Please provide keyword value.\nUse --value/--file to give "
331 "keyword value. Refer --help."
332 << std::endl;
333 return vpd::constants::FAILURE;
334 }
335
336 if (!l_fileOption->empty())
337 {
338 l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
339 if (l_keywordValue.empty())
340 {
341 return vpd::constants::FAILURE;
342 }
343
344 return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
345 l_recordName, l_keywordName, l_keywordValue);
346 }
347
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500348 return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
349 l_recordName, l_keywordName, l_keywordValue);
350 }
351
352 if (!l_dumpObjFlag->empty())
353 {
354 vpd::VpdTool l_vpdToolObj;
355 return l_vpdToolObj.dumpObject(l_vpdPath);
356 }
357
358 if (!l_fixSystemVpdFlag->empty())
359 {
360 vpd::VpdTool l_vpdToolObj;
361 return l_vpdToolObj.fixSystemVpd();
362 }
363
364 if (!l_mfgCleanFlag->empty())
365 {
Souvik Roy63089422025-01-23 02:48:21 -0600366 return doMfgClean(l_mfgCleanConfirmFlag,
367 l_mfgCleanSyncBiosAttributesFlag);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500368 }
369
370 if (!l_dumpInventoryFlag->empty())
371 {
372 vpd::VpdTool l_vpdToolObj;
373 return l_vpdToolObj.dumpInventory(!l_dumpInventoryTableFlag->empty());
374 }
375
376 std::cout << l_app.help() << std::endl;
377 return vpd::constants::FAILURE;
378}