1*7691cc2fSChicago Duan #pragma once 2*7691cc2fSChicago Duan 3*7691cc2fSChicago Duan #include "error_messages.hpp" 4*7691cc2fSChicago Duan #include "utility.hpp" 5*7691cc2fSChicago Duan 6*7691cc2fSChicago Duan #include <app.hpp> 7*7691cc2fSChicago Duan #include <pcie.hpp> 8*7691cc2fSChicago Duan #include <registries/privilege_registry.hpp> 9*7691cc2fSChicago Duan #include <utils/json_utils.hpp> 10*7691cc2fSChicago Duan 11*7691cc2fSChicago Duan namespace redfish 12*7691cc2fSChicago Duan { 13*7691cc2fSChicago Duan 14*7691cc2fSChicago Duan inline std::string dbusSlotTypeToRf(const std::string& slotType) 15*7691cc2fSChicago Duan { 16*7691cc2fSChicago Duan if (slotType == 17*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.FullLength") 18*7691cc2fSChicago Duan { 19*7691cc2fSChicago Duan return "FullLength"; 20*7691cc2fSChicago Duan } 21*7691cc2fSChicago Duan if (slotType == 22*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.HalfLength") 23*7691cc2fSChicago Duan { 24*7691cc2fSChicago Duan return "HalfLength"; 25*7691cc2fSChicago Duan } 26*7691cc2fSChicago Duan if (slotType == 27*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.LowProfile") 28*7691cc2fSChicago Duan { 29*7691cc2fSChicago Duan return "LowProfile"; 30*7691cc2fSChicago Duan } 31*7691cc2fSChicago Duan if (slotType == 32*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Mini") 33*7691cc2fSChicago Duan { 34*7691cc2fSChicago Duan return "Mini"; 35*7691cc2fSChicago Duan } 36*7691cc2fSChicago Duan if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.M_2") 37*7691cc2fSChicago Duan { 38*7691cc2fSChicago Duan return "M2"; 39*7691cc2fSChicago Duan } 40*7691cc2fSChicago Duan if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OEM") 41*7691cc2fSChicago Duan { 42*7691cc2fSChicago Duan return "OEM"; 43*7691cc2fSChicago Duan } 44*7691cc2fSChicago Duan if (slotType == 45*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Small") 46*7691cc2fSChicago Duan { 47*7691cc2fSChicago Duan return "OCP3Small"; 48*7691cc2fSChicago Duan } 49*7691cc2fSChicago Duan if (slotType == 50*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Large") 51*7691cc2fSChicago Duan { 52*7691cc2fSChicago Duan return "OCP3Large"; 53*7691cc2fSChicago Duan } 54*7691cc2fSChicago Duan if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.U_2") 55*7691cc2fSChicago Duan { 56*7691cc2fSChicago Duan return "U2"; 57*7691cc2fSChicago Duan } 58*7691cc2fSChicago Duan 59*7691cc2fSChicago Duan // Unknown or others 60*7691cc2fSChicago Duan return ""; 61*7691cc2fSChicago Duan } 62*7691cc2fSChicago Duan 63*7691cc2fSChicago Duan inline void 64*7691cc2fSChicago Duan onPcieSlotGetAllDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 65*7691cc2fSChicago Duan const boost::system::error_code ec, 66*7691cc2fSChicago Duan const dbus::utility::DBusPropertiesMap& propertiesList) 67*7691cc2fSChicago Duan { 68*7691cc2fSChicago Duan if (ec) 69*7691cc2fSChicago Duan { 70*7691cc2fSChicago Duan BMCWEB_LOG_ERROR << "Can't get PCIeSlot properties!"; 71*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 72*7691cc2fSChicago Duan return; 73*7691cc2fSChicago Duan } 74*7691cc2fSChicago Duan 75*7691cc2fSChicago Duan nlohmann::json& slots = asyncResp->res.jsonValue["Slots"]; 76*7691cc2fSChicago Duan 77*7691cc2fSChicago Duan nlohmann::json::array_t* slotsPtr = 78*7691cc2fSChicago Duan slots.get_ptr<nlohmann::json::array_t*>(); 79*7691cc2fSChicago Duan if (slotsPtr == nullptr) 80*7691cc2fSChicago Duan { 81*7691cc2fSChicago Duan BMCWEB_LOG_ERROR << "Slots key isn't an array???"; 82*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 83*7691cc2fSChicago Duan return; 84*7691cc2fSChicago Duan } 85*7691cc2fSChicago Duan 86*7691cc2fSChicago Duan nlohmann::json::object_t slot; 87*7691cc2fSChicago Duan 88*7691cc2fSChicago Duan for (const auto& property : propertiesList) 89*7691cc2fSChicago Duan { 90*7691cc2fSChicago Duan const std::string& propertyName = property.first; 91*7691cc2fSChicago Duan 92*7691cc2fSChicago Duan if (propertyName == "Generation") 93*7691cc2fSChicago Duan { 94*7691cc2fSChicago Duan const std::string* value = 95*7691cc2fSChicago Duan std::get_if<std::string>(&property.second); 96*7691cc2fSChicago Duan if (value == nullptr) 97*7691cc2fSChicago Duan { 98*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 99*7691cc2fSChicago Duan return; 100*7691cc2fSChicago Duan } 101*7691cc2fSChicago Duan std::optional<std::string> pcieType = 102*7691cc2fSChicago Duan redfishPcieGenerationFromDbus(*value); 103*7691cc2fSChicago Duan if (!pcieType) 104*7691cc2fSChicago Duan { 105*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 106*7691cc2fSChicago Duan return; 107*7691cc2fSChicago Duan } 108*7691cc2fSChicago Duan slot["PCIeType"] = !pcieType; 109*7691cc2fSChicago Duan } 110*7691cc2fSChicago Duan else if (propertyName == "Lanes") 111*7691cc2fSChicago Duan { 112*7691cc2fSChicago Duan const size_t* value = std::get_if<size_t>(&property.second); 113*7691cc2fSChicago Duan if (value == nullptr) 114*7691cc2fSChicago Duan { 115*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 116*7691cc2fSChicago Duan return; 117*7691cc2fSChicago Duan } 118*7691cc2fSChicago Duan slot["Lanes"] = *value; 119*7691cc2fSChicago Duan } 120*7691cc2fSChicago Duan else if (propertyName == "SlotType") 121*7691cc2fSChicago Duan { 122*7691cc2fSChicago Duan const std::string* value = 123*7691cc2fSChicago Duan std::get_if<std::string>(&property.second); 124*7691cc2fSChicago Duan if (value == nullptr) 125*7691cc2fSChicago Duan { 126*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 127*7691cc2fSChicago Duan return; 128*7691cc2fSChicago Duan } 129*7691cc2fSChicago Duan std::string slotType = dbusSlotTypeToRf(*value); 130*7691cc2fSChicago Duan if (!slotType.empty()) 131*7691cc2fSChicago Duan { 132*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 133*7691cc2fSChicago Duan return; 134*7691cc2fSChicago Duan } 135*7691cc2fSChicago Duan slot["SlotType"] = slotType; 136*7691cc2fSChicago Duan } 137*7691cc2fSChicago Duan else if (propertyName == "HotPluggable") 138*7691cc2fSChicago Duan { 139*7691cc2fSChicago Duan const bool* value = std::get_if<bool>(&property.second); 140*7691cc2fSChicago Duan if (value == nullptr) 141*7691cc2fSChicago Duan { 142*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 143*7691cc2fSChicago Duan return; 144*7691cc2fSChicago Duan } 145*7691cc2fSChicago Duan slot["HotPluggable"] = *value; 146*7691cc2fSChicago Duan } 147*7691cc2fSChicago Duan } 148*7691cc2fSChicago Duan slots.emplace_back(std::move(slot)); 149*7691cc2fSChicago Duan } 150*7691cc2fSChicago Duan 151*7691cc2fSChicago Duan inline void onMapperAssociationDone( 152*7691cc2fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 153*7691cc2fSChicago Duan const std::string& chassisID, const std::string& pcieSlotPath, 154*7691cc2fSChicago Duan const std::string& connectionName, const boost::system::error_code ec, 155*7691cc2fSChicago Duan const std::variant<std::vector<std::string>>& endpoints) 156*7691cc2fSChicago Duan { 157*7691cc2fSChicago Duan if (ec) 158*7691cc2fSChicago Duan { 159*7691cc2fSChicago Duan if (ec.value() == EBADR) 160*7691cc2fSChicago Duan { 161*7691cc2fSChicago Duan // This PCIeSlot have no chassis association. 162*7691cc2fSChicago Duan return; 163*7691cc2fSChicago Duan } 164*7691cc2fSChicago Duan BMCWEB_LOG_ERROR << "DBUS response error"; 165*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 166*7691cc2fSChicago Duan return; 167*7691cc2fSChicago Duan } 168*7691cc2fSChicago Duan 169*7691cc2fSChicago Duan const std::vector<std::string>* pcieSlotChassis = 170*7691cc2fSChicago Duan std::get_if<std::vector<std::string>>(&(endpoints)); 171*7691cc2fSChicago Duan 172*7691cc2fSChicago Duan if (pcieSlotChassis == nullptr) 173*7691cc2fSChicago Duan { 174*7691cc2fSChicago Duan BMCWEB_LOG_ERROR << "Error getting PCIe Slot association!"; 175*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 176*7691cc2fSChicago Duan return; 177*7691cc2fSChicago Duan } 178*7691cc2fSChicago Duan 179*7691cc2fSChicago Duan if (pcieSlotChassis->size() != 1) 180*7691cc2fSChicago Duan { 181*7691cc2fSChicago Duan BMCWEB_LOG_ERROR << "PCIe Slot association error! "; 182*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 183*7691cc2fSChicago Duan return; 184*7691cc2fSChicago Duan } 185*7691cc2fSChicago Duan 186*7691cc2fSChicago Duan sdbusplus::message::object_path path((*pcieSlotChassis)[0]); 187*7691cc2fSChicago Duan std::string chassisName = path.filename(); 188*7691cc2fSChicago Duan if (chassisName != chassisID) 189*7691cc2fSChicago Duan { 190*7691cc2fSChicago Duan // The pcie slot doesn't belong to the chassisID 191*7691cc2fSChicago Duan return; 192*7691cc2fSChicago Duan } 193*7691cc2fSChicago Duan 194*7691cc2fSChicago Duan crow::connections::systemBus->async_method_call( 195*7691cc2fSChicago Duan [asyncResp](const boost::system::error_code ec, 196*7691cc2fSChicago Duan const dbus::utility::DBusPropertiesMap& propertiesList) { 197*7691cc2fSChicago Duan onPcieSlotGetAllDone(asyncResp, ec, propertiesList); 198*7691cc2fSChicago Duan }, 199*7691cc2fSChicago Duan connectionName, pcieSlotPath, "org.freedesktop.DBus.Properties", 200*7691cc2fSChicago Duan "GetAll", "xyz.openbmc_project.Inventory.Item.PCIeSlot"); 201*7691cc2fSChicago Duan } 202*7691cc2fSChicago Duan 203*7691cc2fSChicago Duan inline void 204*7691cc2fSChicago Duan onMapperSubtreeDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 205*7691cc2fSChicago Duan const std::string& chassisID, 206*7691cc2fSChicago Duan const boost::system::error_code ec, 207*7691cc2fSChicago Duan const dbus::utility::MapperGetSubTreeResponse& subtree) 208*7691cc2fSChicago Duan { 209*7691cc2fSChicago Duan if (ec) 210*7691cc2fSChicago Duan { 211*7691cc2fSChicago Duan BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec; 212*7691cc2fSChicago Duan messages::internalError(asyncResp->res); 213*7691cc2fSChicago Duan return; 214*7691cc2fSChicago Duan } 215*7691cc2fSChicago Duan if (subtree.empty()) 216*7691cc2fSChicago Duan { 217*7691cc2fSChicago Duan messages::resourceNotFound(asyncResp->res, "#Chassis", chassisID); 218*7691cc2fSChicago Duan return; 219*7691cc2fSChicago Duan } 220*7691cc2fSChicago Duan 221*7691cc2fSChicago Duan BMCWEB_LOG_DEBUG << "Get properties for PCIeSlots associated to chassis = " 222*7691cc2fSChicago Duan << chassisID; 223*7691cc2fSChicago Duan 224*7691cc2fSChicago Duan asyncResp->res.jsonValue["@odata.type"] = "#PCIeSlots.v1_4_1.PCIeSlots"; 225*7691cc2fSChicago Duan asyncResp->res.jsonValue["Name"] = "PCIe Slot Information"; 226*7691cc2fSChicago Duan asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 227*7691cc2fSChicago Duan "redfish", "v1", "Chassis", chassisID, "PCIeSlots"); 228*7691cc2fSChicago Duan asyncResp->res.jsonValue["Id"] = "1"; 229*7691cc2fSChicago Duan asyncResp->res.jsonValue["Slots"] = nlohmann::json::array(); 230*7691cc2fSChicago Duan 231*7691cc2fSChicago Duan for (const auto& pathServicePair : subtree) 232*7691cc2fSChicago Duan { 233*7691cc2fSChicago Duan const std::string& pcieSlotPath = pathServicePair.first; 234*7691cc2fSChicago Duan for (const auto& connectionInterfacePair : pathServicePair.second) 235*7691cc2fSChicago Duan { 236*7691cc2fSChicago Duan const std::string& connectionName = connectionInterfacePair.first; 237*7691cc2fSChicago Duan sdbusplus::message::object_path pcieSlotAssociationPath( 238*7691cc2fSChicago Duan pcieSlotPath); 239*7691cc2fSChicago Duan pcieSlotAssociationPath /= "chassis"; 240*7691cc2fSChicago Duan 241*7691cc2fSChicago Duan // The association of this PCIeSlot is used to determine whether 242*7691cc2fSChicago Duan // it belongs to this ChassisID 243*7691cc2fSChicago Duan crow::connections::systemBus->async_method_call( 244*7691cc2fSChicago Duan [asyncResp, chassisID, pcieSlotPath, connectionName]( 245*7691cc2fSChicago Duan const boost::system::error_code ec, 246*7691cc2fSChicago Duan const std::variant<std::vector<std::string>>& endpoints) { 247*7691cc2fSChicago Duan onMapperAssociationDone(asyncResp, chassisID, pcieSlotPath, 248*7691cc2fSChicago Duan connectionName, ec, endpoints); 249*7691cc2fSChicago Duan }, 250*7691cc2fSChicago Duan "xyz.openbmc_project.ObjectMapper", 251*7691cc2fSChicago Duan std::string{pcieSlotAssociationPath}, 252*7691cc2fSChicago Duan "org.freedesktop.DBus.Properties", "Get", 253*7691cc2fSChicago Duan "xyz.openbmc_project.Association", "endpoints"); 254*7691cc2fSChicago Duan } 255*7691cc2fSChicago Duan } 256*7691cc2fSChicago Duan } 257*7691cc2fSChicago Duan 258*7691cc2fSChicago Duan inline void handlePCIeSlotCollectionGet( 259*7691cc2fSChicago Duan crow::App& app, const crow::Request& req, 260*7691cc2fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 261*7691cc2fSChicago Duan const std::string& chassisID) 262*7691cc2fSChicago Duan { 263*7691cc2fSChicago Duan if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 264*7691cc2fSChicago Duan { 265*7691cc2fSChicago Duan return; 266*7691cc2fSChicago Duan } 267*7691cc2fSChicago Duan 268*7691cc2fSChicago Duan crow::connections::systemBus->async_method_call( 269*7691cc2fSChicago Duan [asyncResp, 270*7691cc2fSChicago Duan chassisID](const boost::system::error_code ec, 271*7691cc2fSChicago Duan const dbus::utility::MapperGetSubTreeResponse& subtree) { 272*7691cc2fSChicago Duan onMapperSubtreeDone(asyncResp, chassisID, ec, subtree); 273*7691cc2fSChicago Duan }, 274*7691cc2fSChicago Duan "xyz.openbmc_project.ObjectMapper", 275*7691cc2fSChicago Duan "/xyz/openbmc_project/object_mapper", 276*7691cc2fSChicago Duan "xyz.openbmc_project.ObjectMapper", "GetSubTree", 277*7691cc2fSChicago Duan "/xyz/openbmc_project/inventory", int32_t(0), 278*7691cc2fSChicago Duan std::array<const char*, 1>{ 279*7691cc2fSChicago Duan "xyz.openbmc_project.Inventory.Item.PCIeSlot"}); 280*7691cc2fSChicago Duan } 281*7691cc2fSChicago Duan 282*7691cc2fSChicago Duan inline void requestRoutesPCIeSlots(App& app) 283*7691cc2fSChicago Duan { 284*7691cc2fSChicago Duan BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PCIeSlots/") 285*7691cc2fSChicago Duan .privileges(redfish::privileges::getPCIeSlots) 286*7691cc2fSChicago Duan .methods(boost::beast::http::verb::get)( 287*7691cc2fSChicago Duan std::bind_front(handlePCIeSlotCollectionGet, std::ref(app))); 288*7691cc2fSChicago Duan } 289*7691cc2fSChicago Duan 290*7691cc2fSChicago Duan } // namespace redfish 291