1 #include "sol_cmds.hpp"
2 
3 #include "main.hpp"
4 #include "sol/sol_context.hpp"
5 #include "sol/sol_manager.hpp"
6 
7 #include <phosphor-logging/log.hpp>
8 
9 namespace sol
10 {
11 
12 namespace command
13 {
14 
15 using namespace phosphor::logging;
16 
17 std::vector<uint8_t> payloadHandler(const std::vector<uint8_t>& inPayload,
18                                     const message::Handler& handler)
19 {
20     auto request = reinterpret_cast<const Payload*>(inPayload.data());
21     auto solDataSize = inPayload.size() - sizeof(Payload);
22 
23     std::vector<uint8_t> charData(solDataSize);
24     if (solDataSize > 0)
25     {
26         std::copy_n(inPayload.data() + sizeof(Payload), solDataSize,
27                     charData.begin());
28     }
29 
30     try
31     {
32         auto& context = std::get<sol::Manager&>(singletonPool)
33                             .getContext(handler.sessionID);
34 
35         context.processInboundPayload(
36             request->packetSeqNum, request->packetAckSeqNum,
37             request->acceptedCharCount, request->inOperation.ack, charData);
38     }
39     catch (std::exception& e)
40     {
41         log<level::ERR>(e.what());
42         return std::vector<uint8_t>();
43     }
44 
45     return std::vector<uint8_t>();
46 }
47 
48 void activating(uint8_t payloadInstance, uint32_t sessionID)
49 {
50     std::vector<uint8_t> outPayload(sizeof(ActivatingRequest));
51 
52     auto request = reinterpret_cast<ActivatingRequest*>(outPayload.data());
53 
54     request->sessionState = 0;
55     request->payloadInstance = payloadInstance;
56     request->majorVersion = MAJOR_VERSION;
57     request->minorVersion = MINOR_VERSION;
58 
59     auto session =
60         std::get<session::Manager&>(singletonPool).getSession(sessionID);
61 
62     message::Handler msgHandler(session->channelPtr, sessionID);
63 
64     msgHandler.sendUnsolicitedIPMIPayload(netfnTransport, solActivatingCmd,
65                                           outPayload);
66 }
67 
68 std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
69                                    const message::Handler& handler)
70 {
71     std::vector<uint8_t> outPayload(sizeof(SetConfParamsResponse));
72     auto request =
73         reinterpret_cast<const SetConfParamsRequest*>(inPayload.data());
74     auto response = reinterpret_cast<SetConfParamsResponse*>(outPayload.data());
75     response->completionCode = IPMI_CC_OK;
76 
77     switch (static_cast<Parameter>(request->paramSelector))
78     {
79         case Parameter::PROGRESS:
80         {
81             uint8_t progress = request->value & progressMask;
82             std::get<sol::Manager&>(singletonPool).progress = progress;
83             break;
84         }
85         case Parameter::ENABLE:
86         {
87             bool enable = request->value & enableMask;
88             std::get<sol::Manager&>(singletonPool).enable = enable;
89             break;
90         }
91         case Parameter::AUTHENTICATION:
92         {
93             if (!request->auth.auth || !request->auth.encrypt)
94             {
95                 response->completionCode = ipmiCCWriteReadParameter;
96             }
97             else if (request->auth.privilege <
98                          static_cast<uint8_t>(session::Privilege::USER) ||
99                      request->auth.privilege >
100                          static_cast<uint8_t>(session::Privilege::OEM))
101             {
102                 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
103             }
104             else
105             {
106                 std::get<sol::Manager&>(singletonPool).solMinPrivilege =
107                     static_cast<session::Privilege>(request->auth.privilege);
108             }
109             break;
110         }
111         case Parameter::ACCUMULATE:
112         {
113             using namespace std::chrono_literals;
114 
115             if (request->acc.threshold == 0)
116             {
117                 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
118                 break;
119             }
120 
121             std::get<sol::Manager&>(singletonPool).accumulateInterval =
122                 request->acc.interval * sol::accIntervalFactor * 1ms;
123             std::get<sol::Manager&>(singletonPool).sendThreshold =
124                 request->acc.threshold;
125             break;
126         }
127         case Parameter::RETRY:
128         {
129             using namespace std::chrono_literals;
130 
131             std::get<sol::Manager&>(singletonPool).retryCount =
132                 request->retry.count;
133             std::get<sol::Manager&>(singletonPool).retryInterval =
134                 request->retry.interval * sol::retryIntervalFactor * 1ms;
135             break;
136         }
137         case Parameter::PORT:
138         {
139             response->completionCode = ipmiCCWriteReadParameter;
140             break;
141         }
142         case Parameter::NVBITRATE:
143         case Parameter::VBITRATE:
144         case Parameter::CHANNEL:
145         default:
146             response->completionCode = ipmiCCParamNotSupported;
147     }
148 
149     return outPayload;
150 }
151 
152 std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
153                                    const message::Handler& handler)
154 {
155     std::vector<uint8_t> outPayload(sizeof(GetConfParamsResponse));
156     auto request =
157         reinterpret_cast<const GetConfParamsRequest*>(inPayload.data());
158     auto response = reinterpret_cast<GetConfParamsResponse*>(outPayload.data());
159     response->completionCode = IPMI_CC_OK;
160     response->paramRev = parameterRevision;
161 
162     if (request->getParamRev)
163     {
164         return outPayload;
165     }
166 
167     switch (static_cast<Parameter>(request->paramSelector))
168     {
169         case Parameter::PROGRESS:
170         {
171             outPayload.push_back(
172                 std::get<sol::Manager&>(singletonPool).progress);
173             break;
174         }
175         case Parameter::ENABLE:
176         {
177             outPayload.push_back(std::get<sol::Manager&>(singletonPool).enable);
178             break;
179         }
180         case Parameter::AUTHENTICATION:
181         {
182             Auth value{0};
183 
184             value.encrypt = std::get<sol::Manager&>(singletonPool).forceEncrypt;
185             value.auth = std::get<sol::Manager&>(singletonPool).forceAuth;
186             value.privilege = static_cast<uint8_t>(
187                 std::get<sol::Manager&>(singletonPool).solMinPrivilege);
188             auto buffer = reinterpret_cast<const uint8_t*>(&value);
189 
190             std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
191             break;
192         }
193         case Parameter::ACCUMULATE:
194         {
195             Accumulate value{0};
196 
197             value.interval = std::get<sol::Manager&>(singletonPool)
198                                  .accumulateInterval.count() /
199                              sol::accIntervalFactor;
200             value.threshold =
201                 std::get<sol::Manager&>(singletonPool).sendThreshold;
202             auto buffer = reinterpret_cast<const uint8_t*>(&value);
203 
204             std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
205             break;
206         }
207         case Parameter::RETRY:
208         {
209             Retry value{0};
210 
211             value.count = std::get<sol::Manager&>(singletonPool).retryCount;
212             value.interval =
213                 std::get<sol::Manager&>(singletonPool).retryInterval.count() /
214                 sol::retryIntervalFactor;
215             auto buffer = reinterpret_cast<const uint8_t*>(&value);
216 
217             std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
218             break;
219         }
220         case Parameter::PORT:
221         {
222             auto port = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
223             auto buffer = reinterpret_cast<const uint8_t*>(&port);
224 
225             std::copy_n(buffer, sizeof(port), std::back_inserter(outPayload));
226             break;
227         }
228         case Parameter::CHANNEL:
229         {
230             outPayload.push_back(
231                 std::get<sol::Manager&>(singletonPool).channel);
232             break;
233         }
234         case Parameter::NVBITRATE:
235         case Parameter::VBITRATE:
236         default:
237             response->completionCode = ipmiCCParamNotSupported;
238     }
239 
240     return outPayload;
241 }
242 
243 } // namespace command
244 
245 } // namespace sol
246