blob: d5c6fc517a92f6473dd79bc15fa258caaf1a6009 [file] [log] [blame]
Ratan Guptab38401b2018-03-16 12:44:26 +05301/**
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 */
Ratan Guptaed5d7ff2018-03-23 00:27:52 +053016#include "argument.hpp"
17#include "ncsi_util.hpp"
18
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -070019#include <phosphor-logging/lg2.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050020
Ratan Guptaed5d7ff2018-03-23 00:27:52 +053021#include <string>
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050022#include <vector>
Ratan Guptaed5d7ff2018-03-23 00:27:52 +053023
24static void exitWithError(const char* err, char** argv)
25{
26 phosphor::network::ncsi::ArgumentParser::usage(argv);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -070027 lg2::error("ERROR: {ERROR}", "ERROR", err);
Ratan Guptaed5d7ff2018-03-23 00:27:52 +053028 exit(EXIT_FAILURE);
29}
30
Jeremy Kerr7f7c0852024-08-08 11:32:55 +080031static void printInfo(phosphor::network::ncsi::InterfaceInfo& info)
32{
33 using namespace phosphor::network::ncsi;
34
35 for (PackageInfo& pkg : info.packages)
36 {
37 lg2::debug("Package id : {ID}", "ID", pkg.id);
38 if (pkg.forced)
39 {
40 lg2::debug(" package is forced");
41 }
42 for (ChannelInfo& chan : pkg.channels)
43 {
44 lg2::debug(" Channel id : {ID}", "ID", chan.id);
45 if (chan.forced)
46 {
47 lg2::debug(" channel is forced");
48 }
49 if (chan.active)
50 {
51 lg2::debug(" channel is active");
52 }
53
54 lg2::debug(" version {MAJOR}.{MINOR} ({STR})", "MAJOR",
55 chan.version_major, "MINOR", chan.version_minor, "STR",
56 chan.version);
57
58 lg2::debug(" link state {LINK}", "LINK", lg2::hex,
59 chan.link_state);
60
61 auto& vlans = chan.vlan_ids;
62
63 if (!vlans.empty())
64 {
65 lg2::debug(" Actve VLAN IDs:");
66 for (uint16_t vlan : vlans)
67 {
68 lg2::debug(" VID: {VLAN_ID}", "VLAN_ID", vlan);
69 }
70 }
71 }
72 }
73}
74
Ratan Guptab38401b2018-03-16 12:44:26 +053075int main(int argc, char** argv)
76{
Ratan Guptaed5d7ff2018-03-23 00:27:52 +053077 using namespace phosphor::network;
78 using namespace phosphor::network::ncsi;
79 // Read arguments.
80 auto options = ArgumentParser(argc, argv);
Gunnar Mills57d9c502018-09-14 14:42:34 -050081 int packageInt{};
82 int channelInt{};
83 int indexInt{};
Johnathan Mantey1ebea282024-02-15 10:26:06 -080084 int operationInt{DEFAULT_VALUE};
Ratan Guptaed5d7ff2018-03-23 00:27:52 +053085
86 // Parse out interface argument.
87 auto ifIndex = (options)["index"];
88 try
89 {
90 indexInt = stoi(ifIndex, nullptr);
91 }
92 catch (const std::exception& e)
93 {
94 exitWithError("Interface not specified.", argv);
95 }
96
97 if (indexInt < 0)
98 {
Gunnar Mills57d9c502018-09-14 14:42:34 -050099 exitWithError("Interface value should be greater than equal to 0",
100 argv);
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530101 }
102
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800103 Interface interface{indexInt};
104
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530105 // Parse out package argument.
106 auto package = (options)["package"];
107 try
108 {
109 packageInt = stoi(package, nullptr);
110 }
111 catch (const std::exception& e)
112 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500113 packageInt = DEFAULT_VALUE;
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530114 }
115
116 if (packageInt < 0)
117 {
118 packageInt = DEFAULT_VALUE;
119 }
120
121 // Parse out channel argument.
122 auto channel = (options)["channel"];
123 try
124 {
125 channelInt = stoi(channel, nullptr);
126 }
127 catch (const std::exception& e)
128 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500129 channelInt = DEFAULT_VALUE;
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530130 }
131
132 if (channelInt < 0)
133 {
134 channelInt = DEFAULT_VALUE;
135 }
136
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500137 auto payloadStr = (options)["oem-payload"];
138 if (!payloadStr.empty())
139 {
140 std::string byte(2, '\0');
141 std::vector<unsigned char> payload;
142
143 if (payloadStr.size() % 2)
144 exitWithError("Payload invalid: specify two hex digits per byte.",
145 argv);
146
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800147 // Parse the payload string (e.g. "50000001572100") to byte data
148 // The first two characters (i.e. "50") represent the Send Cmd Operation
149 // All remaining pairs, interpreted in hex radix, represent the command
150 // payload
151 int sendCmdSelect{};
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500152 for (unsigned int i = 1; i < payloadStr.size(); i += 2)
153 {
154 byte[0] = payloadStr[i - 1];
155 byte[1] = payloadStr[i];
156
157 try
158 {
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800159 sendCmdSelect = stoi(byte, nullptr, 16);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500160 }
161 catch (const std::exception& e)
162 {
163 exitWithError("Payload invalid.", argv);
164 }
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800165 if (i == 1)
166 {
167 operationInt = sendCmdSelect;
168 }
169 else
170 {
171 payload.push_back(sendCmdSelect);
172 }
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500173 }
174
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800175 if (operationInt == DEFAULT_VALUE)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500176 {
177 exitWithError("No payload specified.", argv);
178 }
179
180 if (packageInt == DEFAULT_VALUE)
181 {
182 exitWithError("Package not specified.", argv);
183 }
184
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800185 return interface.sendOemCommand(
186 packageInt, channelInt, operationInt,
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500187 std::span<const unsigned char>(payload.begin(), payload.end()));
188 }
189 else if ((options)["set"] == "true")
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530190 {
Gunnar Mills6af61442018-04-08 14:50:06 -0500191 // Can not perform set operation without package.
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530192 if (packageInt == DEFAULT_VALUE)
193 {
194 exitWithError("Package not specified.", argv);
195 }
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800196 return interface.setChannel(packageInt, channelInt);
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530197 }
198 else if ((options)["info"] == "true")
199 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800200 auto info = interface.getInfo(packageInt);
201 if (!info)
202 {
203 return EXIT_FAILURE;
204 }
205 printInfo(*info);
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530206 }
207 else if ((options)["clear"] == "true")
208 {
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800209 return interface.clearInterface();
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530210 }
Johnathan Mantey5a456062024-02-15 08:45:08 -0800211 else if (!(options)["pmask"].empty())
212 {
213 unsigned int mask{};
214 try
215 {
216 size_t lastChar{};
217 mask = std::stoul((options)["pmask"], &lastChar, 0);
218 if (lastChar < (options["pmask"].size()))
219 {
220 exitWithError("Package mask value is not valid", argv);
221 }
222 }
223 catch (const std::exception& e)
224 {
225 exitWithError("Package mask value is not valid", argv);
226 }
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800227 return interface.setPackageMask(mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800228 }
229 else if (!(options)["cmask"].empty())
230 {
231 if (packageInt == DEFAULT_VALUE)
232 {
233 exitWithError("Package is not specified", argv);
234 }
235 unsigned int mask{};
236 try
237 {
238 size_t lastChar{};
239 mask = stoul((options)["cmask"], &lastChar, 0);
240 if (lastChar < (options["cmask"].size()))
241 {
242 exitWithError("Channel mask value is not valid", argv);
243 }
244 }
245 catch (const std::exception& e)
246 {
247 exitWithError("Channel mask value is not valid", argv);
248 }
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800249 return interface.setChannelMask(packageInt, mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800250 }
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530251 else
252 {
253 exitWithError("No Command specified", argv);
254 }
Ratan Guptab38401b2018-03-16 12:44:26 +0530255 return 0;
256}