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
exitWithError(const char * err,char ** argv)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
main(int argc,char ** argv)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