blob: 7775022bae6efeb9b80568b62c59f70befe89f2e [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#include "command_table.hpp"
2
3#include <iomanip>
4#include <iostream>
5
Tom Joseph07181f52016-08-08 08:17:08 -05006#include "message_handler.hpp"
Tom Joseph1efcb492017-01-31 16:56:47 +05307#include "message_parsers.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05008#include "sessions_manager.hpp"
Nagaraju Goruganti1d9d4162018-03-22 01:27:37 -05009#include <phosphor-logging/log.hpp>
10#include <phosphor-logging/elog-errors.hpp>
11#include "xyz/openbmc_project/Common/error.hpp"
12
13using namespace phosphor::logging;
Tom Joseph07181f52016-08-08 08:17:08 -050014
15namespace command
16{
17
18void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
19{
Feist, Jamesbd45aae2017-10-26 15:06:13 -070020 auto& command = commandTable[inCommand.command];
21
22 if (command)
23 {
Nagaraju Goruganti1d9d4162018-03-22 01:27:37 -050024 log<level::DEBUG>("Already Registered", phosphor::logging::entry(
25 "SKIPPED_ENTRY=0x%x", uint32_t(inCommand.command)));
Feist, Jamesbd45aae2017-10-26 15:06:13 -070026 return;
27 }
28
Feist, Jamesbd45aae2017-10-26 15:06:13 -070029 command = std::move(entry);
Tom Joseph07181f52016-08-08 08:17:08 -050030}
31
32std::vector<uint8_t> Table::executeCommand(uint32_t inCommand,
33 std::vector<uint8_t>& commandData,
34 const message::Handler& handler)
35{
36 using namespace std::chrono_literals;
37
38 std::vector<uint8_t> response;
39
40 auto iterator = commandTable.find(inCommand);
41
42 if (iterator == commandTable.end())
43 {
Tom Joseph07181f52016-08-08 08:17:08 -050044 response.resize(1);
45 response[0] = IPMI_CC_INVALID;
46 }
47 else
48 {
49 auto start = std::chrono::steady_clock::now();
50
51 response = iterator->second->executeCommand(commandData, handler);
52
53 auto end = std::chrono::steady_clock::now();
54
55 auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>
56 (end - start);
57
58 // If command time execution time exceeds 2 seconds, log a time
59 // exceeded message
60 if (elapsedSeconds > 2s)
61 {
62 std::cerr << "E> IPMI command timed out:Elapsed time = "
63 << elapsedSeconds.count() << "s" << "\n";
64 }
65 }
66 return response;
67}
68
69std::vector<uint8_t> NetIpmidEntry::executeCommand(
70 std::vector<uint8_t>& commandData,
71 const message::Handler& handler)
72{
73 std::vector<uint8_t> errResponse;
74
75 // Check if the command qualifies to be run prior to establishing a session
76 if (!sessionless && (handler.sessionID == session::SESSION_ZERO))
77 {
78 errResponse.resize(1);
79 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
80 std::cerr << "E> Table::Not enough privileges for command 0x"
81 << std::hex << command.command << "\n";
82 return errResponse;
83 }
84
85 return functor(commandData, handler);
86}
87
Tom606e8cb2016-12-02 13:36:14 +053088std::vector<uint8_t> ProviderIpmidEntry::executeCommand(
89 std::vector<uint8_t>& commandData,
90 const message::Handler& handler)
91{
Tom Joseph1efcb492017-01-31 16:56:47 +053092 std::vector<uint8_t> response(message::parser::MAX_PAYLOAD_SIZE - 1);
Feist, Jamesbd45aae2017-10-26 15:06:13 -070093 size_t respSize = commandData.size();
Tom606e8cb2016-12-02 13:36:14 +053094
95 ipmi_ret_t ipmiRC = functor(0, 0,
96 reinterpret_cast<void*>(commandData.data()),
97 reinterpret_cast<void*>(response.data() + 1),
98 &respSize, NULL);
99
100 /*
101 * respSize gets you the size of the response data for the IPMI command. The
102 * first byte in a response to the IPMI command is the Completion Code.
103 * So we are inserting completion code as the first byte and incrementing
104 * the response payload size by the size of the completion code.
105 */
106 response[0] = ipmiRC;
107 response.resize(respSize + sizeof(ipmi_ret_t));
108
109 return response;
110}
111
Tom Joseph07181f52016-08-08 08:17:08 -0500112} // namespace command