16c71b0f9SWilly Tu // Copyright 2022 Google LLC
26c71b0f9SWilly Tu //
36c71b0f9SWilly Tu // Licensed under the Apache License, Version 2.0 (the "License");
46c71b0f9SWilly Tu // you may not use this file except in compliance with the License.
56c71b0f9SWilly Tu // You may obtain a copy of the License at
66c71b0f9SWilly Tu //
76c71b0f9SWilly Tu //      http://www.apache.org/licenses/LICENSE-2.0
86c71b0f9SWilly Tu //
96c71b0f9SWilly Tu // Unless required by applicable law or agreed to in writing, software
106c71b0f9SWilly Tu // distributed under the License is distributed on an "AS IS" BASIS,
116c71b0f9SWilly Tu // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126c71b0f9SWilly Tu // See the License for the specific language governing permissions and
136c71b0f9SWilly Tu // limitations under the License.
146c71b0f9SWilly Tu 
156c71b0f9SWilly Tu #include "config.h"
166c71b0f9SWilly Tu 
176c71b0f9SWilly Tu #include "pcie_bifurcation.hpp"
186c71b0f9SWilly Tu 
196c71b0f9SWilly Tu #include "commands.hpp"
206c71b0f9SWilly Tu #include "errors.hpp"
216c71b0f9SWilly Tu #include "handler.hpp"
226c71b0f9SWilly Tu 
236c71b0f9SWilly Tu #include <ipmid/api-types.hpp>
248d618532SMichael Shen #include <stdplus/print.hpp>
25444b5ea4SPatrick Williams 
266c71b0f9SWilly Tu #include <span>
276c71b0f9SWilly Tu #include <vector>
286c71b0f9SWilly Tu 
296c71b0f9SWilly Tu namespace google
306c71b0f9SWilly Tu {
316c71b0f9SWilly Tu namespace ipmi
326c71b0f9SWilly Tu {
336c71b0f9SWilly Tu 
346c71b0f9SWilly Tu namespace
356c71b0f9SWilly Tu {
366c71b0f9SWilly Tu #ifndef MAX_IPMI_BUFFER
376c71b0f9SWilly Tu #define MAX_IPMI_BUFFER 64
386c71b0f9SWilly Tu #endif
396c71b0f9SWilly Tu } // namespace
406c71b0f9SWilly Tu 
416c71b0f9SWilly Tu struct PcieBifurcationRequest
426c71b0f9SWilly Tu {
436c71b0f9SWilly Tu     uint8_t pcieIndex;
446c71b0f9SWilly Tu } __attribute__((packed));
456c71b0f9SWilly Tu 
pcieBifurcation(std::span<const uint8_t> data,HandlerInterface * handler)466c71b0f9SWilly Tu Resp pcieBifurcation(std::span<const uint8_t> data, HandlerInterface* handler)
476c71b0f9SWilly Tu {
486c71b0f9SWilly Tu     if (data.size() < sizeof(struct PcieBifurcationRequest))
496c71b0f9SWilly Tu     {
50*c5b55232SWilly Tu         stdplus::print(stderr, "Invalid command length: {}\n",
516c71b0f9SWilly Tu                        static_cast<uint32_t>(data.size()));
526c71b0f9SWilly Tu         return ::ipmi::responseReqDataLenInvalid();
536c71b0f9SWilly Tu     }
546c71b0f9SWilly Tu 
556c71b0f9SWilly Tu     auto bifurcation = handler->pcieBifurcation(/*index=*/data[0]);
566c71b0f9SWilly Tu 
576c71b0f9SWilly Tu     int length = sizeof(struct PcieBifurcationReply) + bifurcation.size();
586c71b0f9SWilly Tu 
596c71b0f9SWilly Tu     if (length > MAX_IPMI_BUFFER)
606c71b0f9SWilly Tu     {
618d618532SMichael Shen         stdplus::print(stderr, "Response would overflow response buffer\n");
626c71b0f9SWilly Tu         return ::ipmi::responseInvalidCommand();
636c71b0f9SWilly Tu     }
646c71b0f9SWilly Tu 
656c71b0f9SWilly Tu     std::vector<std::uint8_t> reply;
666c71b0f9SWilly Tu     reply.reserve(bifurcation.size() + sizeof(struct PcieBifurcationReply));
676c71b0f9SWilly Tu     reply.emplace_back(bifurcation.size()); /* bifurcationLength */
686c71b0f9SWilly Tu     reply.insert(reply.end(), bifurcation.begin(),
696c71b0f9SWilly Tu                  bifurcation.end());        /* bifurcation */
706c71b0f9SWilly Tu 
716c71b0f9SWilly Tu     return ::ipmi::responseSuccess(SysOEMCommands::SysPCIeSlotBifurcation,
726c71b0f9SWilly Tu                                    reply);
736c71b0f9SWilly Tu }
746c71b0f9SWilly Tu } // namespace ipmi
756c71b0f9SWilly Tu } // namespace google
76