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