xref: /openbmc/openpower-vpd-parser/vpd_tool.cpp (revision 6555e7efc40c305e5c3c8863c3d1793f474ec7e2)
1 #include "vpd_tool_impl.hpp"
2 
3 #include <CLI/CLI.hpp>
4 #include <filesystem>
5 #include <fstream>
6 #include <iostream>
7 
8 using namespace CLI;
9 using namespace std;
10 namespace fs = std::filesystem;
11 using namespace openpower::vpd;
12 using json = nlohmann::json;
13 
14 int main(int argc, char** argv)
15 {
16     int rc = 0;
17     App app{"VPD Command line tool to dump the inventory and to read and "
18             "update the keywords"};
19 
20     string objectPath{};
21     string recordName{};
22     string keyword{};
23     string val{};
24     uint32_t offset = 0;
25 
26     auto object =
27         app.add_option("--object, -O", objectPath, "Enter the Object Path");
28     auto record =
29         app.add_option("--record, -R", recordName, "Enter the Record Name");
30     auto kw = app.add_option("--keyword, -K", keyword, "Enter the Keyword");
31     auto valOption = app.add_option(
32         "--value, -V", val,
33         "Enter the value. The value to be updated should be either in ascii or "
34         "in hex. ascii eg: 01234; hex eg: 0x30313233");
35     app.add_option("--seek, -s", offset,
36                    "User can provide VPD offset using this option. Default "
37                    "offset value is 0. Using --offset is optional and is valid "
38                    "only while using --Hardware/-H option.");
39 
40     auto dumpObjFlag =
41         app.add_flag("--dumpObject, -o",
42                      "Dump the given object from the inventory. { "
43                      "vpd-tool-exe --dumpObject/-o --object/-O object-name }")
44             ->needs(object);
45 
46     auto dumpInvFlag = app.add_flag(
47         "--dumpInventory, -i", "Dump all the inventory objects. { vpd-tool-exe "
48                                "--dumpInventory/-i }");
49 
50     auto readFlag =
51         app.add_flag("--readKeyword, -r",
52                      "Read the data of the given keyword. { "
53                      "vpd-tool-exe --readKeyword/-r --object/-O "
54                      "\"object-name\" --record/-R \"record-name\" --keyword/-K "
55                      "\"keyword-name\" }")
56             ->needs(object)
57             ->needs(record)
58             ->needs(kw);
59 
60     auto writeFlag =
61         app.add_flag(
62                "--writeKeyword, -w, --updateKeyword, -u",
63                "Update the value. { vpd-tool-exe "
64                "--writeKeyword/-w/--updateKeyword/-u "
65                "--object/-O object-name --record/-R record-name --keyword/-K "
66                "keyword-name --value/-V value-to-be-updated }")
67             ->needs(object)
68             ->needs(record)
69             ->needs(kw)
70             ->needs(valOption);
71 
72     auto forceResetFlag =
73         app.add_flag("--forceReset, -f, -F",
74                      "Force Collect for Hardware. CAUTION: Developer Only "
75                      "Option. { vpd-tool-exe --forceReset/-f/-F }");
76 
77     auto Hardware = app.add_flag(
78         "--Hardware, -H",
79         "This is a supplementary flag to read/write directly from/to hardware. "
80         "User should provide valid hardware/eeprom path (and not dbus object "
81         "path) in the -O/--object path. CAUTION: Developer Only Option");
82 
83     auto fixSystemVPDFlag = app.add_flag(
84         "--fixSystemVPD", "Use this option to interactively fix critical "
85                           "system VPD keywords {vpd-tool-exe --fixSystemVPD}");
86 
87     auto mfgClean =
88         app.add_flag("--mfgClean", "Flag to clean and reset specific keywords "
89                                    "on system VPD to its default value.");
90 
91     auto confirm =
92         app.add_flag("--yes", "Using this flag with --mfgClean option, assumes "
93                               "yes to proceed without confirmation.");
94 
95     CLI11_PARSE(app, argc, argv);
96 
97     ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
98     auto jsObject = json::parse(inventoryJson);
99 
100     try
101     {
102         if (*Hardware)
103         {
104             if (!fs::exists(objectPath)) // if dbus object path is given or
105                                          // invalid eeprom path is given
106             {
107                 string errorMsg = "Invalid EEPROM path : ";
108                 errorMsg += objectPath;
109                 errorMsg +=
110                     ". The given EEPROM path doesn't exist. Provide valid "
111                     "EEPROM path when -H flag is used. Refer help option. ";
112                 throw runtime_error(errorMsg);
113             }
114         }
115         if (*dumpObjFlag)
116         {
117             VpdTool vpdToolObj(move(objectPath));
118             vpdToolObj.dumpObject(jsObject);
119         }
120 
121         else if (*dumpInvFlag)
122         {
123             VpdTool vpdToolObj;
124             vpdToolObj.dumpInventory(jsObject);
125         }
126 
127         else if (*readFlag && !*Hardware)
128         {
129             VpdTool vpdToolObj(move(objectPath), move(recordName),
130                                move(keyword));
131             vpdToolObj.readKeyword();
132         }
133 
134         else if (*writeFlag && !*Hardware)
135         {
136             VpdTool vpdToolObj(move(objectPath), move(recordName),
137                                move(keyword), move(val));
138             rc = vpdToolObj.updateKeyword();
139         }
140 
141         else if (*forceResetFlag)
142         {
143             // Force reset the BMC only if the CEC is powered OFF.
144             if (getPowerState() ==
145                 "xyz.openbmc_project.State.Chassis.PowerState.Off")
146             {
147                 VpdTool vpdToolObj;
148                 vpdToolObj.forceReset(jsObject);
149             }
150             else
151             {
152                 std::cerr << "The chassis power state is not Off. Force reset "
153                              "operation is not allowed.";
154                 return -1;
155             }
156         }
157 
158         else if (*writeFlag && *Hardware)
159         {
160             VpdTool vpdToolObj(move(objectPath), move(recordName),
161                                move(keyword), move(val));
162             rc = vpdToolObj.updateHardware(offset);
163         }
164         else if (*readFlag && *Hardware)
165         {
166             VpdTool vpdToolObj(move(objectPath), move(recordName),
167                                move(keyword));
168             vpdToolObj.readKwFromHw(offset);
169         }
170         else if (*fixSystemVPDFlag)
171         {
172             VpdTool vpdToolObj;
173             rc = vpdToolObj.fixSystemVPD();
174         }
175         else if (*mfgClean)
176         {
177             if (!*confirm)
178             {
179                 std::string confirmation{};
180                 std::cout << "\nThis option resets some of the system VPD "
181                              "keywords to their default values. Do you really "
182                              "wish to proceed further?[yes/no]: ";
183                 std::cin >> confirmation;
184 
185                 if (confirmation != "yes")
186                 {
187                     return 0;
188                 }
189             }
190             VpdTool vpdToolObj;
191             rc = vpdToolObj.cleanSystemVPD();
192         }
193         else
194         {
195             throw runtime_error("One of the valid options is required. Refer "
196                                 "--help for list of options.");
197         }
198     }
199 
200     catch (const exception& e)
201     {
202         cerr << e.what();
203 
204         if (*Hardware)
205         {
206             std::cerr << "\nDid you provide a valid offset? By default VPD "
207                          "offset is taken as 0. To input offset, use --offset. "
208                          "Refer vpd-tool help.";
209         }
210         rc = -1;
211     }
212 
213     return rc;
214 }
215