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