1 /** 2 * Copyright © 2018 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "argument.hpp" 17 #include "ncsi_util.hpp" 18 19 #include <phosphor-logging/lg2.hpp> 20 21 #include <string> 22 #include <vector> 23 24 static void exitWithError(const char* err, char** argv) 25 { 26 phosphor::network::ncsi::ArgumentParser::usage(argv); 27 lg2::error("ERROR: {ERROR}", "ERROR", err); 28 exit(EXIT_FAILURE); 29 } 30 31 int main(int argc, char** argv) 32 { 33 using namespace phosphor::network; 34 using namespace phosphor::network::ncsi; 35 // Read arguments. 36 auto options = ArgumentParser(argc, argv); 37 int packageInt{}; 38 int channelInt{}; 39 int indexInt{}; 40 int operationInt{DEFAULT_VALUE}; 41 42 // Parse out interface argument. 43 auto ifIndex = (options)["index"]; 44 try 45 { 46 indexInt = stoi(ifIndex, nullptr); 47 } 48 catch (const std::exception& e) 49 { 50 exitWithError("Interface not specified.", argv); 51 } 52 53 if (indexInt < 0) 54 { 55 exitWithError("Interface value should be greater than equal to 0", 56 argv); 57 } 58 59 // Parse out package argument. 60 auto package = (options)["package"]; 61 try 62 { 63 packageInt = stoi(package, nullptr); 64 } 65 catch (const std::exception& e) 66 { 67 packageInt = DEFAULT_VALUE; 68 } 69 70 if (packageInt < 0) 71 { 72 packageInt = DEFAULT_VALUE; 73 } 74 75 // Parse out channel argument. 76 auto channel = (options)["channel"]; 77 try 78 { 79 channelInt = stoi(channel, nullptr); 80 } 81 catch (const std::exception& e) 82 { 83 channelInt = DEFAULT_VALUE; 84 } 85 86 if (channelInt < 0) 87 { 88 channelInt = DEFAULT_VALUE; 89 } 90 91 auto payloadStr = (options)["oem-payload"]; 92 if (!payloadStr.empty()) 93 { 94 std::string byte(2, '\0'); 95 std::vector<unsigned char> payload; 96 97 if (payloadStr.size() % 2) 98 exitWithError("Payload invalid: specify two hex digits per byte.", 99 argv); 100 101 // Parse the payload string (e.g. "50000001572100") to byte data 102 // The first two characters (i.e. "50") represent the Send Cmd Operation 103 // All remaining pairs, interpreted in hex radix, represent the command 104 // payload 105 int sendCmdSelect{}; 106 for (unsigned int i = 1; i < payloadStr.size(); i += 2) 107 { 108 byte[0] = payloadStr[i - 1]; 109 byte[1] = payloadStr[i]; 110 111 try 112 { 113 sendCmdSelect = stoi(byte, nullptr, 16); 114 } 115 catch (const std::exception& e) 116 { 117 exitWithError("Payload invalid.", argv); 118 } 119 if (i == 1) 120 { 121 operationInt = sendCmdSelect; 122 } 123 else 124 { 125 payload.push_back(sendCmdSelect); 126 } 127 } 128 129 if (operationInt == DEFAULT_VALUE) 130 { 131 exitWithError("No payload specified.", argv); 132 } 133 134 if (packageInt == DEFAULT_VALUE) 135 { 136 exitWithError("Package not specified.", argv); 137 } 138 139 return ncsi::sendOemCommand( 140 indexInt, packageInt, channelInt, operationInt, 141 std::span<const unsigned char>(payload.begin(), payload.end())); 142 } 143 else if ((options)["set"] == "true") 144 { 145 // Can not perform set operation without package. 146 if (packageInt == DEFAULT_VALUE) 147 { 148 exitWithError("Package not specified.", argv); 149 } 150 return ncsi::setChannel(indexInt, packageInt, channelInt); 151 } 152 else if ((options)["info"] == "true") 153 { 154 return ncsi::getInfo(indexInt, packageInt); 155 } 156 else if ((options)["clear"] == "true") 157 { 158 return ncsi::clearInterface(indexInt); 159 } 160 else if (!(options)["pmask"].empty()) 161 { 162 unsigned int mask{}; 163 try 164 { 165 size_t lastChar{}; 166 mask = std::stoul((options)["pmask"], &lastChar, 0); 167 if (lastChar < (options["pmask"].size())) 168 { 169 exitWithError("Package mask value is not valid", argv); 170 } 171 } 172 catch (const std::exception& e) 173 { 174 exitWithError("Package mask value is not valid", argv); 175 } 176 return ncsi::setPackageMask(indexInt, mask); 177 } 178 else if (!(options)["cmask"].empty()) 179 { 180 if (packageInt == DEFAULT_VALUE) 181 { 182 exitWithError("Package is not specified", argv); 183 } 184 unsigned int mask{}; 185 try 186 { 187 size_t lastChar{}; 188 mask = stoul((options)["cmask"], &lastChar, 0); 189 if (lastChar < (options["cmask"].size())) 190 { 191 exitWithError("Channel mask value is not valid", argv); 192 } 193 } 194 catch (const std::exception& e) 195 { 196 exitWithError("Channel mask value is not valid", argv); 197 } 198 return ncsi::setChannelMask(indexInt, packageInt, mask); 199 } 200 else 201 { 202 exitWithError("No Command specified", argv); 203 } 204 return 0; 205 } 206