xref: /openbmc/phosphor-host-ipmid/systemintfcmds.cpp (revision 5087b0753b5ce2ce8f2de5d287ea4d9946fb8420)
1b891a576SVishwanatha Subbanna #include "config.h"
20b02be92SPatrick Venture 
346470a38SPatrick Venture #include "systemintfcmds.hpp"
40b02be92SPatrick Venture 
53eb117a3SVishwanatha Subbanna #include "host-cmd-manager.hpp"
612866370SAndrew Geissler #include "host-interface.hpp"
79e5232e5STom 
8194375f2SWilliam A. Kennington III #include <ipmid-host/cmd.hpp>
9240b186cSVernon Mauery #include <ipmid/api.hpp>
10e4aa6545SVernon Mauery #include <nlohmann/json.hpp>
119cd6d9a0SGeorge Liu #include <phosphor-logging/lg2.hpp>
129e5232e5STom 
13fbc6c9d7SPatrick Williams #include <cstring>
14e4aa6545SVernon Mauery #include <fstream>
15fbc6c9d7SPatrick Williams 
16*5087b075SGeorge Liu void registerNetFnAppFunctions() __attribute__((constructor));
179e5232e5STom 
18523e2d1bSWilly Tu using namespace sdbusplus::server::xyz::openbmc_project::control;
1912866370SAndrew Geissler 
203eb117a3SVishwanatha Subbanna // For accessing Host command manager
213eb117a3SVishwanatha Subbanna using cmdManagerPtr = std::unique_ptr<phosphor::host::command::Manager>;
223eb117a3SVishwanatha Subbanna extern cmdManagerPtr& ipmid_get_host_cmd_manager();
2312866370SAndrew Geissler 
2412866370SAndrew Geissler //-------------------------------------------------------------------
2512866370SAndrew Geissler // Called by Host post response from Get_Message_Flags
2612866370SAndrew Geissler //-------------------------------------------------------------------
27e4aa6545SVernon Mauery ipmi::RspType<uint16_t,              // id
28e4aa6545SVernon Mauery               uint8_t,               // type
29e4aa6545SVernon Mauery               uint24_t,              //  manuf_id
30e4aa6545SVernon Mauery               uint32_t,              // timestamp
31e4aa6545SVernon Mauery               uint8_t,               // netfun
32e4aa6545SVernon Mauery               uint8_t,               // cmd
33e4aa6545SVernon Mauery               std::array<uint8_t, 4> // data
34e4aa6545SVernon Mauery               >
ipmiAppReadEventBuffer(ipmi::Context::ptr & ctx)35e4aa6545SVernon Mauery     ipmiAppReadEventBuffer(ipmi::Context::ptr& ctx)
3612866370SAndrew Geissler {
37e4aa6545SVernon Mauery     // require this to be limited to system interface
38e4aa6545SVernon Mauery     if (ctx->channel != ipmi::channelSystemIface)
39e4aa6545SVernon Mauery     {
40e4aa6545SVernon Mauery         return ipmi::responseInvalidCommand();
41e4aa6545SVernon Mauery     }
4212866370SAndrew Geissler 
43e4aa6545SVernon Mauery     constexpr uint16_t selOemId = 0x5555;
44e4aa6545SVernon Mauery     constexpr uint8_t selRecordTypeOem = 0xc0;
4512866370SAndrew Geissler 
46e4aa6545SVernon Mauery     // read manufacturer ID from dev_id file
47e4aa6545SVernon Mauery     static uint24_t manufId{};
48e4aa6545SVernon Mauery     if (!manufId)
49e4aa6545SVernon Mauery     {
50e4aa6545SVernon Mauery         const char* filename = "/usr/share/ipmi-providers/dev_id.json";
51e4aa6545SVernon Mauery         std::ifstream devIdFile(filename);
52e4aa6545SVernon Mauery         if (devIdFile.is_open())
53e4aa6545SVernon Mauery         {
54e4aa6545SVernon Mauery             auto data = nlohmann::json::parse(devIdFile, nullptr, false);
55e4aa6545SVernon Mauery             if (!data.is_discarded())
56e4aa6545SVernon Mauery             {
57e4aa6545SVernon Mauery                 manufId = data.value("manuf_id", 0);
58e4aa6545SVernon Mauery             }
59e4aa6545SVernon Mauery         }
60e4aa6545SVernon Mauery     }
619e5232e5STom 
62e4aa6545SVernon Mauery     constexpr uint32_t timestamp{0};
639e5232e5STom 
649e5232e5STom     // per IPMI spec NetFuntion for OEM
65e4aa6545SVernon Mauery     constexpr uint8_t netfun = 0x3a;
669e5232e5STom 
673eb117a3SVishwanatha Subbanna     // Read from the Command Manager queue. What gets returned is a
683eb117a3SVishwanatha Subbanna     // pair of <command, data> that can be directly used here
69e4aa6545SVernon Mauery     const auto& [cmd, data0] = ipmid_get_host_cmd_manager()->getNextCommand();
70e4aa6545SVernon Mauery     constexpr uint8_t dataUnused = 0xff;
719e5232e5STom 
72e4aa6545SVernon Mauery     return ipmi::responseSuccess(
73e4aa6545SVernon Mauery         selOemId, selRecordTypeOem, manufId, timestamp, netfun, cmd,
74e4aa6545SVernon Mauery         std::to_array<uint8_t>({data0, dataUnused, dataUnused, dataUnused}));
759e5232e5STom }
769e5232e5STom 
779e5232e5STom //---------------------------------------------------------------------
789e5232e5STom // Called by Host on seeing a SMS_ATN bit set. Return a hardcoded
79414d2f7bSXP Chen // value of 0x0 to indicate Event Message Buffer is not supported
809e5232e5STom //-------------------------------------------------------------------
ipmiAppGetMessageFlags()81461f4645SAndrew Geissler ipmi::RspType<uint8_t> ipmiAppGetMessageFlags()
829e5232e5STom {
839e5232e5STom     // From IPMI spec V2.0 for Get Message Flags Command :
849e5232e5STom     // bit:[1] from LSB : 1b = Event Message Buffer Full.
859e5232e5STom     // Return as 0 if Event Message Buffer is not supported,
869e5232e5STom     // or when the Event Message buffer is disabled.
87461f4645SAndrew Geissler     // This path is used to communicate messages to the host
88461f4645SAndrew Geissler     // from within the phosphor::host::command::Manager
89414d2f7bSXP Chen     constexpr uint8_t setEventMsgBufferNotSupported = 0x0;
90414d2f7bSXP Chen     return ipmi::responseSuccess(setEventMsgBufferNotSupported);
919e5232e5STom }
929e5232e5STom 
935aa26937SYong Li ipmi::RspType<bool,    // Receive Message Queue Interrupt Enabled
945aa26937SYong Li               bool,    // Event Message Buffer Full Interrupt Enabled
955aa26937SYong Li               bool,    // Event Message Buffer Enabled
965aa26937SYong Li               bool,    // System Event Logging Enabled
975aa26937SYong Li               uint1_t, // Reserved
985aa26937SYong Li               bool,    // OEM 0 enabled
995aa26937SYong Li               bool,    // OEM 1 enabled
1005aa26937SYong Li               bool     // OEM 2 enabled
1015aa26937SYong Li               >
ipmiAppGetBMCGlobalEnable()1025aa26937SYong Li     ipmiAppGetBMCGlobalEnable()
10330206dbaSJia, Chunhui {
1045aa26937SYong Li     return ipmi::responseSuccess(true, false, false, true, 0, false, false,
1055aa26937SYong Li                                  false);
10630206dbaSJia, Chunhui }
10730206dbaSJia, Chunhui 
ipmiAppSetBMCGlobalEnable(ipmi::Context::ptr ctx,bool receiveMessageQueueInterruptEnabled,bool eventMessageBufferFullInterruptEnabled,bool eventMessageBufferEnabled,bool systemEventLogEnable,uint1_t reserved,bool OEM0Enabled,bool OEM1Enabled,bool OEM2Enabled)108ecd7bb98SYong Li ipmi::RspType<> ipmiAppSetBMCGlobalEnable(
109ecd7bb98SYong Li     ipmi::Context::ptr ctx, bool receiveMessageQueueInterruptEnabled,
110ecd7bb98SYong Li     bool eventMessageBufferFullInterruptEnabled, bool eventMessageBufferEnabled,
111ecd7bb98SYong Li     bool systemEventLogEnable, uint1_t reserved, bool OEM0Enabled,
112ecd7bb98SYong Li     bool OEM1Enabled, bool OEM2Enabled)
1139e5232e5STom {
114a249a082SYong Li     ipmi::ChannelInfo chInfo;
115a249a082SYong Li 
116a249a082SYong Li     if (ipmi::getChannelInfo(ctx->channel, chInfo) != ipmi::ccSuccess)
117a249a082SYong Li     {
1189cd6d9a0SGeorge Liu         lg2::error("Failed to get Channel Info, channel={CHANNEL}", "CHANNEL",
1199cd6d9a0SGeorge Liu                    ctx->channel);
120a249a082SYong Li         return ipmi::responseUnspecifiedError();
121a249a082SYong Li     }
122a249a082SYong Li 
123a249a082SYong Li     if (chInfo.mediumType !=
124a249a082SYong Li         static_cast<uint8_t>(ipmi::EChannelMediumType::systemInterface))
125a249a082SYong Li     {
1269cd6d9a0SGeorge Liu         lg2::error("Error - supported only in system interface");
127a249a082SYong Li         return ipmi::responseCommandNotAvailable();
128a249a082SYong Li     }
129a249a082SYong Li 
13030206dbaSJia, Chunhui     // Recv Message Queue and SEL are enabled by default.
13130206dbaSJia, Chunhui     // Event Message buffer are disabled by default (not supported).
13230206dbaSJia, Chunhui     // Any request that try to change the mask will be rejected
133ecd7bb98SYong Li     if (!receiveMessageQueueInterruptEnabled || !systemEventLogEnable ||
134ecd7bb98SYong Li         eventMessageBufferFullInterruptEnabled || eventMessageBufferEnabled ||
135ecd7bb98SYong Li         OEM0Enabled || OEM1Enabled || OEM2Enabled || reserved)
13630206dbaSJia, Chunhui     {
137ecd7bb98SYong Li         return ipmi::responseInvalidFieldRequest();
13830206dbaSJia, Chunhui     }
139ecd7bb98SYong Li 
140ecd7bb98SYong Li     return ipmi::responseSuccess();
1419e5232e5STom }
1429e5232e5STom 
1430b02be92SPatrick Venture namespace
1440b02be92SPatrick Venture {
14512c2db79SLei YU // Static storage to keep the object alive during process life
1463eb117a3SVishwanatha Subbanna std::unique_ptr<phosphor::host::command::Host> host
1473eb117a3SVishwanatha Subbanna     __attribute__((init_priority(101)));
1485d82f474SPatrick Williams std::unique_ptr<sdbusplus::server::manager_t> objManager
1493eb117a3SVishwanatha Subbanna     __attribute__((init_priority(101)));
1500b02be92SPatrick Venture } // namespace
15112866370SAndrew Geissler 
registerNetFnAppFunctions()152*5087b075SGeorge Liu void registerNetFnAppFunctions()
1539e5232e5STom {
1549e5232e5STom     // <Read Event Message Buffer>
155e4aa6545SVernon Mauery     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
156e4aa6545SVernon Mauery                           ipmi::app::cmdReadEventMessageBuffer,
157e4aa6545SVernon Mauery                           ipmi::Privilege::Admin, ipmiAppReadEventBuffer);
1589e5232e5STom 
1599e5232e5STom     // <Set BMC Global Enables>
160ecd7bb98SYong Li     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
161ecd7bb98SYong Li                           ipmi::app::cmdSetBmcGlobalEnables,
162ecd7bb98SYong Li                           ipmi::Privilege::Admin, ipmiAppSetBMCGlobalEnable);
1639e5232e5STom 
16430206dbaSJia, Chunhui     // <Get BMC Global Enables>
1655aa26937SYong Li     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1665aa26937SYong Li                           ipmi::app::cmdGetBmcGlobalEnables,
1675aa26937SYong Li                           ipmi::Privilege::User, ipmiAppGetBMCGlobalEnable);
16830206dbaSJia, Chunhui 
1699e5232e5STom     // <Get Message Flags>
170461f4645SAndrew Geissler     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
171461f4645SAndrew Geissler                           ipmi::app::cmdGetMessageFlags, ipmi::Privilege::Admin,
172461f4645SAndrew Geissler                           ipmiAppGetMessageFlags);
1739e5232e5STom 
17412866370SAndrew Geissler     // Create new xyz.openbmc_project.host object on the bus
1753eb117a3SVishwanatha Subbanna     auto objPath = std::string{CONTROL_HOST_OBJ_MGR} + '/' + HOST_NAME + '0';
17612866370SAndrew Geissler 
17720ff333dSVernon Mauery     std::unique_ptr<sdbusplus::asio::connection>& sdbusp =
17820ff333dSVernon Mauery         ipmid_get_sdbus_plus_handler();
17912866370SAndrew Geissler 
180240b186cSVernon Mauery     // Add sdbusplus ObjectManager.
1815d82f474SPatrick Williams     objManager = std::make_unique<sdbusplus::server::manager_t>(
182240b186cSVernon Mauery         *sdbusp, CONTROL_HOST_OBJ_MGR);
183240b186cSVernon Mauery 
1841318a5edSPatrick Williams     host = std::make_unique<phosphor::host::command::Host>(
1851318a5edSPatrick Williams         *sdbusp, objPath.c_str());
186240b186cSVernon Mauery     sdbusp->request_name(CONTROL_HOST_BUSNAME);
18712866370SAndrew Geissler 
1889e5232e5STom     return;
1899e5232e5STom }
190