#include "config.h" #include "systemintfcmds.hpp" #include "host-cmd-manager.hpp" #include "host-interface.hpp" #include #include #include #include #include #include void register_netfn_app_functions() __attribute__((constructor)); using namespace sdbusplus::server::xyz::openbmc_project::control; // For accessing Host command manager using cmdManagerPtr = std::unique_ptr; extern cmdManagerPtr& ipmid_get_host_cmd_manager(); //------------------------------------------------------------------- // Called by Host post response from Get_Message_Flags //------------------------------------------------------------------- ipmi::RspType // data > ipmiAppReadEventBuffer(ipmi::Context::ptr& ctx) { // require this to be limited to system interface if (ctx->channel != ipmi::channelSystemIface) { return ipmi::responseInvalidCommand(); } constexpr uint16_t selOemId = 0x5555; constexpr uint8_t selRecordTypeOem = 0xc0; // read manufacturer ID from dev_id file static uint24_t manufId{}; if (!manufId) { const char* filename = "/usr/share/ipmi-providers/dev_id.json"; std::ifstream devIdFile(filename); if (devIdFile.is_open()) { auto data = nlohmann::json::parse(devIdFile, nullptr, false); if (!data.is_discarded()) { manufId = data.value("manuf_id", 0); } } } constexpr uint32_t timestamp{0}; // per IPMI spec NetFuntion for OEM constexpr uint8_t netfun = 0x3a; // Read from the Command Manager queue. What gets returned is a // pair of that can be directly used here const auto& [cmd, data0] = ipmid_get_host_cmd_manager()->getNextCommand(); constexpr uint8_t dataUnused = 0xff; return ipmi::responseSuccess( selOemId, selRecordTypeOem, manufId, timestamp, netfun, cmd, std::to_array({data0, dataUnused, dataUnused, dataUnused})); } //--------------------------------------------------------------------- // Called by Host on seeing a SMS_ATN bit set. Return a hardcoded // value of 0x0 to indicate Event Message Buffer is not supported //------------------------------------------------------------------- ipmi::RspType ipmiAppGetMessageFlags() { // From IPMI spec V2.0 for Get Message Flags Command : // bit:[1] from LSB : 1b = Event Message Buffer Full. // Return as 0 if Event Message Buffer is not supported, // or when the Event Message buffer is disabled. // This path is used to communicate messages to the host // from within the phosphor::host::command::Manager constexpr uint8_t setEventMsgBufferNotSupported = 0x0; return ipmi::responseSuccess(setEventMsgBufferNotSupported); } ipmi::RspType ipmiAppGetBMCGlobalEnable() { return ipmi::responseSuccess(true, false, false, true, 0, false, false, false); } ipmi::RspType<> ipmiAppSetBMCGlobalEnable( ipmi::Context::ptr ctx, bool receiveMessageQueueInterruptEnabled, bool eventMessageBufferFullInterruptEnabled, bool eventMessageBufferEnabled, bool systemEventLogEnable, uint1_t reserved, bool OEM0Enabled, bool OEM1Enabled, bool OEM2Enabled) { ipmi::ChannelInfo chInfo; if (ipmi::getChannelInfo(ctx->channel, chInfo) != ipmi::ccSuccess) { lg2::error("Failed to get Channel Info, channel={CHANNEL}", "CHANNEL", ctx->channel); return ipmi::responseUnspecifiedError(); } if (chInfo.mediumType != static_cast(ipmi::EChannelMediumType::systemInterface)) { lg2::error("Error - supported only in system interface"); return ipmi::responseCommandNotAvailable(); } // Recv Message Queue and SEL are enabled by default. // Event Message buffer are disabled by default (not supported). // Any request that try to change the mask will be rejected if (!receiveMessageQueueInterruptEnabled || !systemEventLogEnable || eventMessageBufferFullInterruptEnabled || eventMessageBufferEnabled || OEM0Enabled || OEM1Enabled || OEM2Enabled || reserved) { return ipmi::responseInvalidFieldRequest(); } return ipmi::responseSuccess(); } namespace { // Static storage to keep the object alive during process life std::unique_ptr host __attribute__((init_priority(101))); std::unique_ptr objManager __attribute__((init_priority(101))); } // namespace void register_netfn_app_functions() { // ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, ipmi::app::cmdReadEventMessageBuffer, ipmi::Privilege::Admin, ipmiAppReadEventBuffer); // ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, ipmi::app::cmdSetBmcGlobalEnables, ipmi::Privilege::Admin, ipmiAppSetBMCGlobalEnable); // ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, ipmi::app::cmdGetBmcGlobalEnables, ipmi::Privilege::User, ipmiAppGetBMCGlobalEnable); // ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, ipmi::app::cmdGetMessageFlags, ipmi::Privilege::Admin, ipmiAppGetMessageFlags); // Create new xyz.openbmc_project.host object on the bus auto objPath = std::string{CONTROL_HOST_OBJ_MGR} + '/' + HOST_NAME + '0'; std::unique_ptr& sdbusp = ipmid_get_sdbus_plus_handler(); // Add sdbusplus ObjectManager. objManager = std::make_unique( *sdbusp, CONTROL_HOST_OBJ_MGR); host = std::make_unique( *sdbusp, objPath.c_str()); sdbusp->request_name(CONTROL_HOST_BUSNAME); return; }