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