11bbe3d1eSWilliam A. Kennington III /**
21bbe3d1eSWilliam A. Kennington III  * Copyright © 2018 IBM Corporation
31bbe3d1eSWilliam A. Kennington III  *
41bbe3d1eSWilliam A. Kennington III  * Licensed under the Apache License, Version 2.0 (the "License");
51bbe3d1eSWilliam A. Kennington III  * you may not use this file except in compliance with the License.
61bbe3d1eSWilliam A. Kennington III  * You may obtain a copy of the License at
71bbe3d1eSWilliam A. Kennington III  *
81bbe3d1eSWilliam A. Kennington III  *     http://www.apache.org/licenses/LICENSE-2.0
91bbe3d1eSWilliam A. Kennington III  *
101bbe3d1eSWilliam A. Kennington III  * Unless required by applicable law or agreed to in writing, software
111bbe3d1eSWilliam A. Kennington III  * distributed under the License is distributed on an "AS IS" BASIS,
121bbe3d1eSWilliam A. Kennington III  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131bbe3d1eSWilliam A. Kennington III  * See the License for the specific language governing permissions and
141bbe3d1eSWilliam A. Kennington III  * limitations under the License.
151bbe3d1eSWilliam A. Kennington III  */
161bbe3d1eSWilliam A. Kennington III #include "argument.hpp"
171bbe3d1eSWilliam A. Kennington III #include "ncsi_util.hpp"
181bbe3d1eSWilliam A. Kennington III 
19*d423bebfSJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
201bbe3d1eSWilliam A. Kennington III #include <string>
21fa1f5c03SEddie James #include <vector>
221bbe3d1eSWilliam A. Kennington III 
231bbe3d1eSWilliam A. Kennington III static void exitWithError(const char* err, char** argv)
241bbe3d1eSWilliam A. Kennington III {
251bbe3d1eSWilliam A. Kennington III     phosphor::network::ncsi::ArgumentParser::usage(argv);
26*d423bebfSJagpal Singh Gill     lg2::error("ERROR: {ERROR}", "ERROR", err);
271bbe3d1eSWilliam A. Kennington III     exit(EXIT_FAILURE);
281bbe3d1eSWilliam A. Kennington III }
291bbe3d1eSWilliam A. Kennington III 
301bbe3d1eSWilliam A. Kennington III int main(int argc, char** argv)
311bbe3d1eSWilliam A. Kennington III {
321bbe3d1eSWilliam A. Kennington III     using namespace phosphor::network;
331bbe3d1eSWilliam A. Kennington III     using namespace phosphor::network::ncsi;
341bbe3d1eSWilliam A. Kennington III     // Read arguments.
351bbe3d1eSWilliam A. Kennington III     auto options = ArgumentParser(argc, argv);
361bbe3d1eSWilliam A. Kennington III     int packageInt{};
371bbe3d1eSWilliam A. Kennington III     int channelInt{};
381bbe3d1eSWilliam A. Kennington III     int indexInt{};
391bbe3d1eSWilliam A. Kennington III 
401bbe3d1eSWilliam A. Kennington III     // Parse out interface argument.
411bbe3d1eSWilliam A. Kennington III     auto ifIndex = (options)["index"];
421bbe3d1eSWilliam A. Kennington III     try
431bbe3d1eSWilliam A. Kennington III     {
441bbe3d1eSWilliam A. Kennington III         indexInt = stoi(ifIndex, nullptr);
451bbe3d1eSWilliam A. Kennington III     }
461bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
471bbe3d1eSWilliam A. Kennington III     {
481bbe3d1eSWilliam A. Kennington III         exitWithError("Interface not specified.", argv);
491bbe3d1eSWilliam A. Kennington III     }
501bbe3d1eSWilliam A. Kennington III 
511bbe3d1eSWilliam A. Kennington III     if (indexInt < 0)
521bbe3d1eSWilliam A. Kennington III     {
531bbe3d1eSWilliam A. Kennington III         exitWithError("Interface value should be greater than equal to 0",
541bbe3d1eSWilliam A. Kennington III                       argv);
551bbe3d1eSWilliam A. Kennington III     }
561bbe3d1eSWilliam A. Kennington III 
571bbe3d1eSWilliam A. Kennington III     // Parse out package argument.
581bbe3d1eSWilliam A. Kennington III     auto package = (options)["package"];
591bbe3d1eSWilliam A. Kennington III     try
601bbe3d1eSWilliam A. Kennington III     {
611bbe3d1eSWilliam A. Kennington III         packageInt = stoi(package, nullptr);
621bbe3d1eSWilliam A. Kennington III     }
631bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
641bbe3d1eSWilliam A. Kennington III     {
651bbe3d1eSWilliam A. Kennington III         packageInt = DEFAULT_VALUE;
661bbe3d1eSWilliam A. Kennington III     }
671bbe3d1eSWilliam A. Kennington III 
681bbe3d1eSWilliam A. Kennington III     if (packageInt < 0)
691bbe3d1eSWilliam A. Kennington III     {
701bbe3d1eSWilliam A. Kennington III         packageInt = DEFAULT_VALUE;
711bbe3d1eSWilliam A. Kennington III     }
721bbe3d1eSWilliam A. Kennington III 
731bbe3d1eSWilliam A. Kennington III     // Parse out channel argument.
741bbe3d1eSWilliam A. Kennington III     auto channel = (options)["channel"];
751bbe3d1eSWilliam A. Kennington III     try
761bbe3d1eSWilliam A. Kennington III     {
771bbe3d1eSWilliam A. Kennington III         channelInt = stoi(channel, nullptr);
781bbe3d1eSWilliam A. Kennington III     }
791bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
801bbe3d1eSWilliam A. Kennington III     {
811bbe3d1eSWilliam A. Kennington III         channelInt = DEFAULT_VALUE;
821bbe3d1eSWilliam A. Kennington III     }
831bbe3d1eSWilliam A. Kennington III 
841bbe3d1eSWilliam A. Kennington III     if (channelInt < 0)
851bbe3d1eSWilliam A. Kennington III     {
861bbe3d1eSWilliam A. Kennington III         channelInt = DEFAULT_VALUE;
871bbe3d1eSWilliam A. Kennington III     }
881bbe3d1eSWilliam A. Kennington III 
89fa1f5c03SEddie James     auto payloadStr = (options)["oem-payload"];
90fa1f5c03SEddie James     if (!payloadStr.empty())
91fa1f5c03SEddie James     {
92fa1f5c03SEddie James         std::string byte(2, '\0');
93fa1f5c03SEddie James         std::vector<unsigned char> payload;
94fa1f5c03SEddie James 
95fa1f5c03SEddie James         if (payloadStr.size() % 2)
96fa1f5c03SEddie James             exitWithError("Payload invalid: specify two hex digits per byte.",
97fa1f5c03SEddie James                           argv);
98fa1f5c03SEddie James 
99fa1f5c03SEddie James         // Parse the payload string (e.g. "000001572100") to byte data
100fa1f5c03SEddie James         for (unsigned int i = 1; i < payloadStr.size(); i += 2)
101fa1f5c03SEddie James         {
102fa1f5c03SEddie James             byte[0] = payloadStr[i - 1];
103fa1f5c03SEddie James             byte[1] = payloadStr[i];
104fa1f5c03SEddie James 
105fa1f5c03SEddie James             try
106fa1f5c03SEddie James             {
107fa1f5c03SEddie James                 payload.push_back(stoi(byte, nullptr, 16));
108fa1f5c03SEddie James             }
109fa1f5c03SEddie James             catch (const std::exception& e)
110fa1f5c03SEddie James             {
111fa1f5c03SEddie James                 exitWithError("Payload invalid.", argv);
112fa1f5c03SEddie James             }
113fa1f5c03SEddie James         }
114fa1f5c03SEddie James 
115fa1f5c03SEddie James         if (payload.empty())
116fa1f5c03SEddie James         {
117fa1f5c03SEddie James             exitWithError("No payload specified.", argv);
118fa1f5c03SEddie James         }
119fa1f5c03SEddie James 
120fa1f5c03SEddie James         if (packageInt == DEFAULT_VALUE)
121fa1f5c03SEddie James         {
122fa1f5c03SEddie James             exitWithError("Package not specified.", argv);
123fa1f5c03SEddie James         }
124fa1f5c03SEddie James 
125fa1f5c03SEddie James         return ncsi::sendOemCommand(
126fa1f5c03SEddie James             indexInt, packageInt, channelInt,
127fa1f5c03SEddie James             std::span<const unsigned char>(payload.begin(), payload.end()));
128fa1f5c03SEddie James     }
129fa1f5c03SEddie James     else if ((options)["set"] == "true")
1301bbe3d1eSWilliam A. Kennington III     {
1311bbe3d1eSWilliam A. Kennington III         // Can not perform set operation without package.
1321bbe3d1eSWilliam A. Kennington III         if (packageInt == DEFAULT_VALUE)
1331bbe3d1eSWilliam A. Kennington III         {
1341bbe3d1eSWilliam A. Kennington III             exitWithError("Package not specified.", argv);
1351bbe3d1eSWilliam A. Kennington III         }
1361bbe3d1eSWilliam A. Kennington III         return ncsi::setChannel(indexInt, packageInt, channelInt);
1371bbe3d1eSWilliam A. Kennington III     }
1381bbe3d1eSWilliam A. Kennington III     else if ((options)["info"] == "true")
1391bbe3d1eSWilliam A. Kennington III     {
1401bbe3d1eSWilliam A. Kennington III         return ncsi::getInfo(indexInt, packageInt);
1411bbe3d1eSWilliam A. Kennington III     }
1421bbe3d1eSWilliam A. Kennington III     else if ((options)["clear"] == "true")
1431bbe3d1eSWilliam A. Kennington III     {
1441bbe3d1eSWilliam A. Kennington III         return ncsi::clearInterface(indexInt);
1451bbe3d1eSWilliam A. Kennington III     }
1461bbe3d1eSWilliam A. Kennington III     else
1471bbe3d1eSWilliam A. Kennington III     {
1481bbe3d1eSWilliam A. Kennington III         exitWithError("No Command specified", argv);
1491bbe3d1eSWilliam A. Kennington III     }
1501bbe3d1eSWilliam A. Kennington III     return 0;
1511bbe3d1eSWilliam A. Kennington III }
152