blob: a49f92c22c8fb7dc91465bac09006356782ee577 [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#include "command_table.hpp"
2
3#include <iomanip>
4#include <iostream>
5
6#include <host-ipmid/ipmid-api.h>
7#include "message_handler.hpp"
8#include "sessions_manager.hpp"
9
10namespace command
11{
12
13void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
14{
15 std::cout << "I> Registering Command" << std::hex
16 << inCommand.command << "\n";
17
18 commandTable[inCommand.command] = std::move(entry);
19}
20
21std::vector<uint8_t> Table::executeCommand(uint32_t inCommand,
22 std::vector<uint8_t>& commandData,
23 const message::Handler& handler)
24{
25 using namespace std::chrono_literals;
26
27 std::vector<uint8_t> response;
28
29 auto iterator = commandTable.find(inCommand);
30
31 if (iterator == commandTable.end())
32 {
33 std::cerr << "E> Table:: Command Not found: 0x" << std::hex << inCommand
34 << "\n";
35
36 response.resize(1);
37 response[0] = IPMI_CC_INVALID;
38 }
39 else
40 {
41 auto start = std::chrono::steady_clock::now();
42
43 response = iterator->second->executeCommand(commandData, handler);
44
45 auto end = std::chrono::steady_clock::now();
46
47 auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>
48 (end - start);
49
50 // If command time execution time exceeds 2 seconds, log a time
51 // exceeded message
52 if (elapsedSeconds > 2s)
53 {
54 std::cerr << "E> IPMI command timed out:Elapsed time = "
55 << elapsedSeconds.count() << "s" << "\n";
56 }
57 }
58 return response;
59}
60
61std::vector<uint8_t> NetIpmidEntry::executeCommand(
62 std::vector<uint8_t>& commandData,
63 const message::Handler& handler)
64{
65 std::vector<uint8_t> errResponse;
66
67 // Check if the command qualifies to be run prior to establishing a session
68 if (!sessionless && (handler.sessionID == session::SESSION_ZERO))
69 {
70 errResponse.resize(1);
71 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
72 std::cerr << "E> Table::Not enough privileges for command 0x"
73 << std::hex << command.command << "\n";
74 return errResponse;
75 }
76
77 return functor(commandData, handler);
78}
79
Tom606e8cb2016-12-02 13:36:14 +053080std::vector<uint8_t> ProviderIpmidEntry::executeCommand(
81 std::vector<uint8_t>& commandData,
82 const message::Handler& handler)
83{
84
85 std::vector<uint8_t> response(MAX_IPMI_BUFFER);
86 size_t respSize {};
87
88 ipmi_ret_t ipmiRC = functor(0, 0,
89 reinterpret_cast<void*>(commandData.data()),
90 reinterpret_cast<void*>(response.data() + 1),
91 &respSize, NULL);
92
93 /*
94 * respSize gets you the size of the response data for the IPMI command. The
95 * first byte in a response to the IPMI command is the Completion Code.
96 * So we are inserting completion code as the first byte and incrementing
97 * the response payload size by the size of the completion code.
98 */
99 response[0] = ipmiRC;
100 response.resize(respSize + sizeof(ipmi_ret_t));
101
102 return response;
103}
104
Tom Joseph07181f52016-08-08 08:17:08 -0500105} // namespace command