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
41 // Parse out interface argument.
42 auto ifIndex = (options)["index"];
43 try
44 {
45 indexInt = stoi(ifIndex, nullptr);
46 }
47 catch (const std::exception& e)
48 {
49 exitWithError("Interface not specified.", argv);
50 }
51
52 if (indexInt < 0)
53 {
54 exitWithError("Interface value should be greater than equal to 0",
55 argv);
56 }
57
58 // Parse out package argument.
59 auto package = (options)["package"];
60 try
61 {
62 packageInt = stoi(package, nullptr);
63 }
64 catch (const std::exception& e)
65 {
66 packageInt = DEFAULT_VALUE;
67 }
68
69 if (packageInt < 0)
70 {
71 packageInt = DEFAULT_VALUE;
72 }
73
74 // Parse out channel argument.
75 auto channel = (options)["channel"];
76 try
77 {
78 channelInt = stoi(channel, nullptr);
79 }
80 catch (const std::exception& e)
81 {
82 channelInt = DEFAULT_VALUE;
83 }
84
85 if (channelInt < 0)
86 {
87 channelInt = DEFAULT_VALUE;
88 }
89
90 auto payloadStr = (options)["oem-payload"];
91 if (!payloadStr.empty())
92 {
93 std::string byte(2, '\0');
94 std::vector<unsigned char> payload;
95
96 if (payloadStr.size() % 2)
97 exitWithError("Payload invalid: specify two hex digits per byte.",
98 argv);
99
100 // Parse the payload string (e.g. "000001572100") to byte data
101 for (unsigned int i = 1; i < payloadStr.size(); i += 2)
102 {
103 byte[0] = payloadStr[i - 1];
104 byte[1] = payloadStr[i];
105
106 try
107 {
108 payload.push_back(stoi(byte, nullptr, 16));
109 }
110 catch (const std::exception& e)
111 {
112 exitWithError("Payload invalid.", argv);
113 }
114 }
115
116 if (payload.empty())
117 {
118 exitWithError("No payload specified.", argv);
119 }
120
121 if (packageInt == DEFAULT_VALUE)
122 {
123 exitWithError("Package not specified.", argv);
124 }
125
126 return ncsi::sendOemCommand(
127 indexInt, packageInt, channelInt,
128 std::span<const unsigned char>(payload.begin(), payload.end()));
129 }
130 else if ((options)["set"] == "true")
131 {
132 // Can not perform set operation without package.
133 if (packageInt == DEFAULT_VALUE)
134 {
135 exitWithError("Package not specified.", argv);
136 }
137 return ncsi::setChannel(indexInt, packageInt, channelInt);
138 }
139 else if ((options)["info"] == "true")
140 {
141 return ncsi::getInfo(indexInt, packageInt);
142 }
143 else if ((options)["clear"] == "true")
144 {
145 return ncsi::clearInterface(indexInt);
146 }
147 else
148 {
149 exitWithError("No Command specified", argv);
150 }
151 return 0;
152 }
153