blob: 5f45650163dd7096db2443c654cadfd2c1cf7eaf [file] [log] [blame]
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -08001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "pcie_i2c.hpp"
18
19#include "main.hpp"
Patrick Venture8d5c9ce2019-03-16 11:20:12 -070020#include "util.hpp"
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -080021
22#include <cstdint>
23#include <cstring>
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -080024#include <string>
Patrick Venture72e1a882019-03-16 11:43:08 -070025#include <tuple>
26#include <vector>
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -080027
28namespace google
29{
30namespace ipmi
31{
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -080032
33namespace
34{
35
36#ifndef MAX_IPMI_BUFFER
37#define MAX_IPMI_BUFFER 64
38#endif
39
40std::vector<std::tuple<uint32_t, std::string>> pcie_i2c_map;
41
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -080042} // namespace
43
44struct PcieSlotCountRequest
45{
46 uint8_t subcommand;
47} __attribute__((packed));
48
49struct PcieSlotCountReply
50{
51 uint8_t subcommand;
52 uint8_t value;
53} __attribute__((packed));
54
55struct PcieSlotI2cBusMappingRequest
56{
57 uint8_t subcommand;
58 uint8_t entry;
59} __attribute__((packed));
60
61struct PcieSlotI2cBusMappingReply
62{
63 uint8_t subcommand;
64 uint8_t i2c_bus_number;
65 uint8_t pcie_slot_name_len;
66 uint8_t pcie_slot_name[0];
67} __attribute__((packed));
68
69ipmi_ret_t PcieSlotCount(const uint8_t* reqBuf, uint8_t* replyBuf,
70 size_t* dataLen)
71{
72 if ((*dataLen) < sizeof(struct PcieSlotCountRequest))
73 {
74 std::fprintf(stderr, "Invalid command length: %u\n",
75 static_cast<uint32_t>(*dataLen));
76 return IPMI_CC_REQ_DATA_LEN_INVALID;
77 }
78
79 // If there are already entries in the vector, clear them.
Patrick Venture3fb74292019-03-16 11:32:16 -070080 pcie_i2c_map = buildPcieMap();
Jaghathiswari Rankappagounder Natarajan2d4836d2018-11-29 14:16:39 -080081
82 struct PcieSlotCountReply reply;
83 reply.subcommand = SysPcieSlotCount;
84 // Fill the pcie slot count as the number of entries in the vector.
85 reply.value = pcie_i2c_map.size();
86
87 std::memcpy(&replyBuf[0], &reply, sizeof(reply));
88
89 // Return the subcommand and the result.
90 (*dataLen) = sizeof(reply);
91
92 return IPMI_CC_OK;
93}
94
95ipmi_ret_t PcieSlotI2cBusMapping(const uint8_t* reqBuf, uint8_t* replyBuf,
96 size_t* dataLen)
97{
98 struct PcieSlotI2cBusMappingRequest request;
99
100 if ((*dataLen) < sizeof(request))
101 {
102 std::fprintf(stderr, "Invalid command length: %u\n",
103 static_cast<uint32_t>(*dataLen));
104 return IPMI_CC_REQ_DATA_LEN_INVALID;
105 }
106
107 // If there are no entries in the vector return error.
108 if (pcie_i2c_map.empty())
109 {
110 return IPMI_CC_INVALID_RESERVATION_ID;
111 }
112
113 std::memcpy(&request, &reqBuf[0], sizeof(request));
114
115 // The valid entries range from 0 to N - 1, N being the total number of
116 // entries in the vector.
117 if (request.entry >= pcie_i2c_map.size())
118 {
119 return IPMI_CC_PARM_OUT_OF_RANGE;
120 }
121
122 // Get the i2c bus number and the pcie slot name from the vector.
123 uint32_t i2c_bus_number = std::get<0>(pcie_i2c_map[request.entry]);
124 std::string pcie_slot_name = std::get<1>(pcie_i2c_map[request.entry]);
125
126 int length =
127 sizeof(struct PcieSlotI2cBusMappingReply) + pcie_slot_name.length();
128
129 // TODO (jaghu) : Add a way to dynamically receive the MAX_IPMI_BUFFER
130 // value and change error to IPMI_CC_REQUESTED_TOO_MANY_BYTES.
131 if (length > MAX_IPMI_BUFFER)
132 {
133 std::fprintf(stderr, "Response would overflow response buffer\n");
134 return IPMI_CC_INVALID;
135 }
136
137 auto reply =
138 reinterpret_cast<struct PcieSlotI2cBusMappingReply*>(&replyBuf[0]);
139 reply->subcommand = SysPcieSlotI2cBusMapping;
140 // Copy the i2c bus number and the pcie slot name to the reply struct.
141 reply->i2c_bus_number = i2c_bus_number;
142 reply->pcie_slot_name_len = pcie_slot_name.length();
143 std::memcpy(reply->pcie_slot_name, pcie_slot_name.c_str(),
144 pcie_slot_name.length());
145
146 // Return the subcommand and the result.
147 (*dataLen) = length;
148 return IPMI_CC_OK;
149}
150} // namespace ipmi
151} // namespace google