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