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 
19d423bebfSJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
20*89d734b9SPatrick Williams 
211bbe3d1eSWilliam A. Kennington III #include <string>
22fa1f5c03SEddie James #include <vector>
231bbe3d1eSWilliam A. Kennington III 
exitWithError(const char * err,char ** argv)241bbe3d1eSWilliam A. Kennington III static void exitWithError(const char* err, char** argv)
251bbe3d1eSWilliam A. Kennington III {
261bbe3d1eSWilliam A. Kennington III     phosphor::network::ncsi::ArgumentParser::usage(argv);
27d423bebfSJagpal Singh Gill     lg2::error("ERROR: {ERROR}", "ERROR", err);
281bbe3d1eSWilliam A. Kennington III     exit(EXIT_FAILURE);
291bbe3d1eSWilliam A. Kennington III }
301bbe3d1eSWilliam A. Kennington III 
main(int argc,char ** argv)311bbe3d1eSWilliam A. Kennington III int main(int argc, char** argv)
321bbe3d1eSWilliam A. Kennington III {
331bbe3d1eSWilliam A. Kennington III     using namespace phosphor::network;
341bbe3d1eSWilliam A. Kennington III     using namespace phosphor::network::ncsi;
351bbe3d1eSWilliam A. Kennington III     // Read arguments.
361bbe3d1eSWilliam A. Kennington III     auto options = ArgumentParser(argc, argv);
371bbe3d1eSWilliam A. Kennington III     int packageInt{};
381bbe3d1eSWilliam A. Kennington III     int channelInt{};
391bbe3d1eSWilliam A. Kennington III     int indexInt{};
401bbe3d1eSWilliam A. Kennington III 
411bbe3d1eSWilliam A. Kennington III     // Parse out interface argument.
421bbe3d1eSWilliam A. Kennington III     auto ifIndex = (options)["index"];
431bbe3d1eSWilliam A. Kennington III     try
441bbe3d1eSWilliam A. Kennington III     {
451bbe3d1eSWilliam A. Kennington III         indexInt = stoi(ifIndex, nullptr);
461bbe3d1eSWilliam A. Kennington III     }
471bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
481bbe3d1eSWilliam A. Kennington III     {
491bbe3d1eSWilliam A. Kennington III         exitWithError("Interface not specified.", argv);
501bbe3d1eSWilliam A. Kennington III     }
511bbe3d1eSWilliam A. Kennington III 
521bbe3d1eSWilliam A. Kennington III     if (indexInt < 0)
531bbe3d1eSWilliam A. Kennington III     {
541bbe3d1eSWilliam A. Kennington III         exitWithError("Interface value should be greater than equal to 0",
551bbe3d1eSWilliam A. Kennington III                       argv);
561bbe3d1eSWilliam A. Kennington III     }
571bbe3d1eSWilliam A. Kennington III 
581bbe3d1eSWilliam A. Kennington III     // Parse out package argument.
591bbe3d1eSWilliam A. Kennington III     auto package = (options)["package"];
601bbe3d1eSWilliam A. Kennington III     try
611bbe3d1eSWilliam A. Kennington III     {
621bbe3d1eSWilliam A. Kennington III         packageInt = stoi(package, nullptr);
631bbe3d1eSWilliam A. Kennington III     }
641bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
651bbe3d1eSWilliam A. Kennington III     {
661bbe3d1eSWilliam A. Kennington III         packageInt = DEFAULT_VALUE;
671bbe3d1eSWilliam A. Kennington III     }
681bbe3d1eSWilliam A. Kennington III 
691bbe3d1eSWilliam A. Kennington III     if (packageInt < 0)
701bbe3d1eSWilliam A. Kennington III     {
711bbe3d1eSWilliam A. Kennington III         packageInt = DEFAULT_VALUE;
721bbe3d1eSWilliam A. Kennington III     }
731bbe3d1eSWilliam A. Kennington III 
741bbe3d1eSWilliam A. Kennington III     // Parse out channel argument.
751bbe3d1eSWilliam A. Kennington III     auto channel = (options)["channel"];
761bbe3d1eSWilliam A. Kennington III     try
771bbe3d1eSWilliam A. Kennington III     {
781bbe3d1eSWilliam A. Kennington III         channelInt = stoi(channel, nullptr);
791bbe3d1eSWilliam A. Kennington III     }
801bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
811bbe3d1eSWilliam A. Kennington III     {
821bbe3d1eSWilliam A. Kennington III         channelInt = DEFAULT_VALUE;
831bbe3d1eSWilliam A. Kennington III     }
841bbe3d1eSWilliam A. Kennington III 
851bbe3d1eSWilliam A. Kennington III     if (channelInt < 0)
861bbe3d1eSWilliam A. Kennington III     {
871bbe3d1eSWilliam A. Kennington III         channelInt = DEFAULT_VALUE;
881bbe3d1eSWilliam A. Kennington III     }
891bbe3d1eSWilliam A. Kennington III 
90fa1f5c03SEddie James     auto payloadStr = (options)["oem-payload"];
91fa1f5c03SEddie James     if (!payloadStr.empty())
92fa1f5c03SEddie James     {
93fa1f5c03SEddie James         std::string byte(2, '\0');
94fa1f5c03SEddie James         std::vector<unsigned char> payload;
95fa1f5c03SEddie James 
96fa1f5c03SEddie James         if (payloadStr.size() % 2)
97fa1f5c03SEddie James             exitWithError("Payload invalid: specify two hex digits per byte.",
98fa1f5c03SEddie James                           argv);
99fa1f5c03SEddie James 
100fa1f5c03SEddie James         // Parse the payload string (e.g. "000001572100") to byte data
101fa1f5c03SEddie James         for (unsigned int i = 1; i < payloadStr.size(); i += 2)
102fa1f5c03SEddie James         {
103fa1f5c03SEddie James             byte[0] = payloadStr[i - 1];
104fa1f5c03SEddie James             byte[1] = payloadStr[i];
105fa1f5c03SEddie James 
106fa1f5c03SEddie James             try
107fa1f5c03SEddie James             {
108fa1f5c03SEddie James                 payload.push_back(stoi(byte, nullptr, 16));
109fa1f5c03SEddie James             }
110fa1f5c03SEddie James             catch (const std::exception& e)
111fa1f5c03SEddie James             {
112fa1f5c03SEddie James                 exitWithError("Payload invalid.", argv);
113fa1f5c03SEddie James             }
114fa1f5c03SEddie James         }
115fa1f5c03SEddie James 
116fa1f5c03SEddie James         if (payload.empty())
117fa1f5c03SEddie James         {
118fa1f5c03SEddie James             exitWithError("No payload specified.", argv);
119fa1f5c03SEddie James         }
120fa1f5c03SEddie James 
121fa1f5c03SEddie James         if (packageInt == DEFAULT_VALUE)
122fa1f5c03SEddie James         {
123fa1f5c03SEddie James             exitWithError("Package not specified.", argv);
124fa1f5c03SEddie James         }
125fa1f5c03SEddie James 
126fa1f5c03SEddie James         return ncsi::sendOemCommand(
127fa1f5c03SEddie James             indexInt, packageInt, channelInt,
128fa1f5c03SEddie James             std::span<const unsigned char>(payload.begin(), payload.end()));
129fa1f5c03SEddie James     }
130fa1f5c03SEddie James     else if ((options)["set"] == "true")
1311bbe3d1eSWilliam A. Kennington III     {
1321bbe3d1eSWilliam A. Kennington III         // Can not perform set operation without package.
1331bbe3d1eSWilliam A. Kennington III         if (packageInt == DEFAULT_VALUE)
1341bbe3d1eSWilliam A. Kennington III         {
1351bbe3d1eSWilliam A. Kennington III             exitWithError("Package not specified.", argv);
1361bbe3d1eSWilliam A. Kennington III         }
1371bbe3d1eSWilliam A. Kennington III         return ncsi::setChannel(indexInt, packageInt, channelInt);
1381bbe3d1eSWilliam A. Kennington III     }
1391bbe3d1eSWilliam A. Kennington III     else if ((options)["info"] == "true")
1401bbe3d1eSWilliam A. Kennington III     {
1411bbe3d1eSWilliam A. Kennington III         return ncsi::getInfo(indexInt, packageInt);
1421bbe3d1eSWilliam A. Kennington III     }
1431bbe3d1eSWilliam A. Kennington III     else if ((options)["clear"] == "true")
1441bbe3d1eSWilliam A. Kennington III     {
1451bbe3d1eSWilliam A. Kennington III         return ncsi::clearInterface(indexInt);
1461bbe3d1eSWilliam A. Kennington III     }
1471bbe3d1eSWilliam A. Kennington III     else
1481bbe3d1eSWilliam A. Kennington III     {
1491bbe3d1eSWilliam A. Kennington III         exitWithError("No Command specified", argv);
1501bbe3d1eSWilliam A. Kennington III     }
1511bbe3d1eSWilliam A. Kennington III     return 0;
1521bbe3d1eSWilliam A. Kennington III }
153