17691cc2fSChicago Duan #pragma once 27691cc2fSChicago Duan 37691cc2fSChicago Duan #include "error_messages.hpp" 4*0ec8b83dSEd Tanous #include "generated/enums/pcie_slot.hpp" 57691cc2fSChicago Duan #include "utility.hpp" 67691cc2fSChicago Duan 77691cc2fSChicago Duan #include <app.hpp> 87691cc2fSChicago Duan #include <pcie.hpp> 97691cc2fSChicago Duan #include <registries/privilege_registry.hpp> 10d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 11d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 12d1bde9e5SKrzysztof Grobelny #include <utils/dbus_utils.hpp> 137691cc2fSChicago Duan #include <utils/json_utils.hpp> 147691cc2fSChicago Duan 157691cc2fSChicago Duan namespace redfish 167691cc2fSChicago Duan { 177691cc2fSChicago Duan 18*0ec8b83dSEd Tanous inline pcie_slot::SlotTypes dbusSlotTypeToRf(const std::string& slotType) 197691cc2fSChicago Duan { 207691cc2fSChicago Duan if (slotType == 217691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.FullLength") 227691cc2fSChicago Duan { 23*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::FullLength; 247691cc2fSChicago Duan } 257691cc2fSChicago Duan if (slotType == 267691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.HalfLength") 277691cc2fSChicago Duan { 28*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::HalfLength; 297691cc2fSChicago Duan } 307691cc2fSChicago Duan if (slotType == 317691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.LowProfile") 327691cc2fSChicago Duan { 33*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::LowProfile; 347691cc2fSChicago Duan } 357691cc2fSChicago Duan if (slotType == 367691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Mini") 377691cc2fSChicago Duan { 38*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::Mini; 397691cc2fSChicago Duan } 407691cc2fSChicago Duan if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.M_2") 417691cc2fSChicago Duan { 42*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::M2; 437691cc2fSChicago Duan } 447691cc2fSChicago Duan if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OEM") 457691cc2fSChicago Duan { 46*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::OEM; 477691cc2fSChicago Duan } 487691cc2fSChicago Duan if (slotType == 497691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Small") 507691cc2fSChicago Duan { 51*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::OCP3Small; 527691cc2fSChicago Duan } 537691cc2fSChicago Duan if (slotType == 547691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Large") 557691cc2fSChicago Duan { 56*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::OCP3Large; 577691cc2fSChicago Duan } 587691cc2fSChicago Duan if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.U_2") 597691cc2fSChicago Duan { 60*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::U2; 617691cc2fSChicago Duan } 627691cc2fSChicago Duan 637691cc2fSChicago Duan // Unknown or others 64*0ec8b83dSEd Tanous return pcie_slot::SlotTypes::Invalid; 657691cc2fSChicago Duan } 667691cc2fSChicago Duan 677691cc2fSChicago Duan inline void 687691cc2fSChicago Duan onPcieSlotGetAllDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 697691cc2fSChicago Duan const boost::system::error_code ec, 707691cc2fSChicago Duan const dbus::utility::DBusPropertiesMap& propertiesList) 717691cc2fSChicago Duan { 727691cc2fSChicago Duan if (ec) 737691cc2fSChicago Duan { 747691cc2fSChicago Duan BMCWEB_LOG_ERROR << "Can't get PCIeSlot properties!"; 757691cc2fSChicago Duan messages::internalError(asyncResp->res); 767691cc2fSChicago Duan return; 777691cc2fSChicago Duan } 787691cc2fSChicago Duan 797691cc2fSChicago Duan nlohmann::json& slots = asyncResp->res.jsonValue["Slots"]; 807691cc2fSChicago Duan 817691cc2fSChicago Duan nlohmann::json::array_t* slotsPtr = 827691cc2fSChicago Duan slots.get_ptr<nlohmann::json::array_t*>(); 837691cc2fSChicago Duan if (slotsPtr == nullptr) 847691cc2fSChicago Duan { 857691cc2fSChicago Duan BMCWEB_LOG_ERROR << "Slots key isn't an array???"; 867691cc2fSChicago Duan messages::internalError(asyncResp->res); 877691cc2fSChicago Duan return; 887691cc2fSChicago Duan } 897691cc2fSChicago Duan 907691cc2fSChicago Duan nlohmann::json::object_t slot; 917691cc2fSChicago Duan 92d1bde9e5SKrzysztof Grobelny const std::string* generation = nullptr; 93d1bde9e5SKrzysztof Grobelny const size_t* lanes = nullptr; 94d1bde9e5SKrzysztof Grobelny const std::string* slotType = nullptr; 95d1bde9e5SKrzysztof Grobelny const bool* hotPluggable = nullptr; 967691cc2fSChicago Duan 97d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 98d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), propertiesList, "Generation", 99d1bde9e5SKrzysztof Grobelny generation, "Lanes", lanes, "SlotType", slotType, "HotPluggable", 100d1bde9e5SKrzysztof Grobelny hotPluggable); 101d1bde9e5SKrzysztof Grobelny 102d1bde9e5SKrzysztof Grobelny if (!success) 1037691cc2fSChicago Duan { 1047691cc2fSChicago Duan messages::internalError(asyncResp->res); 1057691cc2fSChicago Duan return; 1067691cc2fSChicago Duan } 107d1bde9e5SKrzysztof Grobelny 108d1bde9e5SKrzysztof Grobelny if (generation != nullptr) 109d1bde9e5SKrzysztof Grobelny { 110*0ec8b83dSEd Tanous std::optional<pcie_device::PCIeTypes> pcieType = 111d1bde9e5SKrzysztof Grobelny redfishPcieGenerationFromDbus(*generation); 1127691cc2fSChicago Duan if (!pcieType) 1137691cc2fSChicago Duan { 1147691cc2fSChicago Duan messages::internalError(asyncResp->res); 1157691cc2fSChicago Duan return; 1167691cc2fSChicago Duan } 1177691cc2fSChicago Duan slot["PCIeType"] = !pcieType; 1187691cc2fSChicago Duan } 119d1bde9e5SKrzysztof Grobelny 120d1bde9e5SKrzysztof Grobelny if (lanes != nullptr) 1217691cc2fSChicago Duan { 122d1bde9e5SKrzysztof Grobelny 123d1bde9e5SKrzysztof Grobelny slot["Lanes"] = *lanes; 1247691cc2fSChicago Duan } 125d1bde9e5SKrzysztof Grobelny 126d1bde9e5SKrzysztof Grobelny if (slotType != nullptr) 1277691cc2fSChicago Duan { 128d1bde9e5SKrzysztof Grobelny std::string redfishSlotType = dbusSlotTypeToRf(*slotType); 1297691cc2fSChicago Duan if (!slotType.empty()) 1307691cc2fSChicago Duan { 1317691cc2fSChicago Duan messages::internalError(asyncResp->res); 1327691cc2fSChicago Duan return; 1337691cc2fSChicago Duan } 134d1bde9e5SKrzysztof Grobelny slot["SlotType"] = redfishSlotType; 1357691cc2fSChicago Duan } 136d1bde9e5SKrzysztof Grobelny 137d1bde9e5SKrzysztof Grobelny if (hotPluggable != nullptr) 1387691cc2fSChicago Duan { 139d1bde9e5SKrzysztof Grobelny slot["HotPluggable"] = *hotPluggable; 1407691cc2fSChicago Duan } 141d1bde9e5SKrzysztof Grobelny 1427691cc2fSChicago Duan slots.emplace_back(std::move(slot)); 1437691cc2fSChicago Duan } 1447691cc2fSChicago Duan 1457691cc2fSChicago Duan inline void onMapperAssociationDone( 1467691cc2fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1477691cc2fSChicago Duan const std::string& chassisID, const std::string& pcieSlotPath, 1487691cc2fSChicago Duan const std::string& connectionName, const boost::system::error_code ec, 1497691cc2fSChicago Duan const std::variant<std::vector<std::string>>& endpoints) 1507691cc2fSChicago Duan { 1517691cc2fSChicago Duan if (ec) 1527691cc2fSChicago Duan { 1537691cc2fSChicago Duan if (ec.value() == EBADR) 1547691cc2fSChicago Duan { 1557691cc2fSChicago Duan // This PCIeSlot have no chassis association. 1567691cc2fSChicago Duan return; 1577691cc2fSChicago Duan } 1587691cc2fSChicago Duan BMCWEB_LOG_ERROR << "DBUS response error"; 1597691cc2fSChicago Duan messages::internalError(asyncResp->res); 1607691cc2fSChicago Duan return; 1617691cc2fSChicago Duan } 1627691cc2fSChicago Duan 1637691cc2fSChicago Duan const std::vector<std::string>* pcieSlotChassis = 1647691cc2fSChicago Duan std::get_if<std::vector<std::string>>(&(endpoints)); 1657691cc2fSChicago Duan 1667691cc2fSChicago Duan if (pcieSlotChassis == nullptr) 1677691cc2fSChicago Duan { 1687691cc2fSChicago Duan BMCWEB_LOG_ERROR << "Error getting PCIe Slot association!"; 1697691cc2fSChicago Duan messages::internalError(asyncResp->res); 1707691cc2fSChicago Duan return; 1717691cc2fSChicago Duan } 1727691cc2fSChicago Duan 1737691cc2fSChicago Duan if (pcieSlotChassis->size() != 1) 1747691cc2fSChicago Duan { 1757691cc2fSChicago Duan BMCWEB_LOG_ERROR << "PCIe Slot association error! "; 1767691cc2fSChicago Duan messages::internalError(asyncResp->res); 1777691cc2fSChicago Duan return; 1787691cc2fSChicago Duan } 1797691cc2fSChicago Duan 1807691cc2fSChicago Duan sdbusplus::message::object_path path((*pcieSlotChassis)[0]); 1817691cc2fSChicago Duan std::string chassisName = path.filename(); 1827691cc2fSChicago Duan if (chassisName != chassisID) 1837691cc2fSChicago Duan { 1847691cc2fSChicago Duan // The pcie slot doesn't belong to the chassisID 1857691cc2fSChicago Duan return; 1867691cc2fSChicago Duan } 1877691cc2fSChicago Duan 188d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 189d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, connectionName, pcieSlotPath, 190d1bde9e5SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.PCIeSlot", 1917691cc2fSChicago Duan [asyncResp](const boost::system::error_code ec, 1927691cc2fSChicago Duan const dbus::utility::DBusPropertiesMap& propertiesList) { 1937691cc2fSChicago Duan onPcieSlotGetAllDone(asyncResp, ec, propertiesList); 194d1bde9e5SKrzysztof Grobelny }); 1957691cc2fSChicago Duan } 1967691cc2fSChicago Duan 1977691cc2fSChicago Duan inline void 1987691cc2fSChicago Duan onMapperSubtreeDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1997691cc2fSChicago Duan const std::string& chassisID, 2007691cc2fSChicago Duan const boost::system::error_code ec, 2017691cc2fSChicago Duan const dbus::utility::MapperGetSubTreeResponse& subtree) 2027691cc2fSChicago Duan { 2037691cc2fSChicago Duan if (ec) 2047691cc2fSChicago Duan { 2057691cc2fSChicago Duan BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec; 2067691cc2fSChicago Duan messages::internalError(asyncResp->res); 2077691cc2fSChicago Duan return; 2087691cc2fSChicago Duan } 2097691cc2fSChicago Duan if (subtree.empty()) 2107691cc2fSChicago Duan { 211d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisID); 2127691cc2fSChicago Duan return; 2137691cc2fSChicago Duan } 2147691cc2fSChicago Duan 2157691cc2fSChicago Duan BMCWEB_LOG_DEBUG << "Get properties for PCIeSlots associated to chassis = " 2167691cc2fSChicago Duan << chassisID; 2177691cc2fSChicago Duan 2187691cc2fSChicago Duan asyncResp->res.jsonValue["@odata.type"] = "#PCIeSlots.v1_4_1.PCIeSlots"; 2197691cc2fSChicago Duan asyncResp->res.jsonValue["Name"] = "PCIe Slot Information"; 2207691cc2fSChicago Duan asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 2217691cc2fSChicago Duan "redfish", "v1", "Chassis", chassisID, "PCIeSlots"); 2227691cc2fSChicago Duan asyncResp->res.jsonValue["Id"] = "1"; 2237691cc2fSChicago Duan asyncResp->res.jsonValue["Slots"] = nlohmann::json::array(); 2247691cc2fSChicago Duan 2257691cc2fSChicago Duan for (const auto& pathServicePair : subtree) 2267691cc2fSChicago Duan { 2277691cc2fSChicago Duan const std::string& pcieSlotPath = pathServicePair.first; 2287691cc2fSChicago Duan for (const auto& connectionInterfacePair : pathServicePair.second) 2297691cc2fSChicago Duan { 2307691cc2fSChicago Duan const std::string& connectionName = connectionInterfacePair.first; 2317691cc2fSChicago Duan sdbusplus::message::object_path pcieSlotAssociationPath( 2327691cc2fSChicago Duan pcieSlotPath); 2337691cc2fSChicago Duan pcieSlotAssociationPath /= "chassis"; 2347691cc2fSChicago Duan 2357691cc2fSChicago Duan // The association of this PCIeSlot is used to determine whether 2367691cc2fSChicago Duan // it belongs to this ChassisID 2377691cc2fSChicago Duan crow::connections::systemBus->async_method_call( 2387691cc2fSChicago Duan [asyncResp, chassisID, pcieSlotPath, connectionName]( 2397691cc2fSChicago Duan const boost::system::error_code ec, 2407691cc2fSChicago Duan const std::variant<std::vector<std::string>>& endpoints) { 2417691cc2fSChicago Duan onMapperAssociationDone(asyncResp, chassisID, pcieSlotPath, 2427691cc2fSChicago Duan connectionName, ec, endpoints); 2437691cc2fSChicago Duan }, 2447691cc2fSChicago Duan "xyz.openbmc_project.ObjectMapper", 2457691cc2fSChicago Duan std::string{pcieSlotAssociationPath}, 2467691cc2fSChicago Duan "org.freedesktop.DBus.Properties", "Get", 2477691cc2fSChicago Duan "xyz.openbmc_project.Association", "endpoints"); 2487691cc2fSChicago Duan } 2497691cc2fSChicago Duan } 2507691cc2fSChicago Duan } 2517691cc2fSChicago Duan 2527691cc2fSChicago Duan inline void handlePCIeSlotCollectionGet( 2537691cc2fSChicago Duan crow::App& app, const crow::Request& req, 2547691cc2fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2557691cc2fSChicago Duan const std::string& chassisID) 2567691cc2fSChicago Duan { 2572aacf856SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2587691cc2fSChicago Duan { 2597691cc2fSChicago Duan return; 2607691cc2fSChicago Duan } 2617691cc2fSChicago Duan 2627691cc2fSChicago Duan crow::connections::systemBus->async_method_call( 2637691cc2fSChicago Duan [asyncResp, 2647691cc2fSChicago Duan chassisID](const boost::system::error_code ec, 2657691cc2fSChicago Duan const dbus::utility::MapperGetSubTreeResponse& subtree) { 2667691cc2fSChicago Duan onMapperSubtreeDone(asyncResp, chassisID, ec, subtree); 2677691cc2fSChicago Duan }, 2687691cc2fSChicago Duan "xyz.openbmc_project.ObjectMapper", 2697691cc2fSChicago Duan "/xyz/openbmc_project/object_mapper", 2707691cc2fSChicago Duan "xyz.openbmc_project.ObjectMapper", "GetSubTree", 2717691cc2fSChicago Duan "/xyz/openbmc_project/inventory", int32_t(0), 2727691cc2fSChicago Duan std::array<const char*, 1>{ 2737691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot"}); 2747691cc2fSChicago Duan } 2757691cc2fSChicago Duan 2767691cc2fSChicago Duan inline void requestRoutesPCIeSlots(App& app) 2777691cc2fSChicago Duan { 2787691cc2fSChicago Duan BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PCIeSlots/") 2797691cc2fSChicago Duan .privileges(redfish::privileges::getPCIeSlots) 2807691cc2fSChicago Duan .methods(boost::beast::http::verb::get)( 2817691cc2fSChicago Duan std::bind_front(handlePCIeSlotCollectionGet, std::ref(app))); 2827691cc2fSChicago Duan } 2837691cc2fSChicago Duan 2847691cc2fSChicago Duan } // namespace redfish 285