1 #include "channel.hpp"
2 #include "types.hpp"
3 #include "transporthandler.hpp"
4 #include "utils.hpp"
5 #include "net.hpp"
6 
7 #include <string>
8 #include <arpa/inet.h>
9 
10 #include <phosphor-logging/log.hpp>
11 #include <phosphor-logging/elog-errors.hpp>
12 #include "xyz/openbmc_project/Common/error.hpp"
13 
14 
15 using namespace phosphor::logging;
16 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
17 
18 /** @struct GetChannelAccessRequest
19  *
20  *  IPMI payload for Get Channel access command request.
21  */
22 struct GetChannelAccessRequest
23 {
24     uint8_t channelNumber;      //!< Channel number.
25     uint8_t volatileSetting;    //!< Get non-volatile or the volatile setting.
26 } __attribute__((packed));
27 
28 /** @struct GetChannelAccessResponse
29  *
30  *  IPMI payload for Get Channel access command response.
31  */
32 struct GetChannelAccessResponse
33 {
34     uint8_t settings;          //!< Channel settings.
35     uint8_t privilegeLimit;    //!< Channel privilege level limit.
36 } __attribute__((packed));
37 
38 
39 ipmi_ret_t ipmi_get_channel_access(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
40                             ipmi_request_t request, ipmi_response_t response,
41                             ipmi_data_len_t data_len, ipmi_context_t context)
42 {
43     auto requestData = reinterpret_cast<const GetChannelAccessRequest*>
44                    (request);
45     std::vector<uint8_t> outPayload(sizeof(GetChannelAccessResponse));
46     auto responseData = reinterpret_cast<GetChannelAccessResponse*>
47             (outPayload.data());
48 
49     /*
50      * The value Eh is used as a way to identify the current channel that
51      * the command is being received from.
52      */
53     constexpr auto channelE = 0x0E;
54     int channel = requestData->channelNumber;
55     auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
56 
57     if (channel != channelE && ethdevice.empty())
58     {
59         *data_len = 0;
60         return IPMI_CC_INVALID_FIELD_REQUEST;
61     }
62 
63     /*
64      * [7:6] - reserved
65      * [5]   - 1b = Alerting disabled
66      * [4]   - 1b = per message authentication disabled
67      * [3]   - 0b = User level authentication enabled
68      * [2:0] - 2h = always available
69      */
70     constexpr auto channelSetting = 0x32;
71 
72     responseData->settings = channelSetting;
73     //Defaulting the channel privilege to administrator level.
74     responseData->privilegeLimit = PRIVILEGE_ADMIN;
75 
76     *data_len = outPayload.size();
77     memcpy(response, outPayload.data(), *data_len);
78 
79     return IPMI_CC_OK;
80 }
81 
82 // ATTENTION: This ipmi function is very hardcoded on purpose
83 // OpenBMC does not fully support IPMI.  This command is useful
84 // to have around because it enables testing of interfaces with
85 // the IPMI tool.
86 #define GET_CHANNEL_INFO_CHANNEL_OFFSET 0
87 // IPMI Table 6-2
88 #define IPMI_CHANNEL_TYPE_IPMB 1
89 // IPMI Table 6-3
90 #define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6
91 
92 ipmi_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
93                              ipmi_request_t request, ipmi_response_t response,
94                              ipmi_data_len_t data_len, ipmi_context_t context)
95 {
96     ipmi_ret_t rc = IPMI_CC_OK;
97     uint8_t resp[] = {
98         1,
99         IPMI_CHANNEL_MEDIUM_TYPE_OTHER,
100         IPMI_CHANNEL_TYPE_IPMB,
101         1,0x41,0xA7,0x00,0,0};
102     uint8_t *p = (uint8_t*) request;
103     int channel = (*p) & CHANNEL_MASK;
104     std::string ethdevice = ipmi::network::ChanneltoEthernet(channel);
105 
106     printf("IPMI APP GET CHANNEL INFO\n");
107 
108     // The supported channels numbers are those which are configured.
109     // Channel Number E is used as way to identify the current channel
110     // that the command is being is received from.
111     if (channel != 0xe && ethdevice.empty()) {
112         rc = IPMI_CC_PARM_OUT_OF_RANGE;
113         *data_len = 0;
114     } else {
115         *data_len = sizeof(resp);
116         memcpy(response, resp, *data_len);
117     }
118 
119     return rc;
120 }
121