blob: 51a5e6921dd4e23ecadab0ec7a15be0ca261d3e6 [file] [log] [blame]
Chicago Duan7691cc22021-01-25 19:52:35 +08001#pragma once
2
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "app.hpp"
George Liue99073f2022-12-09 11:06:16 +08004#include "dbus_utility.hpp"
Chicago Duan7691cc22021-01-25 19:52:35 +08005#include "error_messages.hpp"
Ed Tanous4ce2c1b2023-02-10 11:57:54 -08006#include "generated/enums/pcie_slots.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08007#include "pcie.hpp"
8#include "registries/privilege_registry.hpp"
Chicago Duan7691cc22021-01-25 19:52:35 +08009#include "utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080010#include "utils/dbus_utils.hpp"
11#include "utils/json_utils.hpp"
Chicago Duan7691cc22021-01-25 19:52:35 +080012
George Liue99073f2022-12-09 11:06:16 +080013#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070014#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020015#include <sdbusplus/asio/property.hpp>
16#include <sdbusplus/unpack_properties.hpp>
Chicago Duan7691cc22021-01-25 19:52:35 +080017
George Liue99073f2022-12-09 11:06:16 +080018#include <array>
19#include <string_view>
20
Chicago Duan7691cc22021-01-25 19:52:35 +080021namespace redfish
22{
23
Lakshmi Yadlapatid87fdd92023-05-02 16:50:31 -050024inline std::optional<pcie_slots::SlotTypes>
25 dbusSlotTypeToRf(const std::string& slotType)
Chicago Duan7691cc22021-01-25 19:52:35 +080026{
27 if (slotType ==
28 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.FullLength")
29 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080030 return pcie_slots::SlotTypes::FullLength;
Chicago Duan7691cc22021-01-25 19:52:35 +080031 }
32 if (slotType ==
33 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.HalfLength")
34 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080035 return pcie_slots::SlotTypes::HalfLength;
Chicago Duan7691cc22021-01-25 19:52:35 +080036 }
37 if (slotType ==
38 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.LowProfile")
39 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080040 return pcie_slots::SlotTypes::LowProfile;
Chicago Duan7691cc22021-01-25 19:52:35 +080041 }
42 if (slotType ==
43 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Mini")
44 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080045 return pcie_slots::SlotTypes::Mini;
Chicago Duan7691cc22021-01-25 19:52:35 +080046 }
47 if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.M_2")
48 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080049 return pcie_slots::SlotTypes::M2;
Chicago Duan7691cc22021-01-25 19:52:35 +080050 }
51 if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OEM")
52 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080053 return pcie_slots::SlotTypes::OEM;
Chicago Duan7691cc22021-01-25 19:52:35 +080054 }
55 if (slotType ==
56 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Small")
57 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080058 return pcie_slots::SlotTypes::OCP3Small;
Chicago Duan7691cc22021-01-25 19:52:35 +080059 }
60 if (slotType ==
61 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Large")
62 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080063 return pcie_slots::SlotTypes::OCP3Large;
Chicago Duan7691cc22021-01-25 19:52:35 +080064 }
65 if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.U_2")
66 {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -080067 return pcie_slots::SlotTypes::U2;
Chicago Duan7691cc22021-01-25 19:52:35 +080068 }
Lakshmi Yadlapatid87fdd92023-05-02 16:50:31 -050069 if (slotType ==
70 "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Unknown")
71 {
72 return pcie_slots::SlotTypes::Invalid;
73 }
Chicago Duan7691cc22021-01-25 19:52:35 +080074
Lakshmi Yadlapatid87fdd92023-05-02 16:50:31 -050075 // Unspecified slotType should return an internal error.
76 return std::nullopt;
Chicago Duan7691cc22021-01-25 19:52:35 +080077}
78
79inline void
80 onPcieSlotGetAllDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080081 const boost::system::error_code& ec,
Chicago Duan7691cc22021-01-25 19:52:35 +080082 const dbus::utility::DBusPropertiesMap& propertiesList)
83{
84 if (ec)
85 {
86 BMCWEB_LOG_ERROR << "Can't get PCIeSlot properties!";
87 messages::internalError(asyncResp->res);
88 return;
89 }
90
91 nlohmann::json& slots = asyncResp->res.jsonValue["Slots"];
92
93 nlohmann::json::array_t* slotsPtr =
94 slots.get_ptr<nlohmann::json::array_t*>();
95 if (slotsPtr == nullptr)
96 {
97 BMCWEB_LOG_ERROR << "Slots key isn't an array???";
98 messages::internalError(asyncResp->res);
99 return;
100 }
101
102 nlohmann::json::object_t slot;
103
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200104 const std::string* generation = nullptr;
105 const size_t* lanes = nullptr;
106 const std::string* slotType = nullptr;
107 const bool* hotPluggable = nullptr;
Chicago Duan7691cc22021-01-25 19:52:35 +0800108
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200109 const bool success = sdbusplus::unpackPropertiesNoThrow(
110 dbus_utils::UnpackErrorPrinter(), propertiesList, "Generation",
111 generation, "Lanes", lanes, "SlotType", slotType, "HotPluggable",
112 hotPluggable);
113
114 if (!success)
115 {
116 messages::internalError(asyncResp->res);
117 return;
Chicago Duan7691cc22021-01-25 19:52:35 +0800118 }
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200119
120 if (generation != nullptr)
121 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700122 std::optional<pcie_device::PCIeTypes> pcieType =
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200123 redfishPcieGenerationFromDbus(*generation);
124 if (!pcieType)
125 {
126 messages::internalError(asyncResp->res);
127 return;
128 }
Lakshmi Yadlapatibbf372a2023-05-02 15:09:08 -0500129 if (*pcieType != pcie_device::PCIeTypes::Invalid)
130 {
131 slot["PCIeType"] = *pcieType;
132 }
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200133 }
134
135 if (lanes != nullptr)
136 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200137 slot["Lanes"] = *lanes;
138 }
139
140 if (slotType != nullptr)
141 {
Lakshmi Yadlapatid87fdd92023-05-02 16:50:31 -0500142 std::optional<pcie_slots::SlotTypes> redfishSlotType =
143 dbusSlotTypeToRf(*slotType);
144 if (!redfishSlotType)
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200145 {
146 messages::internalError(asyncResp->res);
147 return;
148 }
Lakshmi Yadlapatid87fdd92023-05-02 16:50:31 -0500149 if (*redfishSlotType != pcie_slots::SlotTypes::Invalid)
150 {
151 slot["SlotType"] = *redfishSlotType;
152 }
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200153 }
154
155 if (hotPluggable != nullptr)
156 {
157 slot["HotPluggable"] = *hotPluggable;
158 }
159
Chicago Duan7691cc22021-01-25 19:52:35 +0800160 slots.emplace_back(std::move(slot));
161}
162
163inline void onMapperAssociationDone(
164 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
165 const std::string& chassisID, const std::string& pcieSlotPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800166 const std::string& connectionName, const boost::system::error_code& ec,
George Liu6c3e9452023-03-03 13:55:29 +0800167 const dbus::utility::MapperEndPoints& pcieSlotChassis)
Chicago Duan7691cc22021-01-25 19:52:35 +0800168{
169 if (ec)
170 {
171 if (ec.value() == EBADR)
172 {
173 // This PCIeSlot have no chassis association.
174 return;
175 }
176 BMCWEB_LOG_ERROR << "DBUS response error";
177 messages::internalError(asyncResp->res);
178 return;
179 }
180
George Liu6c3e9452023-03-03 13:55:29 +0800181 if (pcieSlotChassis.size() != 1)
Chicago Duan7691cc22021-01-25 19:52:35 +0800182 {
183 BMCWEB_LOG_ERROR << "PCIe Slot association error! ";
184 messages::internalError(asyncResp->res);
185 return;
186 }
187
George Liu6c3e9452023-03-03 13:55:29 +0800188 sdbusplus::message::object_path path(pcieSlotChassis[0]);
Chicago Duan7691cc22021-01-25 19:52:35 +0800189 std::string chassisName = path.filename();
190 if (chassisName != chassisID)
191 {
192 // The pcie slot doesn't belong to the chassisID
193 return;
194 }
195
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200196 sdbusplus::asio::getAllProperties(
197 *crow::connections::systemBus, connectionName, pcieSlotPath,
198 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800199 [asyncResp](const boost::system::error_code& ec2,
Chicago Duan7691cc22021-01-25 19:52:35 +0800200 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous4ce2c1b2023-02-10 11:57:54 -0800201 onPcieSlotGetAllDone(asyncResp, ec2, propertiesList);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200202 });
Chicago Duan7691cc22021-01-25 19:52:35 +0800203}
204
205inline void
206 onMapperSubtreeDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
207 const std::string& chassisID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800208 const boost::system::error_code& ec,
Chicago Duan7691cc22021-01-25 19:52:35 +0800209 const dbus::utility::MapperGetSubTreeResponse& subtree)
210{
211 if (ec)
212 {
213 BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec;
214 messages::internalError(asyncResp->res);
215 return;
216 }
217 if (subtree.empty())
218 {
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800219 messages::resourceNotFound(asyncResp->res, "Chassis", chassisID);
Chicago Duan7691cc22021-01-25 19:52:35 +0800220 return;
221 }
222
223 BMCWEB_LOG_DEBUG << "Get properties for PCIeSlots associated to chassis = "
224 << chassisID;
225
226 asyncResp->res.jsonValue["@odata.type"] = "#PCIeSlots.v1_4_1.PCIeSlots";
227 asyncResp->res.jsonValue["Name"] = "PCIe Slot Information";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700228 asyncResp->res.jsonValue["@odata.id"] =
229 boost::urls::format("/redfish/v1/Chassis/{}/PCIeSlots", chassisID);
Chicago Duan7691cc22021-01-25 19:52:35 +0800230 asyncResp->res.jsonValue["Id"] = "1";
231 asyncResp->res.jsonValue["Slots"] = nlohmann::json::array();
232
233 for (const auto& pathServicePair : subtree)
234 {
235 const std::string& pcieSlotPath = pathServicePair.first;
236 for (const auto& connectionInterfacePair : pathServicePair.second)
237 {
238 const std::string& connectionName = connectionInterfacePair.first;
239 sdbusplus::message::object_path pcieSlotAssociationPath(
240 pcieSlotPath);
241 pcieSlotAssociationPath /= "chassis";
242
243 // The association of this PCIeSlot is used to determine whether
244 // it belongs to this ChassisID
George Liu6c3e9452023-03-03 13:55:29 +0800245 dbus::utility::getAssociationEndPoints(
246 std::string{pcieSlotAssociationPath},
Chicago Duan7691cc22021-01-25 19:52:35 +0800247 [asyncResp, chassisID, pcieSlotPath, connectionName](
Ed Tanous4ce2c1b2023-02-10 11:57:54 -0800248 const boost::system::error_code& ec2,
George Liu6c3e9452023-03-03 13:55:29 +0800249 const dbus::utility::MapperEndPoints& endpoints) {
Chicago Duan7691cc22021-01-25 19:52:35 +0800250 onMapperAssociationDone(asyncResp, chassisID, pcieSlotPath,
Ed Tanous4ce2c1b2023-02-10 11:57:54 -0800251 connectionName, ec2, endpoints);
George Liu6c3e9452023-03-03 13:55:29 +0800252 });
Chicago Duan7691cc22021-01-25 19:52:35 +0800253 }
254 }
255}
256
257inline void handlePCIeSlotCollectionGet(
258 crow::App& app, const crow::Request& req,
259 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
260 const std::string& chassisID)
261{
Ed Tanous2aacf852022-06-17 08:07:54 -0700262 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Chicago Duan7691cc22021-01-25 19:52:35 +0800263 {
264 return;
265 }
266
George Liue99073f2022-12-09 11:06:16 +0800267 constexpr std::array<std::string_view, 1> interfaces = {
268 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
269 dbus::utility::getSubTree(
270 "/xyz/openbmc_project/inventory", 0, interfaces,
Chicago Duan7691cc22021-01-25 19:52:35 +0800271 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +0800272 chassisID](const boost::system::error_code& ec,
Chicago Duan7691cc22021-01-25 19:52:35 +0800273 const dbus::utility::MapperGetSubTreeResponse& subtree) {
274 onMapperSubtreeDone(asyncResp, chassisID, ec, subtree);
George Liue99073f2022-12-09 11:06:16 +0800275 });
Chicago Duan7691cc22021-01-25 19:52:35 +0800276}
277
278inline void requestRoutesPCIeSlots(App& app)
279{
280 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PCIeSlots/")
281 .privileges(redfish::privileges::getPCIeSlots)
282 .methods(boost::beast::http::verb::get)(
283 std::bind_front(handlePCIeSlotCollectionGet, std::ref(app)));
284}
285
286} // namespace redfish