-
Notifications
You must be signed in to change notification settings - Fork 75
/
systemintfcmds.cpp
189 lines (158 loc) · 6.76 KB
/
systemintfcmds.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "config.h"
#include "systemintfcmds.hpp"
#include "host-cmd-manager.hpp"
#include "host-interface.hpp"
#include <ipmid-host/cmd.hpp>
#include <ipmid/api.hpp>
#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>
#include <cstring>
#include <fstream>
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<phosphor::host::command::Manager>;
extern cmdManagerPtr& ipmid_get_host_cmd_manager();
//-------------------------------------------------------------------
// Called by Host post response from Get_Message_Flags
//-------------------------------------------------------------------
ipmi::RspType<uint16_t, // id
uint8_t, // type
uint24_t, // manuf_id
uint32_t, // timestamp
uint8_t, // netfun
uint8_t, // cmd
std::array<uint8_t, 4> // 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 <command, data> 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<uint8_t>({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<uint8_t> 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<bool, // Receive Message Queue Interrupt Enabled
bool, // Event Message Buffer Full Interrupt Enabled
bool, // Event Message Buffer Enabled
bool, // System Event Logging Enabled
uint1_t, // Reserved
bool, // OEM 0 enabled
bool, // OEM 1 enabled
bool // OEM 2 enabled
>
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<uint8_t>(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<phosphor::host::command::Host> host
__attribute__((init_priority(101)));
std::unique_ptr<sdbusplus::server::manager_t> objManager
__attribute__((init_priority(101)));
} // namespace
void register_netfn_app_functions()
{
// <Read Event Message Buffer>
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
ipmi::app::cmdReadEventMessageBuffer,
ipmi::Privilege::Admin, ipmiAppReadEventBuffer);
// <Set BMC Global Enables>
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
ipmi::app::cmdSetBmcGlobalEnables,
ipmi::Privilege::Admin, ipmiAppSetBMCGlobalEnable);
// <Get BMC Global Enables>
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
ipmi::app::cmdGetBmcGlobalEnables,
ipmi::Privilege::User, ipmiAppGetBMCGlobalEnable);
// <Get Message Flags>
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<sdbusplus::asio::connection>& sdbusp =
ipmid_get_sdbus_plus_handler();
// Add sdbusplus ObjectManager.
objManager = std::make_unique<sdbusplus::server::manager_t>(
*sdbusp, CONTROL_HOST_OBJ_MGR);
host = std::make_unique<phosphor::host::command::Host>(
*sdbusp, objPath.c_str());
sdbusp->request_name(CONTROL_HOST_BUSNAME);
return;
}