blob: e2f35917b6aa0766ecacd5ccbd5ddd4f7b8e8760 [file] [log] [blame]
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#pragma once
18
19#include "node.hpp"
20
21#include <boost/system/linux_error.hpp>
22
23namespace redfish
24{
25
Gunnar Mills1214b7e2020-06-04 10:11:30 -050026static constexpr char const* pcieService = "xyz.openbmc_project.PCIe";
27static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe";
28static constexpr char const* pcieDeviceInterface =
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080029 "xyz.openbmc_project.PCIe.Device";
30
Jason M. Billsadbe1922019-10-14 15:44:35 -070031static inline void getPCIeDeviceList(std::shared_ptr<AsyncResp> asyncResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032 const std::string& name)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080033{
Jason M. Billsadbe1922019-10-14 15:44:35 -070034 auto getPCIeMapCallback = [asyncResp, name](
35 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050036 std::vector<std::string>& pcieDevicePaths) {
Jason M. Billsadbe1922019-10-14 15:44:35 -070037 if (ec)
38 {
39 BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
40 << ec.message();
41 // Not an error, system just doesn't have PCIe info
42 return;
43 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -050044 nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
Jason M. Billsadbe1922019-10-14 15:44:35 -070045 pcieDeviceList = nlohmann::json::array();
Gunnar Mills1214b7e2020-06-04 10:11:30 -050046 for (const std::string& pcieDevicePath : pcieDevicePaths)
Jason M. Billsadbe1922019-10-14 15:44:35 -070047 {
48 size_t devStart = pcieDevicePath.rfind("/");
49 if (devStart == std::string::npos)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080050 {
Jason M. Billsadbe1922019-10-14 15:44:35 -070051 continue;
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080052 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080053
Jason M. Billsadbe1922019-10-14 15:44:35 -070054 std::string devName = pcieDevicePath.substr(devStart + 1);
55 if (devName.empty())
56 {
57 continue;
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080058 }
Jason M. Billsadbe1922019-10-14 15:44:35 -070059 pcieDeviceList.push_back(
60 {{"@odata.id",
61 "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
62 }
63 asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
64 };
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080065 crow::connections::systemBus->async_method_call(
66 std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
67 "/xyz/openbmc_project/object_mapper",
68 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
69 std::string(pciePath) + "/", 1, std::array<std::string, 0>());
70}
71
Jason M. Billsadbe1922019-10-14 15:44:35 -070072class SystemPCIeDeviceCollection : public Node
73{
74 public:
Ed Tanous52cc1122020-07-18 13:51:21 -070075 SystemPCIeDeviceCollection(App& app) :
Jason M. Billsadbe1922019-10-14 15:44:35 -070076 Node(app, "/redfish/v1/Systems/system/PCIeDevices/")
77 {
78 entityPrivileges = {
79 {boost::beast::http::verb::get, {{"Login"}}},
80 {boost::beast::http::verb::head, {{"Login"}}},
81 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
82 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
83 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
84 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
85 }
86
87 private:
88 /**
89 * Functions triggers appropriate requests on DBus
90 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -050091 void doGet(crow::Response& res, const crow::Request& req,
92 const std::vector<std::string>& params) override
Jason M. Billsadbe1922019-10-14 15:44:35 -070093 {
94 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
95 asyncResp->res.jsonValue = {
96 {"@odata.type", "#PCIeDeviceCollection.PCIeDeviceCollection"},
Jason M. Billsadbe1922019-10-14 15:44:35 -070097 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
98 {"Name", "PCIe Device Collection"},
99 {"Description", "Collection of PCIe Devices"},
100 {"Members", nlohmann::json::array()},
101 {"Members@odata.count", 0}};
102 getPCIeDeviceList(asyncResp, "Members");
103 }
104};
105
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800106class SystemPCIeDevice : public Node
107{
108 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700109 SystemPCIeDevice(App& app) :
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800110 Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/",
111 std::string())
112 {
113 entityPrivileges = {
114 {boost::beast::http::verb::get, {{"Login"}}},
115 {boost::beast::http::verb::head, {{"Login"}}},
116 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
117 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
118 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
119 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
120 }
121
122 private:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500123 void doGet(crow::Response& res, const crow::Request& req,
124 const std::vector<std::string>& params) override
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800125 {
126 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
127 if (params.size() != 1)
128 {
129 messages::internalError(asyncResp->res);
130 return;
131 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500132 const std::string& device = params[0];
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800133
134 auto getPCIeDeviceCallback =
135 [asyncResp,
136 device](const boost::system::error_code ec,
Patrick Williams19bd78d2020-05-13 17:38:24 -0500137 boost::container::flat_map<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500138 std::variant<std::string>>&
139 pcieDevProperties) {
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800140 if (ec)
141 {
142 BMCWEB_LOG_DEBUG
143 << "failed to get PCIe Device properties ec: "
Ed Tanous271584a2019-07-09 16:24:22 -0700144 << ec.value() << ": " << ec.message();
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800145 if (ec.value() ==
146 boost::system::linux_error::bad_request_descriptor)
147 {
148 messages::resourceNotFound(asyncResp->res, "PCIeDevice",
149 device);
150 }
151 else
152 {
153 messages::internalError(asyncResp->res);
154 }
155 return;
156 }
157
158 asyncResp->res.jsonValue = {
Jason M. Billsdede6a92019-10-14 15:41:30 -0700159 {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800160 {"@odata.id",
161 "/redfish/v1/Systems/system/PCIeDevices/" + device},
162 {"Name", "PCIe Device"},
163 {"Id", device}};
164
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500165 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500166 &pcieDevProperties["Manufacturer"]);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800167 property)
168 {
169 asyncResp->res.jsonValue["Manufacturer"] = *property;
170 }
171
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500172 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500173 &pcieDevProperties["DeviceType"]);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800174 property)
175 {
176 asyncResp->res.jsonValue["DeviceType"] = *property;
177 }
178
Jason M. Billsdede6a92019-10-14 15:41:30 -0700179 asyncResp->res.jsonValue["PCIeFunctions"] = {
180 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
181 device + "/PCIeFunctions"}};
182 };
183 std::string escapedPath = std::string(pciePath) + "/" + device;
184 dbus::utility::escapePathForDbus(escapedPath);
185 crow::connections::systemBus->async_method_call(
186 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
187 "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
188 }
189};
190
191class SystemPCIeFunctionCollection : public Node
192{
193 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700194 SystemPCIeFunctionCollection(App& app) :
Jason M. Billsdede6a92019-10-14 15:41:30 -0700195 Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/",
196 std::string())
197 {
198 entityPrivileges = {
199 {boost::beast::http::verb::get, {{"Login"}}},
200 {boost::beast::http::verb::head, {{"Login"}}},
201 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
202 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
203 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
204 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
205 }
206
207 private:
208 /**
209 * Functions triggers appropriate requests on DBus
210 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500211 void doGet(crow::Response& res, const crow::Request& req,
212 const std::vector<std::string>& params) override
Jason M. Billsdede6a92019-10-14 15:41:30 -0700213 {
214 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
215 if (params.size() != 1)
216 {
217 messages::internalError(asyncResp->res);
218 return;
219 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500220 const std::string& device = params[0];
Jason M. Billsdede6a92019-10-14 15:41:30 -0700221 asyncResp->res.jsonValue = {
222 {"@odata.type", "#PCIeFunctionCollection.PCIeFunctionCollection"},
Jason M. Billsdede6a92019-10-14 15:41:30 -0700223 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + device +
224 "/PCIeFunctions"},
225 {"Name", "PCIe Function Collection"},
226 {"Description",
227 "Collection of PCIe Functions for PCIe Device " + device}};
228
229 auto getPCIeDeviceCallback =
230 [asyncResp,
231 device](const boost::system::error_code ec,
Patrick Williams19bd78d2020-05-13 17:38:24 -0500232 boost::container::flat_map<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500233 std::variant<std::string>>&
234 pcieDevProperties) {
Jason M. Billsdede6a92019-10-14 15:41:30 -0700235 if (ec)
236 {
237 BMCWEB_LOG_DEBUG
238 << "failed to get PCIe Device properties ec: "
239 << ec.value() << ": " << ec.message();
240 if (ec.value() ==
241 boost::system::linux_error::bad_request_descriptor)
242 {
243 messages::resourceNotFound(asyncResp->res, "PCIeDevice",
244 device);
245 }
246 else
247 {
248 messages::internalError(asyncResp->res);
249 }
250 return;
251 }
252
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500253 nlohmann::json& pcieFunctionList =
Jason M. Billsdede6a92019-10-14 15:41:30 -0700254 asyncResp->res.jsonValue["Members"];
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800255 pcieFunctionList = nlohmann::json::array();
256 static constexpr const int maxPciFunctionNum = 8;
257 for (int functionNum = 0; functionNum < maxPciFunctionNum;
258 functionNum++)
259 {
260 // Check if this function exists by looking for a device ID
261 std::string devIDProperty =
262 "Function" + std::to_string(functionNum) + "DeviceId";
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500263 std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500264 &pcieDevProperties[devIDProperty]);
Jason M. Billsdede6a92019-10-14 15:41:30 -0700265 if (property && !property->empty())
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800266 {
267 pcieFunctionList.push_back(
268 {{"@odata.id",
269 "/redfish/v1/Systems/system/PCIeDevices/" +
270 device + "/PCIeFunctions/" +
271 std::to_string(functionNum)}});
272 }
273 }
Jason M. Billsdede6a92019-10-14 15:41:30 -0700274 asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800275 pcieFunctionList.size();
276 };
277 std::string escapedPath = std::string(pciePath) + "/" + device;
278 dbus::utility::escapePathForDbus(escapedPath);
279 crow::connections::systemBus->async_method_call(
280 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
281 "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
282 }
283};
284
285class SystemPCIeFunction : public Node
286{
287 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700288 SystemPCIeFunction(App& app) :
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800289 Node(
290 app,
291 "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/",
292 std::string(), std::string())
293 {
294 entityPrivileges = {
295 {boost::beast::http::verb::get, {{"Login"}}},
296 {boost::beast::http::verb::head, {{"Login"}}},
297 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
298 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
299 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
300 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
301 }
302
303 private:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500304 void doGet(crow::Response& res, const crow::Request& req,
305 const std::vector<std::string>& params) override
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800306 {
307 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
308 if (params.size() != 2)
309 {
310 messages::internalError(asyncResp->res);
311 return;
312 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500313 const std::string& device = params[0];
314 const std::string& function = params[1];
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800315
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500316 auto getPCIeDeviceCallback = [asyncResp, device, function](
317 const boost::system::error_code ec,
318 boost::container::flat_map<
319 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 std::variant<std::string>>&
321 pcieDevProperties) {
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500322 if (ec)
323 {
324 BMCWEB_LOG_DEBUG
325 << "failed to get PCIe Device properties ec: " << ec.value()
326 << ": " << ec.message();
327 if (ec.value() ==
328 boost::system::linux_error::bad_request_descriptor)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800329 {
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500330 messages::resourceNotFound(asyncResp->res, "PCIeDevice",
331 device);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800332 }
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500333 else
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800334 {
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500335 messages::internalError(asyncResp->res);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800336 }
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500337 return;
338 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800339
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500340 // Check if this function exists by looking for a device ID
341 std::string devIDProperty = "Function" + function + "DeviceId";
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500342 if (std::string* property =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500343 std::get_if<std::string>(&pcieDevProperties[devIDProperty]);
344 property && property->empty())
345 {
346 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
347 function);
348 return;
349 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800350
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500351 asyncResp->res.jsonValue = {
352 {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
353 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
354 device + "/PCIeFunctions/" + function},
355 {"Name", "PCIe Function"},
356 {"Id", function},
357 {"FunctionId", std::stoi(function)},
358 {"Links",
359 {{"PCIeDevice",
360 {{"@odata.id",
361 "/redfish/v1/Systems/system/PCIeDevices/" + device}}}}}};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800362
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500363 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500364 &pcieDevProperties["Function" + function + "DeviceId"]);
365 property)
366 {
367 asyncResp->res.jsonValue["DeviceId"] = *property;
368 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800369
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500370 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500371 &pcieDevProperties["Function" + function + "VendorId"]);
372 property)
373 {
374 asyncResp->res.jsonValue["VendorId"] = *property;
375 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800376
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500377 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500378 &pcieDevProperties["Function" + function + "FunctionType"]);
379 property)
380 {
381 asyncResp->res.jsonValue["FunctionType"] = *property;
382 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800383
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500384 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500385 &pcieDevProperties["Function" + function + "DeviceClass"]);
386 property)
387 {
388 asyncResp->res.jsonValue["DeviceClass"] = *property;
389 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800390
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500391 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500392 &pcieDevProperties["Function" + function + "ClassCode"]);
393 property)
394 {
395 asyncResp->res.jsonValue["ClassCode"] = *property;
396 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800397
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500398 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500399 &pcieDevProperties["Function" + function + "RevisionId"]);
400 property)
401 {
402 asyncResp->res.jsonValue["RevisionId"] = *property;
403 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800404
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500405 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500406 &pcieDevProperties["Function" + function + "SubsystemId"]);
407 property)
408 {
409 asyncResp->res.jsonValue["SubsystemId"] = *property;
410 }
411
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500412 if (std::string* property = std::get_if<std::string>(
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500413 &pcieDevProperties["Function" + function +
414 "SubsystemVendorId"]);
415 property)
416 {
417 asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
418 }
419 };
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800420 std::string escapedPath = std::string(pciePath) + "/" + device;
421 dbus::utility::escapePathForDbus(escapedPath);
422 crow::connections::systemBus->async_method_call(
423 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
424 "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
425 }
426};
427
428} // namespace redfish