blob: e53443404f8cfaf6571689d5e0020d498e2393a6 [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
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080020#include <boost/system/linux_error.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070021#include <registries/privilege_registry.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080022
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
Ed Tanousb5a76932020-09-29 16:16:58 -070031static inline void
zhanghch058d1b46d2021-04-01 11:18:24 +080032 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousb5a76932020-09-29 16:16:58 -070033 const std::string& name)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080034{
Jason M. Billsadbe1922019-10-14 15:44:35 -070035 auto getPCIeMapCallback = [asyncResp, name](
36 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050037 std::vector<std::string>& pcieDevicePaths) {
Jason M. Billsadbe1922019-10-14 15:44:35 -070038 if (ec)
39 {
40 BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
41 << ec.message();
42 // Not an error, system just doesn't have PCIe info
43 return;
44 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -050045 nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
Jason M. Billsadbe1922019-10-14 15:44:35 -070046 pcieDeviceList = nlohmann::json::array();
Gunnar Mills1214b7e2020-06-04 10:11:30 -050047 for (const std::string& pcieDevicePath : pcieDevicePaths)
Jason M. Billsadbe1922019-10-14 15:44:35 -070048 {
Ed Tanous3174e4d2020-10-07 11:41:22 -070049 size_t devStart = pcieDevicePath.rfind('/');
Jason M. Billsadbe1922019-10-14 15:44:35 -070050 if (devStart == std::string::npos)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080051 {
Jason M. Billsadbe1922019-10-14 15:44:35 -070052 continue;
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080053 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080054
Jason M. Billsadbe1922019-10-14 15:44:35 -070055 std::string devName = pcieDevicePath.substr(devStart + 1);
56 if (devName.empty())
57 {
58 continue;
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080059 }
Jason M. Billsadbe1922019-10-14 15:44:35 -070060 pcieDeviceList.push_back(
61 {{"@odata.id",
62 "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
63 }
64 asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
65 };
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080066 crow::connections::systemBus->async_method_call(
67 std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
68 "/xyz/openbmc_project/object_mapper",
69 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
70 std::string(pciePath) + "/", 1, std::array<std::string, 0>());
71}
72
John Edward Broadbent7e860f12021-04-08 15:57:16 -070073inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -070074{
Jason M. Billsadbe1922019-10-14 15:44:35 -070075 /**
76 * Functions triggers appropriate requests on DBus
77 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -070078 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -070079 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -070080 .methods(boost::beast::http::verb::get)(
81 [](const crow::Request&,
82 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Jason M. Billsadbe1922019-10-14 15:44:35 -070083
John Edward Broadbent7e860f12021-04-08 15:57:16 -070084 {
85 asyncResp->res.jsonValue = {
86 {"@odata.type",
87 "#PCIeDeviceCollection.PCIeDeviceCollection"},
88 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
89 {"Name", "PCIe Device Collection"},
90 {"Description", "Collection of PCIe Devices"},
91 {"Members", nlohmann::json::array()},
92 {"Members@odata.count", 0}};
93 getPCIeDeviceList(asyncResp, "Members");
94 });
95}
96
97inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080098{
John Edward Broadbent7e860f12021-04-08 15:57:16 -070099 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700100 .privileges(redfish::privileges::getPCIeDevice)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700101 .methods(boost::beast::http::verb::get)(
102 [](const crow::Request&,
103 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
104 const std::string& device)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800105
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700106 {
107 auto getPCIeDeviceCallback = [asyncResp, device](
108 const boost::system::error_code
109 ec,
110 boost::container::flat_map<
111 std::string,
112 std::variant<std::string>>&
113 pcieDevProperties) {
114 if (ec)
115 {
116 BMCWEB_LOG_DEBUG
117 << "failed to get PCIe Device properties ec: "
118 << ec.value() << ": " << ec.message();
119 if (ec.value() ==
120 boost::system::linux_error::bad_request_descriptor)
121 {
122 messages::resourceNotFound(asyncResp->res,
123 "PCIeDevice", device);
124 }
125 else
126 {
127 messages::internalError(asyncResp->res);
128 }
129 return;
130 }
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800131
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700132 asyncResp->res.jsonValue = {
133 {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
134 {"@odata.id",
135 "/redfish/v1/Systems/system/PCIeDevices/" + device},
136 {"Name", "PCIe Device"},
137 {"Id", device}};
138
139 if (std::string* property = std::get_if<std::string>(
140 &pcieDevProperties["Manufacturer"]);
141 property)
142 {
143 asyncResp->res.jsonValue["Manufacturer"] = *property;
144 }
145
146 if (std::string* property = std::get_if<std::string>(
147 &pcieDevProperties["DeviceType"]);
148 property)
149 {
150 asyncResp->res.jsonValue["DeviceType"] = *property;
151 }
152
153 asyncResp->res.jsonValue["PCIeFunctions"] = {
154 {"@odata.id",
155 "/redfish/v1/Systems/system/PCIeDevices/" + device +
156 "/PCIeFunctions"}};
157 };
158 std::string escapedPath = std::string(pciePath) + "/" + device;
159 dbus::utility::escapePathForDbus(escapedPath);
160 crow::connections::systemBus->async_method_call(
161 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
162 "org.freedesktop.DBus.Properties", "GetAll",
163 pcieDeviceInterface);
164 });
165}
166
167inline void requestRoutesSystemPCIeFunctionCollection(App& app)
168{
169 /**
170 * Functions triggers appropriate requests on DBus
171 */
172 BMCWEB_ROUTE(app,
173 "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700174 .privileges(redfish::privileges::getPCIeFunctionCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700175 .methods(boost::beast::http::verb::get)(
176 [](const crow::Request&,
177 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
178 const std::string& device)
179
180 {
181 asyncResp->res.jsonValue = {
182 {"@odata.type",
183 "#PCIeFunctionCollection.PCIeFunctionCollection"},
184 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
185 device + "/PCIeFunctions"},
186 {"Name", "PCIe Function Collection"},
187 {"Description",
188 "Collection of PCIe Functions for PCIe Device " + device}};
189
190 auto getPCIeDeviceCallback = [asyncResp, device](
191 const boost::system::error_code
192 ec,
193 boost::container::flat_map<
194 std::string,
195 std::variant<std::string>>&
196 pcieDevProperties) {
197 if (ec)
198 {
199 BMCWEB_LOG_DEBUG
200 << "failed to get PCIe Device properties ec: "
201 << ec.value() << ": " << ec.message();
202 if (ec.value() ==
203 boost::system::linux_error::bad_request_descriptor)
204 {
205 messages::resourceNotFound(asyncResp->res,
206 "PCIeDevice", device);
207 }
208 else
209 {
210 messages::internalError(asyncResp->res);
211 }
212 return;
213 }
214
215 nlohmann::json& pcieFunctionList =
216 asyncResp->res.jsonValue["Members"];
217 pcieFunctionList = nlohmann::json::array();
218 static constexpr const int maxPciFunctionNum = 8;
219 for (int functionNum = 0; functionNum < maxPciFunctionNum;
220 functionNum++)
221 {
222 // Check if this function exists by looking for a device
223 // ID
224 std::string devIDProperty =
225 "Function" + std::to_string(functionNum) +
226 "DeviceId";
227 std::string* property = std::get_if<std::string>(
228 &pcieDevProperties[devIDProperty]);
229 if (property && !property->empty())
230 {
231 pcieFunctionList.push_back(
232 {{"@odata.id",
233 "/redfish/v1/Systems/system/PCIeDevices/" +
234 device + "/PCIeFunctions/" +
235 std::to_string(functionNum)}});
236 }
237 }
238 asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
239 pcieFunctionList.size();
240 };
241 std::string escapedPath = std::string(pciePath) + "/" + device;
242 dbus::utility::escapePathForDbus(escapedPath);
243 crow::connections::systemBus->async_method_call(
244 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
245 "org.freedesktop.DBus.Properties", "GetAll",
246 pcieDeviceInterface);
247 });
248}
249
250inline void requestRoutesSystemPCIeFunction(App& app)
251{
252 BMCWEB_ROUTE(
253 app,
254 "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700255 .privileges(redfish::privileges::getPCIeFunction)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700256 .methods(
257 boost::beast::http::verb::get)([](const crow::Request&,
258 const std::shared_ptr<
259 bmcweb::AsyncResp>& asyncResp,
260 const std::string& device,
261 const std::string& function) {
262 auto getPCIeDeviceCallback = [asyncResp, device, function](
263 const boost::system::error_code ec,
264 boost::container::flat_map<
265 std::string,
266 std::variant<std::string>>&
267 pcieDevProperties) {
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800268 if (ec)
269 {
270 BMCWEB_LOG_DEBUG
271 << "failed to get PCIe Device properties ec: "
Ed Tanous271584a2019-07-09 16:24:22 -0700272 << ec.value() << ": " << ec.message();
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800273 if (ec.value() ==
274 boost::system::linux_error::bad_request_descriptor)
275 {
276 messages::resourceNotFound(asyncResp->res, "PCIeDevice",
277 device);
278 }
279 else
280 {
281 messages::internalError(asyncResp->res);
282 }
283 return;
284 }
285
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700286 // Check if this function exists by looking for a device ID
287 std::string devIDProperty = "Function" + function + "DeviceId";
288 if (std::string* property = std::get_if<std::string>(
289 &pcieDevProperties[devIDProperty]);
290 property && property->empty())
291 {
292 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
293 function);
294 return;
295 }
296
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800297 asyncResp->res.jsonValue = {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700298 {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
Jason M. Billsdede6a92019-10-14 15:41:30 -0700299 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700300 device + "/PCIeFunctions/" + function},
301 {"Name", "PCIe Function"},
302 {"Id", function},
303 {"FunctionId", std::stoi(function)},
304 {"Links",
305 {{"PCIeDevice",
306 {{"@odata.id",
307 "/redfish/v1/Systems/system/PCIeDevices/" +
308 device}}}}}};
309
310 if (std::string* property = std::get_if<std::string>(
311 &pcieDevProperties["Function" + function + "DeviceId"]);
312 property)
313 {
314 asyncResp->res.jsonValue["DeviceId"] = *property;
315 }
316
317 if (std::string* property = std::get_if<std::string>(
318 &pcieDevProperties["Function" + function + "VendorId"]);
319 property)
320 {
321 asyncResp->res.jsonValue["VendorId"] = *property;
322 }
323
324 if (std::string* property = std::get_if<std::string>(
325 &pcieDevProperties["Function" + function +
326 "FunctionType"]);
327 property)
328 {
329 asyncResp->res.jsonValue["FunctionType"] = *property;
330 }
331
332 if (std::string* property = std::get_if<std::string>(
333 &pcieDevProperties["Function" + function +
334 "DeviceClass"]);
335 property)
336 {
337 asyncResp->res.jsonValue["DeviceClass"] = *property;
338 }
339
340 if (std::string* property = std::get_if<std::string>(
341 &pcieDevProperties["Function" + function +
342 "ClassCode"]);
343 property)
344 {
345 asyncResp->res.jsonValue["ClassCode"] = *property;
346 }
347
348 if (std::string* property = std::get_if<std::string>(
349 &pcieDevProperties["Function" + function +
350 "RevisionId"]);
351 property)
352 {
353 asyncResp->res.jsonValue["RevisionId"] = *property;
354 }
355
356 if (std::string* property = std::get_if<std::string>(
357 &pcieDevProperties["Function" + function +
358 "SubsystemId"]);
359 property)
360 {
361 asyncResp->res.jsonValue["SubsystemId"] = *property;
362 }
363
364 if (std::string* property = std::get_if<std::string>(
365 &pcieDevProperties["Function" + function +
366 "SubsystemVendorId"]);
367 property)
368 {
369 asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
370 }
Jason M. Billsdede6a92019-10-14 15:41:30 -0700371 };
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700372 std::string escapedPath = std::string(pciePath) + "/" + device;
373 dbus::utility::escapePathForDbus(escapedPath);
374 crow::connections::systemBus->async_method_call(
375 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
376 "org.freedesktop.DBus.Properties", "GetAll",
377 pcieDeviceInterface);
378 });
379}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800380
381} // namespace redfish