xref: /openbmc/fb-ipmi-oem/src/biccommands.cpp (revision 25b79bf4)
1 /*
2  * Copyright (c)  2018 Intel Corporation.
3  * Copyright (c)  2018-present Facebook.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <ipmid/api.hpp>
19 #include <ipmid/api-types.hpp>
20 
21 #include <commandutils.hpp>
22 #include <biccommands.hpp>
23 #include <phosphor-logging/log.hpp>
24 
25 #include <vector>
26 #include <variant>
27 #include <iostream>
28 
29 namespace ipmi
30 {
31 
32 using namespace phosphor::logging;
33 
34 #ifdef BIC_ENABLED
35 static void registerBICFunctions() __attribute__((constructor));
36 #endif
37 
38 extern message::Response::ptr executeIpmiCommand(message::Request::ptr);
39 
40 int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
41                std::vector<uint8_t>&);
42 
43 //----------------------------------------------------------------------
44 // ipmiOemBicHandler (IPMI/Section - ) (CMD_OEM_BIC_INFO)
45 // This Function will handle BIC request for netfn=0x38 and cmd=1
46 // send the response back to the sender.
47 //----------------------------------------------------------------------
48 
49 ipmi::RspType<IanaType, uint8_t, uint2_t, uint6_t, uint8_t, uint8_t,
50               ipmi::message::Payload>
51     ipmiOemBicHandler(ipmi::Context::ptr ctx, IanaType reqIana,
52                       uint8_t interface, uint2_t lun, uint6_t netFnReq,
53                       uint8_t cmdReq, SecureBuffer data)
54 {
55 
56     ipmi::message::Response::ptr res;
57 
58     // Updating the correct netfn and cmd in the ipmi Context
59     ctx->netFn = ((uint8_t)netFnReq);
60     ctx->cmd = cmdReq;
61 
62     // creating ipmi message request for calling executeIpmiCommand function
63     auto req = std::make_shared<ipmi::message::Request>(ctx, std::move(data));
64 
65     // Calling executeIpmiCommand request function
66     res = ipmi::executeIpmiCommand(req);
67 
68     // sending the response with headers and payload
69     return ipmi::responseSuccess(reqIana, interface, lun, ++netFnReq, cmdReq,
70                                  res->cc, res->payload);
71 }
72 
73 //----------------------------------------------------------------------
74 // ipmiOemPostCodeHandler (CMD_OEM_BIC_POST_BUFFER_INFO)
75 // This Function will handle BIC incomming postcode from multi-host for
76 // netfn=0x38 and cmd=0x08 send the response back to the sender.
77 //----------------------------------------------------------------------
78 
79 ipmi::RspType<IanaType> ipmiOemPostCodeHandler(ipmi::Context::ptr ctx,
80                                                IanaType reqIana,
81                                                uint8_t dataLen,
82                                                std::vector<uint8_t> data)
83 {
84     // creating bus connection
85     auto conn = getSdBus();
86 
87     using postcode_t = std::tuple<uint64_t, std::vector<uint8_t>>;
88 
89     std::string dbusObjStr = dbusObj + std::to_string((ctx->hostIdx + 1));
90 
91     for (unsigned int index = 0; index < dataLen; index++)
92     {
93         uint64_t primaryPostCode = static_cast<uint64_t>(data[index]);
94         auto postCode = postcode_t(primaryPostCode, {});
95 
96         try
97         {
98             auto method = conn->new_method_call(
99                 "xyz.openbmc_project.State.Boot.Raw", dbusObjStr.c_str(),
100                 "org.freedesktop.DBus.Properties", "Set");
101 
102             // Adding paramters to method call
103             method.append(dbusService, "Value",
104                           std::variant<postcode_t>(postCode));
105 
106             // Invoke method call function
107             auto reply = conn->call(method);
108         }
109 
110         catch (std::exception& e)
111         {
112             phosphor::logging::log<phosphor::logging::level::ERR>(
113                 "post code handler error\n");
114 
115             // sending the Error response
116             return ipmi::responseResponseError();
117         }
118     }
119 
120     return ipmi::responseSuccess(reqIana);
121 }
122 
123 //----------------------------------------------------------------------
124 // ipmiOemGetBicGpioState (CMD_OEM_GET_BIC_GPIO_STATE)
125 // This Function will handle BIC GPIO stats for
126 // netfn=0x38 and cmd=0x03 send the response back to the sender.
127 //----------------------------------------------------------------------
128 
129 ipmi::RspType<IanaType, std::vector<uint8_t>>
130     ipmiOemGetBicGpioState(ipmi::Context::ptr ctx, std::vector<uint8_t> reqIana)
131 {
132     std::vector<uint8_t> respData;
133 
134     if (std::equal(reqIana.begin(), reqIana.end(), iana.begin()) == false)
135     {
136         phosphor::logging::log<phosphor::logging::level::ERR>(
137             "Invalid IANA number");
138         return ipmi::responseInvalidFieldRequest();
139     }
140 
141     uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
142 
143     if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqIana, respData))
144     {
145         return ipmi::responseUnspecifiedError();
146     }
147 
148     std::vector<uint8_t> gpioState;
149     IanaType respIana;
150 
151     auto r =
152         std::ranges::copy_n(respData.begin(), iana.size(), respIana.begin()).in;
153     std::copy(r, respData.end(), std::back_inserter(gpioState));
154 
155     return ipmi::responseSuccess(respIana, gpioState);
156 }
157 
158 [[maybe_unused]] static void registerBICFunctions(void)
159 {
160 
161     phosphor::logging::log<phosphor::logging::level::INFO>(
162         "Registering BIC commands");
163 
164     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
165                           static_cast<Cmd>(fb_bic_cmds::CMD_OEM_BIC_INFO),
166                           ipmi::Privilege::User, ipmiOemBicHandler);
167     ipmi::registerHandler(
168         ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
169         static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SEND_POST_BUFFER_TO_BMC),
170         ipmi::Privilege::User, ipmiOemPostCodeHandler);
171     ipmi::registerHandler(
172         ipmi::prioOemBase, ipmi::netFnOemFive,
173         static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_BIC_GPIO_STATE),
174         ipmi::Privilege::User, ipmiOemGetBicGpioState);
175     return;
176 }
177 
178 } // namespace ipmi
179