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