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