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             .lock();
62 
63     message::Handler msgHandler(session->channelPtr, sessionID);
64 
65     msgHandler.sendUnsolicitedIPMIPayload(netfnTransport, solActivatingCmd,
66                                           outPayload);
67 }
68 
69 std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
70                                    const message::Handler& handler)
71 {
72     std::vector<uint8_t> outPayload(sizeof(SetConfParamsResponse));
73     auto request =
74         reinterpret_cast<const SetConfParamsRequest*>(inPayload.data());
75     auto response = reinterpret_cast<SetConfParamsResponse*>(outPayload.data());
76     response->completionCode = IPMI_CC_OK;
77 
78     switch (static_cast<Parameter>(request->paramSelector))
79     {
80         case Parameter::PROGRESS:
81         {
82             uint8_t progress = request->value & progressMask;
83             std::get<sol::Manager&>(singletonPool).progress = progress;
84             break;
85         }
86         case Parameter::ENABLE:
87         {
88             bool enable = request->value & enableMask;
89             std::get<sol::Manager&>(singletonPool).enable = enable;
90             break;
91         }
92         case Parameter::AUTHENTICATION:
93         {
94             if (!request->auth.auth || !request->auth.encrypt)
95             {
96                 response->completionCode = ipmiCCWriteReadParameter;
97             }
98             else if (request->auth.privilege <
99                          static_cast<uint8_t>(session::Privilege::USER) ||
100                      request->auth.privilege >
101                          static_cast<uint8_t>(session::Privilege::OEM))
102             {
103                 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
104             }
105             else
106             {
107                 std::get<sol::Manager&>(singletonPool).solMinPrivilege =
108                     static_cast<session::Privilege>(request->auth.privilege);
109             }
110             break;
111         }
112         case Parameter::ACCUMULATE:
113         {
114             using namespace std::chrono_literals;
115 
116             if (request->acc.threshold == 0)
117             {
118                 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
119                 break;
120             }
121 
122             std::get<sol::Manager&>(singletonPool).accumulateInterval =
123                 request->acc.interval * sol::accIntervalFactor * 1ms;
124             std::get<sol::Manager&>(singletonPool).sendThreshold =
125                 request->acc.threshold;
126             break;
127         }
128         case Parameter::RETRY:
129         {
130             using namespace std::chrono_literals;
131 
132             std::get<sol::Manager&>(singletonPool).retryCount =
133                 request->retry.count;
134             std::get<sol::Manager&>(singletonPool).retryInterval =
135                 request->retry.interval * sol::retryIntervalFactor * 1ms;
136             break;
137         }
138         case Parameter::PORT:
139         {
140             response->completionCode = ipmiCCWriteReadParameter;
141             break;
142         }
143         case Parameter::NVBITRATE:
144         case Parameter::VBITRATE:
145         case Parameter::CHANNEL:
146         default:
147             response->completionCode = ipmiCCParamNotSupported;
148     }
149 
150     return outPayload;
151 }
152 
153 std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
154                                    const message::Handler& handler)
155 {
156     std::vector<uint8_t> outPayload(sizeof(GetConfParamsResponse));
157     auto request =
158         reinterpret_cast<const GetConfParamsRequest*>(inPayload.data());
159     auto response = reinterpret_cast<GetConfParamsResponse*>(outPayload.data());
160     response->completionCode = IPMI_CC_OK;
161     response->paramRev = parameterRevision;
162 
163     if (request->getParamRev)
164     {
165         return outPayload;
166     }
167 
168     switch (static_cast<Parameter>(request->paramSelector))
169     {
170         case Parameter::PROGRESS:
171         {
172             outPayload.push_back(
173                 std::get<sol::Manager&>(singletonPool).progress);
174             break;
175         }
176         case Parameter::ENABLE:
177         {
178             outPayload.push_back(std::get<sol::Manager&>(singletonPool).enable);
179             break;
180         }
181         case Parameter::AUTHENTICATION:
182         {
183             Auth value{0};
184 
185             value.encrypt = std::get<sol::Manager&>(singletonPool).forceEncrypt;
186             value.auth = std::get<sol::Manager&>(singletonPool).forceAuth;
187             value.privilege = static_cast<uint8_t>(
188                 std::get<sol::Manager&>(singletonPool).solMinPrivilege);
189             auto buffer = reinterpret_cast<const uint8_t*>(&value);
190 
191             std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
192             break;
193         }
194         case Parameter::ACCUMULATE:
195         {
196             Accumulate value{0};
197 
198             value.interval = std::get<sol::Manager&>(singletonPool)
199                                  .accumulateInterval.count() /
200                              sol::accIntervalFactor;
201             value.threshold =
202                 std::get<sol::Manager&>(singletonPool).sendThreshold;
203             auto buffer = reinterpret_cast<const uint8_t*>(&value);
204 
205             std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
206             break;
207         }
208         case Parameter::RETRY:
209         {
210             Retry value{0};
211 
212             value.count = std::get<sol::Manager&>(singletonPool).retryCount;
213             value.interval =
214                 std::get<sol::Manager&>(singletonPool).retryInterval.count() /
215                 sol::retryIntervalFactor;
216             auto buffer = reinterpret_cast<const uint8_t*>(&value);
217 
218             std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
219             break;
220         }
221         case Parameter::PORT:
222         {
223             auto port = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
224             auto buffer = reinterpret_cast<const uint8_t*>(&port);
225 
226             std::copy_n(buffer, sizeof(port), std::back_inserter(outPayload));
227             break;
228         }
229         case Parameter::CHANNEL:
230         {
231             outPayload.push_back(
232                 std::get<sol::Manager&>(singletonPool).channel);
233             break;
234         }
235         case Parameter::NVBITRATE:
236         case Parameter::VBITRATE:
237         default:
238             response->completionCode = ipmiCCParamNotSupported;
239     }
240 
241     return outPayload;
242 }
243 
244 } // namespace command
245 
246 } // namespace sol
247