blob: 1d9e063a5e6cc6f7dfcc2166e435c4f312be187f [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#include "command_table.hpp"
2
Richard Marian Thomaiyar472a37b2018-09-06 07:11:07 +05303#include "main.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05004#include "message_handler.hpp"
Tom Joseph1efcb492017-01-31 16:56:47 +05305#include "message_parsers.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05006#include "sessions_manager.hpp"
Nagaraju Goruganti1d9d4162018-03-22 01:27:37 -05007
Vernon Mauery9e801a22018-10-12 13:20:49 -07008#include <iomanip>
Vernon Mauery66501642018-07-30 09:07:10 -07009#include <main.hpp>
Vernon Mauery9e801a22018-10-12 13:20:49 -070010#include <phosphor-logging/elog-errors.hpp>
11#include <phosphor-logging/log.hpp>
Vernon Mauery66501642018-07-30 09:07:10 -070012#include <user_channel/user_layer.hpp>
Vernon Maueryf41a5542018-10-15 16:04:17 -070013#include <xyz/openbmc_project/Common/error.hpp>
Vernon Mauery9e801a22018-10-12 13:20:49 -070014
Vernon Mauery66501642018-07-30 09:07:10 -070015using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Nagaraju Goruganti1d9d4162018-03-22 01:27:37 -050016using namespace phosphor::logging;
Tom Joseph07181f52016-08-08 08:17:08 -050017
Vernon Mauery66501642018-07-30 09:07:10 -070018namespace ipmi
19{
Patrick Williams9edc2312020-05-13 17:58:04 -050020using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
21 int64_t, uint64_t, double, std::string>;
Vernon Mauery66501642018-07-30 09:07:10 -070022
23} // namespace ipmi
24
Tom Joseph07181f52016-08-08 08:17:08 -050025namespace command
26{
27
28void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
29{
Feist, Jamesbd45aae2017-10-26 15:06:13 -070030 auto& command = commandTable[inCommand.command];
31
32 if (command)
33 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070034 log<level::DEBUG>(
35 "Already Registered",
Vernon Mauery66501642018-07-30 09:07:10 -070036 phosphor::logging::entry("SKIPPED_ENTRY=0x%x", inCommand.command));
Feist, Jamesbd45aae2017-10-26 15:06:13 -070037 return;
38 }
39
Feist, Jamesbd45aae2017-10-26 15:06:13 -070040 command = std::move(entry);
Tom Joseph07181f52016-08-08 08:17:08 -050041}
42
Vernon Mauery8d6f2002018-11-07 09:55:53 -080043void Table::executeCommand(uint32_t inCommand,
44 std::vector<uint8_t>& commandData,
45 std::shared_ptr<message::Handler> handler)
Tom Joseph07181f52016-08-08 08:17:08 -050046{
47 using namespace std::chrono_literals;
48
Tom Joseph07181f52016-08-08 08:17:08 -050049 auto iterator = commandTable.find(inCommand);
50
51 if (iterator == commandTable.end())
52 {
Vernon Mauery66501642018-07-30 09:07:10 -070053 CommandID command(inCommand);
54
Vernon Mauery779e7e12021-06-08 16:24:45 -070055 // Do not forward any session zero commands to ipmid
56 if (handler->sessionID == session::sessionZero)
57 {
58 log<level::INFO>("Table: refuse to forward session-zero command",
59 entry("LUN=%x", command.lun()),
60 entry("NETFN=%x", command.netFn()),
61 entry("CMD=%x", command.cmd()));
62 return;
63 }
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070064 std::shared_ptr<session::Session> session =
65 std::get<session::Manager&>(singletonPool)
66 .getSession(handler->sessionID);
67
68 // Ignore messages that are not part of an active session
69 auto state = static_cast<session::State>(session->state());
70 if (state != session::State::active)
71 {
72 return;
73 }
Vernon Mauery779e7e12021-06-08 16:24:45 -070074
Vernon Mauery66501642018-07-30 09:07:10 -070075 auto bus = getSdBus();
76 // forward the request onto the main ipmi queue
Vernon Mauery8d6f2002018-11-07 09:55:53 -080077 using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
78 std::vector<uint8_t>>;
Vernon Mauery66501642018-07-30 09:07:10 -070079 uint8_t lun = command.lun();
80 uint8_t netFn = command.netFn();
81 uint8_t cmd = command.cmd();
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070082
Vernon Mauery66501642018-07-30 09:07:10 -070083 std::map<std::string, ipmi::Value> options = {
Vernon Maueryd92bc322019-03-15 15:24:30 -070084 {"userId", ipmi::Value(static_cast<int>(
85 ipmi::ipmiUserGetUserId(session->userName)))},
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053086 {"privilege",
87 ipmi::Value(static_cast<int>(session->currentPrivilege()))},
Rajashekar Gade Reddy49a94b22019-11-13 16:46:32 +053088 {"currentSessionId",
89 ipmi::Value(static_cast<uint32_t>(session->getBMCSessionID()))},
Vernon Mauery66501642018-07-30 09:07:10 -070090 };
Vernon Mauery8d6f2002018-11-07 09:55:53 -080091 bus->async_method_call(
92 [handler, this](const boost::system::error_code& ec,
93 const IpmiDbusRspType& response) {
94 if (!ec)
95 {
96 const uint8_t& cc = std::get<3>(response);
97 const std::vector<uint8_t>& responseData =
98 std::get<4>(response);
99 std::vector<uint8_t> payload;
100 payload.reserve(1 + responseData.size());
101 payload.push_back(cc);
102 payload.insert(payload.end(), responseData.begin(),
103 responseData.end());
104 handler->outPayload = std::move(payload);
105 }
106 else
107 {
108 std::vector<uint8_t> payload;
109 payload.push_back(IPMI_CC_UNSPECIFIED_ERROR);
110 handler->outPayload = std::move(payload);
111 }
112 },
113 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
114 "xyz.openbmc_project.Ipmi.Server", "execute", netFn, lun, cmd,
115 commandData, options);
Tom Joseph07181f52016-08-08 08:17:08 -0500116 }
117 else
118 {
119 auto start = std::chrono::steady_clock::now();
120
Vernon Mauerycfb34ca2021-06-10 15:37:07 -0700121 // Ignore messages that are not part of an active/pre-active session
122 if (handler->sessionID != session::sessionZero)
123 {
124 std::shared_ptr<session::Session> session =
125 std::get<session::Manager&>(singletonPool)
126 .getSession(handler->sessionID);
127 auto state = static_cast<session::State>(session->state());
128 if ((state != session::State::setupInProgress) &&
129 (state != session::State::active))
130 {
131 return;
132 }
133 }
134
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800135 handler->outPayload =
136 iterator->second->executeCommand(commandData, handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500137
138 auto end = std::chrono::steady_clock::now();
139
Yong Li899cf5a2020-01-19 13:32:20 +0800140 std::chrono::duration<size_t> elapsedSeconds =
Vernon Mauery9e801a22018-10-12 13:20:49 -0700141 std::chrono::duration_cast<std::chrono::seconds>(end - start);
Tom Joseph07181f52016-08-08 08:17:08 -0500142
143 // If command time execution time exceeds 2 seconds, log a time
144 // exceeded message
145 if (elapsedSeconds > 2s)
146 {
Vernon Maueryfc37e592018-12-19 14:55:15 -0800147 log<level::ERR>("IPMI command timed out",
Yong Li899cf5a2020-01-19 13:32:20 +0800148 entry("DELAY=%zu", elapsedSeconds.count()));
Tom Joseph07181f52016-08-08 08:17:08 -0500149 }
150 }
Tom Joseph07181f52016-08-08 08:17:08 -0500151}
152
Vernon Mauery9e801a22018-10-12 13:20:49 -0700153std::vector<uint8_t>
154 NetIpmidEntry::executeCommand(std::vector<uint8_t>& commandData,
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800155 std::shared_ptr<message::Handler> handler)
Tom Joseph07181f52016-08-08 08:17:08 -0500156{
157 std::vector<uint8_t> errResponse;
158
159 // Check if the command qualifies to be run prior to establishing a session
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530160 if (!sessionless && (handler->sessionID == session::sessionZero))
Tom Joseph07181f52016-08-08 08:17:08 -0500161 {
162 errResponse.resize(1);
163 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
Vernon Maueryfc37e592018-12-19 14:55:15 -0800164 log<level::INFO>("Table: Insufficient privilege for command",
Vernon Mauery66501642018-07-30 09:07:10 -0700165 entry("LUN=%x", command.lun()),
166 entry("NETFN=%x", command.netFn()),
167 entry("CMD=%x", command.cmd()));
Tom Joseph07181f52016-08-08 08:17:08 -0500168 return errResponse;
169 }
170
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800171 return functor(commandData, *handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500172}
173
Tom Joseph07181f52016-08-08 08:17:08 -0500174} // namespace command