blob: 07ad1579dd4a7d81896206b03571324ba980a680 [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 {
44 std::cerr << "E> Table:: Command Not found: 0x" << std::hex << inCommand
45 << "\n";
46
47 response.resize(1);
48 response[0] = IPMI_CC_INVALID;
49 }
50 else
51 {
52 auto start = std::chrono::steady_clock::now();
53
54 response = iterator->second->executeCommand(commandData, handler);
55
56 auto end = std::chrono::steady_clock::now();
57
58 auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>
59 (end - start);
60
61 // If command time execution time exceeds 2 seconds, log a time
62 // exceeded message
63 if (elapsedSeconds > 2s)
64 {
65 std::cerr << "E> IPMI command timed out:Elapsed time = "
66 << elapsedSeconds.count() << "s" << "\n";
67 }
68 }
69 return response;
70}
71
72std::vector<uint8_t> NetIpmidEntry::executeCommand(
73 std::vector<uint8_t>& commandData,
74 const message::Handler& handler)
75{
76 std::vector<uint8_t> errResponse;
77
78 // Check if the command qualifies to be run prior to establishing a session
79 if (!sessionless && (handler.sessionID == session::SESSION_ZERO))
80 {
81 errResponse.resize(1);
82 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
83 std::cerr << "E> Table::Not enough privileges for command 0x"
84 << std::hex << command.command << "\n";
85 return errResponse;
86 }
87
88 return functor(commandData, handler);
89}
90
Tom606e8cb2016-12-02 13:36:14 +053091std::vector<uint8_t> ProviderIpmidEntry::executeCommand(
92 std::vector<uint8_t>& commandData,
93 const message::Handler& handler)
94{
Tom Joseph1efcb492017-01-31 16:56:47 +053095 std::vector<uint8_t> response(message::parser::MAX_PAYLOAD_SIZE - 1);
Feist, Jamesbd45aae2017-10-26 15:06:13 -070096 size_t respSize = commandData.size();
Tom606e8cb2016-12-02 13:36:14 +053097
98 ipmi_ret_t ipmiRC = functor(0, 0,
99 reinterpret_cast<void*>(commandData.data()),
100 reinterpret_cast<void*>(response.data() + 1),
101 &respSize, NULL);
102
103 /*
104 * respSize gets you the size of the response data for the IPMI command. The
105 * first byte in a response to the IPMI command is the Completion Code.
106 * So we are inserting completion code as the first byte and incrementing
107 * the response payload size by the size of the completion code.
108 */
109 response[0] = ipmiRC;
110 response.resize(respSize + sizeof(ipmi_ret_t));
111
112 return response;
113}
114
Tom Joseph07181f52016-08-08 08:17:08 -0500115} // namespace command