blob: 15142743bb4c2501d6c813bed196b5897aebf9f8 [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>
Patrick Williams75a8d8b2021-09-02 11:30:44 -05009#include <ipmid/types.hpp>
Vernon Mauery66501642018-07-30 09:07:10 -070010#include <main.hpp>
Vernon Mauery9e801a22018-10-12 13:20:49 -070011#include <phosphor-logging/elog-errors.hpp>
12#include <phosphor-logging/log.hpp>
Vernon Mauery66501642018-07-30 09:07:10 -070013#include <user_channel/user_layer.hpp>
Vernon Maueryf41a5542018-10-15 16:04:17 -070014#include <xyz/openbmc_project/Common/error.hpp>
Vernon Mauery9e801a22018-10-12 13:20:49 -070015
Vernon Mauery66501642018-07-30 09:07:10 -070016using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Nagaraju Goruganti1d9d4162018-03-22 01:27:37 -050017using namespace phosphor::logging;
Tom Joseph07181f52016-08-08 08:17:08 -050018
19namespace command
20{
21
22void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
23{
Feist, Jamesbd45aae2017-10-26 15:06:13 -070024 auto& command = commandTable[inCommand.command];
25
26 if (command)
27 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070028 log<level::DEBUG>(
29 "Already Registered",
Vernon Mauery66501642018-07-30 09:07:10 -070030 phosphor::logging::entry("SKIPPED_ENTRY=0x%x", inCommand.command));
Feist, Jamesbd45aae2017-10-26 15:06:13 -070031 return;
32 }
33
Feist, Jamesbd45aae2017-10-26 15:06:13 -070034 command = std::move(entry);
Tom Joseph07181f52016-08-08 08:17:08 -050035}
36
Vernon Mauery8d6f2002018-11-07 09:55:53 -080037void Table::executeCommand(uint32_t inCommand,
38 std::vector<uint8_t>& commandData,
39 std::shared_ptr<message::Handler> handler)
Tom Joseph07181f52016-08-08 08:17:08 -050040{
41 using namespace std::chrono_literals;
42
Tom Joseph07181f52016-08-08 08:17:08 -050043 auto iterator = commandTable.find(inCommand);
44
45 if (iterator == commandTable.end())
46 {
Vernon Mauery66501642018-07-30 09:07:10 -070047 CommandID command(inCommand);
48
Vernon Mauery779e7e12021-06-08 16:24:45 -070049 // Do not forward any session zero commands to ipmid
50 if (handler->sessionID == session::sessionZero)
51 {
52 log<level::INFO>("Table: refuse to forward session-zero command",
53 entry("LUN=%x", command.lun()),
54 entry("NETFN=%x", command.netFn()),
55 entry("CMD=%x", command.cmd()));
56 return;
57 }
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070058 std::shared_ptr<session::Session> session =
Vernon Mauery2085ae02021-06-10 11:51:00 -070059 session::Manager::get().getSession(handler->sessionID);
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070060
61 // Ignore messages that are not part of an active session
62 auto state = static_cast<session::State>(session->state());
63 if (state != session::State::active)
64 {
65 return;
66 }
Vernon Mauery779e7e12021-06-08 16:24:45 -070067
Vernon Mauery66501642018-07-30 09:07:10 -070068 auto bus = getSdBus();
69 // forward the request onto the main ipmi queue
Vernon Mauery8d6f2002018-11-07 09:55:53 -080070 using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
71 std::vector<uint8_t>>;
Vernon Mauery66501642018-07-30 09:07:10 -070072 uint8_t lun = command.lun();
73 uint8_t netFn = command.netFn();
74 uint8_t cmd = command.cmd();
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070075
Vernon Mauery66501642018-07-30 09:07:10 -070076 std::map<std::string, ipmi::Value> options = {
Vernon Maueryd92bc322019-03-15 15:24:30 -070077 {"userId", ipmi::Value(static_cast<int>(
78 ipmi::ipmiUserGetUserId(session->userName)))},
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053079 {"privilege",
80 ipmi::Value(static_cast<int>(session->currentPrivilege()))},
Rajashekar Gade Reddy49a94b22019-11-13 16:46:32 +053081 {"currentSessionId",
82 ipmi::Value(static_cast<uint32_t>(session->getBMCSessionID()))},
Vernon Mauery66501642018-07-30 09:07:10 -070083 };
Vernon Mauery8d6f2002018-11-07 09:55:53 -080084 bus->async_method_call(
85 [handler, this](const boost::system::error_code& ec,
86 const IpmiDbusRspType& response) {
87 if (!ec)
88 {
89 const uint8_t& cc = std::get<3>(response);
90 const std::vector<uint8_t>& responseData =
91 std::get<4>(response);
92 std::vector<uint8_t> payload;
93 payload.reserve(1 + responseData.size());
94 payload.push_back(cc);
95 payload.insert(payload.end(), responseData.begin(),
96 responseData.end());
97 handler->outPayload = std::move(payload);
98 }
99 else
100 {
101 std::vector<uint8_t> payload;
102 payload.push_back(IPMI_CC_UNSPECIFIED_ERROR);
103 handler->outPayload = std::move(payload);
104 }
105 },
106 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
107 "xyz.openbmc_project.Ipmi.Server", "execute", netFn, lun, cmd,
108 commandData, options);
Tom Joseph07181f52016-08-08 08:17:08 -0500109 }
110 else
111 {
112 auto start = std::chrono::steady_clock::now();
113
Vernon Mauerycfb34ca2021-06-10 15:37:07 -0700114 // Ignore messages that are not part of an active/pre-active session
115 if (handler->sessionID != session::sessionZero)
116 {
117 std::shared_ptr<session::Session> session =
Vernon Mauery2085ae02021-06-10 11:51:00 -0700118 session::Manager::get().getSession(handler->sessionID);
Vernon Mauerycfb34ca2021-06-10 15:37:07 -0700119 auto state = static_cast<session::State>(session->state());
120 if ((state != session::State::setupInProgress) &&
121 (state != session::State::active))
122 {
123 return;
124 }
125 }
126
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800127 handler->outPayload =
128 iterator->second->executeCommand(commandData, handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500129
130 auto end = std::chrono::steady_clock::now();
131
Yong Li899cf5a2020-01-19 13:32:20 +0800132 std::chrono::duration<size_t> elapsedSeconds =
Vernon Mauery9e801a22018-10-12 13:20:49 -0700133 std::chrono::duration_cast<std::chrono::seconds>(end - start);
Tom Joseph07181f52016-08-08 08:17:08 -0500134
135 // If command time execution time exceeds 2 seconds, log a time
136 // exceeded message
137 if (elapsedSeconds > 2s)
138 {
Vernon Maueryfc37e592018-12-19 14:55:15 -0800139 log<level::ERR>("IPMI command timed out",
Yong Li899cf5a2020-01-19 13:32:20 +0800140 entry("DELAY=%zu", elapsedSeconds.count()));
Tom Joseph07181f52016-08-08 08:17:08 -0500141 }
142 }
Tom Joseph07181f52016-08-08 08:17:08 -0500143}
144
Vernon Mauery9e801a22018-10-12 13:20:49 -0700145std::vector<uint8_t>
146 NetIpmidEntry::executeCommand(std::vector<uint8_t>& commandData,
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800147 std::shared_ptr<message::Handler> handler)
Tom Joseph07181f52016-08-08 08:17:08 -0500148{
149 std::vector<uint8_t> errResponse;
150
151 // Check if the command qualifies to be run prior to establishing a session
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530152 if (!sessionless && (handler->sessionID == session::sessionZero))
Tom Joseph07181f52016-08-08 08:17:08 -0500153 {
154 errResponse.resize(1);
155 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
Vernon Maueryfc37e592018-12-19 14:55:15 -0800156 log<level::INFO>("Table: Insufficient privilege for command",
Vernon Mauery66501642018-07-30 09:07:10 -0700157 entry("LUN=%x", command.lun()),
158 entry("NETFN=%x", command.netFn()),
159 entry("CMD=%x", command.cmd()));
Tom Joseph07181f52016-08-08 08:17:08 -0500160 return errResponse;
161 }
162
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700163 return functor(commandData, handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500164}
165
Tom Joseph07181f52016-08-08 08:17:08 -0500166} // namespace command