xref: /openbmc/google-ipmi-sys/pcie_i2c.cpp (revision 8c0094e4eb82029af1d111d2736111cbdda59b63)
1a2056e9cSWilly Tu // Copyright 2021 Google LLC
2a2056e9cSWilly Tu //
3a2056e9cSWilly Tu // Licensed under the Apache License, Version 2.0 (the "License");
4a2056e9cSWilly Tu // you may not use this file except in compliance with the License.
5a2056e9cSWilly Tu // You may obtain a copy of the License at
6a2056e9cSWilly Tu //
7a2056e9cSWilly Tu //      http://www.apache.org/licenses/LICENSE-2.0
8a2056e9cSWilly Tu //
9a2056e9cSWilly Tu // Unless required by applicable law or agreed to in writing, software
10a2056e9cSWilly Tu // distributed under the License is distributed on an "AS IS" BASIS,
11a2056e9cSWilly Tu // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a2056e9cSWilly Tu // See the License for the specific language governing permissions and
13a2056e9cSWilly Tu // limitations under the License.
142d4836dbSJaghathiswari Rankappagounder Natarajan 
152d4836dbSJaghathiswari Rankappagounder Natarajan #include "pcie_i2c.hpp"
162d4836dbSJaghathiswari Rankappagounder Natarajan 
170e9aae5dSPatrick Venture #include "commands.hpp"
18ff3cd8e9SWilly Tu #include "handler.hpp"
192d4836dbSJaghathiswari Rankappagounder Natarajan 
20444b5ea4SPatrick Williams #include <ipmid/api-types.hpp>
218d618532SMichael Shen #include <stdplus/print.hpp>
22444b5ea4SPatrick Williams 
232d4836dbSJaghathiswari Rankappagounder Natarajan #include <cstdint>
242d4836dbSJaghathiswari Rankappagounder Natarajan #include <cstring>
25b4e3704cSWilly Tu #include <span>
262d4836dbSJaghathiswari Rankappagounder Natarajan #include <string>
2772e1a882SPatrick Venture #include <tuple>
2872e1a882SPatrick Venture #include <vector>
292d4836dbSJaghathiswari Rankappagounder Natarajan 
302d4836dbSJaghathiswari Rankappagounder Natarajan namespace google
312d4836dbSJaghathiswari Rankappagounder Natarajan {
322d4836dbSJaghathiswari Rankappagounder Natarajan namespace ipmi
332d4836dbSJaghathiswari Rankappagounder Natarajan {
342d4836dbSJaghathiswari Rankappagounder Natarajan 
352d4836dbSJaghathiswari Rankappagounder Natarajan #ifndef MAX_IPMI_BUFFER
362d4836dbSJaghathiswari Rankappagounder Natarajan #define MAX_IPMI_BUFFER 64
372d4836dbSJaghathiswari Rankappagounder Natarajan #endif
382d4836dbSJaghathiswari Rankappagounder Natarajan 
392d4836dbSJaghathiswari Rankappagounder Natarajan struct PcieSlotI2cBusMappingRequest
402d4836dbSJaghathiswari Rankappagounder Natarajan {
412d4836dbSJaghathiswari Rankappagounder Natarajan     uint8_t entry;
422d4836dbSJaghathiswari Rankappagounder Natarajan } __attribute__((packed));
432d4836dbSJaghathiswari Rankappagounder Natarajan 
pcieSlotCount(std::span<const uint8_t>,HandlerInterface * handler)44b4e3704cSWilly Tu Resp pcieSlotCount(std::span<const uint8_t>, HandlerInterface* handler)
452d4836dbSJaghathiswari Rankappagounder Natarajan {
462d4836dbSJaghathiswari Rankappagounder Natarajan     // If there are already entries in the vector, clear them.
4749f23ad9SPatrick Venture     handler->buildI2cPcieMapping();
482d4836dbSJaghathiswari Rankappagounder Natarajan 
492d4836dbSJaghathiswari Rankappagounder Natarajan     // Fill the pcie slot count as the number of entries in the vector.
50ff3cd8e9SWilly Tu     std::uint8_t value = handler->getI2cPcieMappingSize();
512d4836dbSJaghathiswari Rankappagounder Natarajan 
52ff3cd8e9SWilly Tu     return ::ipmi::responseSuccess(SysOEMCommands::SysPcieSlotCount,
53ff3cd8e9SWilly Tu                                    std::vector<std::uint8_t>{value});
542d4836dbSJaghathiswari Rankappagounder Natarajan }
552d4836dbSJaghathiswari Rankappagounder Natarajan 
pcieSlotI2cBusMapping(std::span<const uint8_t> data,HandlerInterface * handler)56b4e3704cSWilly Tu Resp pcieSlotI2cBusMapping(std::span<const uint8_t> data,
57ff3cd8e9SWilly Tu                            HandlerInterface* handler)
582d4836dbSJaghathiswari Rankappagounder Natarajan {
592d4836dbSJaghathiswari Rankappagounder Natarajan     struct PcieSlotI2cBusMappingRequest request;
602d4836dbSJaghathiswari Rankappagounder Natarajan 
61ff3cd8e9SWilly Tu     if (data.size() < sizeof(request))
622d4836dbSJaghathiswari Rankappagounder Natarajan     {
638d618532SMichael Shen         stdplus::print(stderr, "Invalid command length: {}\n", data.size());
64ff3cd8e9SWilly Tu         return ::ipmi::responseReqDataLenInvalid();
652d4836dbSJaghathiswari Rankappagounder Natarajan     }
662d4836dbSJaghathiswari Rankappagounder Natarajan 
672d4836dbSJaghathiswari Rankappagounder Natarajan     // If there are no entries in the vector return error.
6849f23ad9SPatrick Venture     size_t mapSize = handler->getI2cPcieMappingSize();
6949f23ad9SPatrick Venture     if (mapSize == 0)
702d4836dbSJaghathiswari Rankappagounder Natarajan     {
71ff3cd8e9SWilly Tu         return ::ipmi::responseInvalidReservationId();
722d4836dbSJaghathiswari Rankappagounder Natarajan     }
732d4836dbSJaghathiswari Rankappagounder Natarajan 
74ff3cd8e9SWilly Tu     std::memcpy(&request, data.data(), sizeof(request));
752d4836dbSJaghathiswari Rankappagounder Natarajan 
762d4836dbSJaghathiswari Rankappagounder Natarajan     // The valid entries range from 0 to N - 1, N being the total number of
772d4836dbSJaghathiswari Rankappagounder Natarajan     // entries in the vector.
7849f23ad9SPatrick Venture     if (request.entry >= mapSize)
792d4836dbSJaghathiswari Rankappagounder Natarajan     {
80ff3cd8e9SWilly Tu         return ::ipmi::responseParmOutOfRange();
812d4836dbSJaghathiswari Rankappagounder Natarajan     }
822d4836dbSJaghathiswari Rankappagounder Natarajan 
832d4836dbSJaghathiswari Rankappagounder Natarajan     // Get the i2c bus number and the pcie slot name from the vector.
8449f23ad9SPatrick Venture     auto i2cEntry = handler->getI2cEntry(request.entry);
8549f23ad9SPatrick Venture     uint32_t i2c_bus_number = std::get<0>(i2cEntry);
8649f23ad9SPatrick Venture     std::string pcie_slot_name = std::get<1>(i2cEntry);
872d4836dbSJaghathiswari Rankappagounder Natarajan 
88444b5ea4SPatrick Williams     int length = sizeof(struct PcieSlotI2cBusMappingReply) +
89444b5ea4SPatrick Williams                  pcie_slot_name.length();
902d4836dbSJaghathiswari Rankappagounder Natarajan 
912d4836dbSJaghathiswari Rankappagounder Natarajan     // TODO (jaghu) : Add a way to dynamically receive the MAX_IPMI_BUFFER
922d4836dbSJaghathiswari Rankappagounder Natarajan     // value and change error to IPMI_CC_REQUESTED_TOO_MANY_BYTES.
932d4836dbSJaghathiswari Rankappagounder Natarajan     if (length > MAX_IPMI_BUFFER)
942d4836dbSJaghathiswari Rankappagounder Natarajan     {
958d618532SMichael Shen         stdplus::print(stderr, "Response would overflow response buffer\n");
96ff3cd8e9SWilly Tu         return ::ipmi::responseInvalidCommand();
972d4836dbSJaghathiswari Rankappagounder Natarajan     }
982d4836dbSJaghathiswari Rankappagounder Natarajan 
99ff3cd8e9SWilly Tu     std::vector<std::uint8_t> reply;
100*8c0094e4SPatrick Williams     reply.reserve(
101*8c0094e4SPatrick Williams         pcie_slot_name.length() + sizeof(struct PcieSlotI2cBusMappingReply));
1022d4836dbSJaghathiswari Rankappagounder Natarajan     // Copy the i2c bus number and the pcie slot name to the reply struct.
103ff3cd8e9SWilly Tu     reply.emplace_back(i2c_bus_number);          /* i2c_bus_number */
104ff3cd8e9SWilly Tu     reply.emplace_back(pcie_slot_name.length()); /* pcie_slot_name length */
105ff3cd8e9SWilly Tu     reply.insert(reply.end(), pcie_slot_name.begin(),
106ff3cd8e9SWilly Tu                  pcie_slot_name.end());          /* pcie_slot_name */
1072d4836dbSJaghathiswari Rankappagounder Natarajan 
108ff3cd8e9SWilly Tu     return ::ipmi::responseSuccess(SysOEMCommands::SysPcieSlotI2cBusMapping,
109ff3cd8e9SWilly Tu                                    reply);
1102d4836dbSJaghathiswari Rankappagounder Natarajan }
1112d4836dbSJaghathiswari Rankappagounder Natarajan } // namespace ipmi
1122d4836dbSJaghathiswari Rankappagounder Natarajan } // namespace google
113