blob: bfdd04114cdff1a4eded1948342549fbcccc7391 [file] [log] [blame]
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001/*
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#pragma once
17
James Feist35e257a2020-06-05 13:30:51 -070018#include "health.hpp"
19
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020020#include <boost/container/flat_map.hpp>
21#include <node.hpp>
22#include <utils/json_utils.hpp>
23
24namespace redfish
25{
26
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060027using InterfacesProperties = boost::container::flat_map<
28 std::string,
29 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>>;
30
Ed Tanous029573d2019-02-01 10:57:49 -080031void getResourceList(std::shared_ptr<AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032 const std::string& subclass,
33 const std::vector<const char*>& collectionName)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020034{
35 BMCWEB_LOG_DEBUG << "Get available system cpu/mem resources.";
36 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -080037 [subclass, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020038 const boost::system::error_code ec,
39 const boost::container::flat_map<
40 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -050041 std::string, std::vector<std::string>>>&
42 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020043 if (ec)
44 {
45 BMCWEB_LOG_DEBUG << "DBUS response error";
46 messages::internalError(aResp->res);
47 return;
48 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -050049 nlohmann::json& members = aResp->res.jsonValue["Members"];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020050 members = nlohmann::json::array();
51
Gunnar Mills1214b7e2020-06-04 10:11:30 -050052 for (const auto& object : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020053 {
54 auto iter = object.first.rfind("/");
55 if ((iter != std::string::npos) && (iter < object.first.size()))
56 {
57 members.push_back(
Ed Tanous029573d2019-02-01 10:57:49 -080058 {{"@odata.id", "/redfish/v1/Systems/system/" +
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020059 subclass + "/" +
60 object.first.substr(iter + 1)}});
61 }
62 }
63 aResp->res.jsonValue["Members@odata.count"] = members.size();
64 },
65 "xyz.openbmc_project.ObjectMapper",
66 "/xyz/openbmc_project/object_mapper",
67 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -070068 "/xyz/openbmc_project/inventory", 0, collectionName);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020069}
70
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060071void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050072 const InterfacesProperties& cpuInterfacesProperties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020073{
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060074 BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020075
Gunnar Mills1214b7e2020-06-04 10:11:30 -050076 const bool* present = nullptr;
77 const bool* functional = nullptr;
78 for (const auto& interface : cpuInterfacesProperties)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060079 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050080 for (const auto& property : interface.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060081 {
82 if (property.first == "ProcessorCoreCount")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020083 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050084 const uint16_t* coresCount =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060085 std::get_if<uint16_t>(&property.second);
Ed Tanous883b3112018-12-06 16:13:35 -080086 if (coresCount == nullptr)
87 {
88 // Important property not in desired type
89 messages::internalError(aResp->res);
90 return;
91 }
92 if (*coresCount == 0)
93 {
94 // Slot is not populated, set status end return
95 aResp->res.jsonValue["Status"]["State"] = "Absent";
96 aResp->res.jsonValue["Status"]["Health"] = "OK";
97 // HTTP Code will be set up automatically, just return
98 return;
99 }
100
101 aResp->res.jsonValue["TotalCores"] = *coresCount;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200102 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600103 else if (property.first == "ProcessorType")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200104 {
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600105 aResp->res.jsonValue["Name"] = property.second;
106 }
107 else if (property.first == "Manufacturer")
108 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109 const std::string* value =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600110 std::get_if<std::string>(&property.second);
111 if (value != nullptr)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200112 {
113 aResp->res.jsonValue["Manufacturer"] = property.second;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600114 // Otherwise would be unexpected.
115 if (value->find("Intel") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200116 {
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600117 aResp->res.jsonValue["ProcessorArchitecture"] = "x86";
118 aResp->res.jsonValue["InstructionSet"] = "x86-64";
119 }
120 else if (value->find("IBM") != std::string::npos)
121 {
122 aResp->res.jsonValue["ProcessorArchitecture"] = "Power";
123 aResp->res.jsonValue["InstructionSet"] = "PowerISA";
124 }
125 }
126 }
127 else if (property.first == "ProcessorMaxSpeed")
128 {
129 aResp->res.jsonValue["MaxSpeedMHz"] = property.second;
130 }
131 else if (property.first == "ProcessorThreadCount")
132 {
133 aResp->res.jsonValue["TotalThreads"] = property.second;
134 }
135 else if (property.first == "Model")
136 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500137 const std::string* value =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600138 std::get_if<std::string>(&property.second);
139 if (value != nullptr)
140 {
141 aResp->res.jsonValue["Model"] = *value;
142 }
143 }
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600144 else if (property.first == "PartNumber")
145 {
146 aResp->res.jsonValue["PartNumber"] = property.second;
147 }
148 else if (property.first == "SerialNumber")
149 {
150 aResp->res.jsonValue["SerialNumber"] = property.second;
151 }
152 else if (property.first == "Version")
153 {
154 aResp->res.jsonValue["Version"] = property.second;
155 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600156 else if (property.first == "Present")
157 {
158 present = std::get_if<bool>(&property.second);
159 }
160 else if (property.first == "Functional")
161 {
162 functional = std::get_if<bool>(&property.second);
163 }
164 }
165 }
166
167 if ((present == nullptr) || (functional == nullptr))
168 {
169 // Important property not in desired type
170 messages::internalError(aResp->res);
171 return;
172 }
173
174 if (*present == false)
175 {
176 aResp->res.jsonValue["Status"]["State"] = "Absent";
177 aResp->res.jsonValue["Status"]["Health"] = "OK";
178 }
179 else
180 {
181 aResp->res.jsonValue["Status"]["State"] = "Enabled";
182 if (*functional == true)
183 {
184 aResp->res.jsonValue["Status"]["Health"] = "OK";
185 }
186 else
187 {
188 aResp->res.jsonValue["Status"]["Health"] = "Critical";
189 }
190 }
191
192 return;
193}
194
195void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500196 const std::string& cpuId, const std::string& service,
197 const std::string& objPath)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600198{
199 BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
200
201 crow::connections::systemBus->async_method_call(
202 [cpuId, service, objPath, aResp{std::move(aResp)}](
203 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500204 const dbus::utility::ManagedObjectType& dbusData) {
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600205 if (ec)
206 {
207 BMCWEB_LOG_DEBUG << "DBUS response error";
208 messages::internalError(aResp->res);
209 return;
210 }
211 aResp->res.jsonValue["Id"] = cpuId;
212 aResp->res.jsonValue["Name"] = "Processor";
213 aResp->res.jsonValue["ProcessorType"] = "CPU";
214
215 std::string corePath = objPath + "/core";
216 size_t totalCores = 0;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500217 for (const auto& object : dbusData)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600218 {
219 if (object.first.str == objPath)
220 {
221 getCpuDataByInterface(aResp, object.second);
222 }
223 else if (boost::starts_with(object.first.str, corePath))
224 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500225 for (const auto& interface : object.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600226 {
227 if (interface.first ==
228 "xyz.openbmc_project.Inventory.Item")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200229 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500230 for (const auto& property : interface.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600231 {
232 if (property.first == "Present")
233 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500234 const bool* present =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600235 std::get_if<bool>(&property.second);
236 if (present != nullptr)
237 {
238 if (*present == true)
239 {
240 totalCores++;
241 }
242 }
243 }
244 }
Gunnar Millsb957ba52019-01-31 15:58:15 -0600245 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200246 }
247 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200248 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600249 // In getCpuDataByInterface(), state and health are set
250 // based on the present and functional status. If core
251 // count is zero, then it has a higher precedence.
252 if (totalCores == 0)
253 {
254 // Slot is not populated, set status end return
255 aResp->res.jsonValue["Status"]["State"] = "Absent";
256 aResp->res.jsonValue["Status"]["Health"] = "OK";
257 }
258 aResp->res.jsonValue["TotalCores"] = totalCores;
259 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200260 },
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600261 service, "/xyz/openbmc_project/inventory",
262 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200263}
264
Zhikui Ren5e54a362020-07-13 15:31:38 -0700265void getCpuAssetData(std::shared_ptr<AsyncResp> aResp,
266 const std::string& service, const std::string& objPath)
267{
268 BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
269 crow::connections::systemBus->async_method_call(
270 [objPath, aResp{std::move(aResp)}](
271 const boost::system::error_code ec,
272 const boost::container::flat_map<
273 std::string, std::variant<std::string, uint32_t, uint16_t,
274 bool>>& properties) {
275 if (ec)
276 {
277 BMCWEB_LOG_DEBUG << "DBUS response error";
278 messages::internalError(aResp->res);
279 return;
280 }
281
282 for (const auto& property : properties)
283 {
284 if (property.first == "SerialNumber")
285 {
286 const std::string* sn =
287 std::get_if<std::string>(&property.second);
288 if (sn != nullptr)
289 {
290 aResp->res.jsonValue["SerialNumber"] = *sn;
291 }
292 }
293 else if (property.first == "Model")
294 {
295 const std::string* model =
296 std::get_if<std::string>(&property.second);
297 if (model != nullptr)
298 {
299 aResp->res.jsonValue["Model"] = *model;
300 }
301 }
302 }
303 },
304 service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
305 "xyz.openbmc_project.Inventory.Decorator.Asset");
306}
307
Alpana Kumari32bee762019-04-25 04:47:57 -0500308void getAcceleratorDataByService(std::shared_ptr<AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500309 const std::string& acclrtrId,
310 const std::string& service,
311 const std::string& objPath)
Alpana Kumari32bee762019-04-25 04:47:57 -0500312{
313 BMCWEB_LOG_DEBUG
314 << "Get available system Accelerator resources by service.";
315 crow::connections::systemBus->async_method_call(
316 [acclrtrId, aResp{std::move(aResp)}](
317 const boost::system::error_code ec,
318 const boost::container::flat_map<
Santosh Puranik94e1b822019-07-24 04:48:32 -0500319 std::string, std::variant<std::string, uint32_t, uint16_t,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 bool>>& properties) {
Alpana Kumari32bee762019-04-25 04:47:57 -0500321 if (ec)
322 {
323 BMCWEB_LOG_DEBUG << "DBUS response error";
324 messages::internalError(aResp->res);
325 return;
326 }
327 aResp->res.jsonValue["Id"] = acclrtrId;
328 aResp->res.jsonValue["Name"] = "Processor";
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500329 const bool* accPresent = nullptr;
330 const bool* accFunctional = nullptr;
Alpana Kumari32bee762019-04-25 04:47:57 -0500331
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500332 for (const auto& property : properties)
Alpana Kumari32bee762019-04-25 04:47:57 -0500333 {
334 if (property.first == "Functional")
335 {
Santosh Puranik94e1b822019-07-24 04:48:32 -0500336 accFunctional = std::get_if<bool>(&property.second);
Alpana Kumari32bee762019-04-25 04:47:57 -0500337 }
338 else if (property.first == "Present")
339 {
Santosh Puranik94e1b822019-07-24 04:48:32 -0500340 accPresent = std::get_if<bool>(&property.second);
Alpana Kumari32bee762019-04-25 04:47:57 -0500341 }
342 }
343
Alpana Kumari657877c2020-02-24 02:24:07 -0600344 if ((accPresent != nullptr) && (*accPresent == false))
Alpana Kumari32bee762019-04-25 04:47:57 -0500345 {
Alpana Kumari657877c2020-02-24 02:24:07 -0600346 aResp->res.jsonValue["Status"]["State"] = "Absent";
347 aResp->res.jsonValue["Status"]["Health"] = "OK";
Alpana Kumari32bee762019-04-25 04:47:57 -0500348 }
349 else
350 {
Alpana Kumari657877c2020-02-24 02:24:07 -0600351 aResp->res.jsonValue["Status"]["State"] = "Enabled";
352
353 if ((accFunctional != nullptr) && (*accFunctional == false))
354 {
355 aResp->res.jsonValue["Status"]["Health"] = "Critical";
356 }
357 else
358 {
359 aResp->res.jsonValue["Status"]["Health"] = "OK";
360 }
Alpana Kumari32bee762019-04-25 04:47:57 -0500361 }
Alpana Kumari32bee762019-04-25 04:47:57 -0500362 aResp->res.jsonValue["ProcessorType"] = "Accelerator";
363 },
364 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
365}
366
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500367void getCpuData(std::shared_ptr<AsyncResp> aResp, const std::string& cpuId,
368 const std::vector<const char*> inventoryItems)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200369{
370 BMCWEB_LOG_DEBUG << "Get available system cpu resources.";
Alpana Kumari32bee762019-04-25 04:47:57 -0500371
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200372 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800373 [cpuId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200374 const boost::system::error_code ec,
375 const boost::container::flat_map<
376 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500377 std::string, std::vector<std::string>>>&
378 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200379 if (ec)
380 {
381 BMCWEB_LOG_DEBUG << "DBUS response error";
382 messages::internalError(aResp->res);
383 return;
384 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500385 for (const auto& object : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200386 {
387 if (boost::ends_with(object.first, cpuId))
388 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500389 for (const auto& service : object.second)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200390 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500391 for (const auto& inventory : service.second)
Zhikui Ren5e54a362020-07-13 15:31:38 -0700392 {
393 if (inventory == "xyz.openbmc_project."
394 "Inventory.Decorator.Asset")
395 {
396 getCpuAssetData(aResp, service.first,
397 object.first);
398 }
399 else if (inventory ==
400 "xyz.openbmc_project.Inventory.Item.Cpu")
Alpana Kumari32bee762019-04-25 04:47:57 -0500401 {
402 getCpuDataByService(aResp, cpuId, service.first,
403 object.first);
404 }
405 else if (inventory == "xyz.openbmc_project."
406 "Inventory.Item.Accelerator")
407 {
408 getAcceleratorDataByService(
409 aResp, cpuId, service.first, object.first);
410 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700411 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200412 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700413 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200414 }
415 }
416 // Object not found
417 messages::resourceNotFound(aResp->res, "Processor", cpuId);
418 return;
419 },
420 "xyz.openbmc_project.ObjectMapper",
421 "/xyz/openbmc_project/object_mapper",
422 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700423 "/xyz/openbmc_project/inventory", 0, inventoryItems);
424}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200425
426void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500427 const std::string& dimmId, const std::string& service,
428 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200429{
James Feist35e257a2020-06-05 13:30:51 -0700430 auto health = std::make_shared<HealthPopulate>(aResp);
431 health->selfPath = objPath;
432 health->populate();
433
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200434 BMCWEB_LOG_DEBUG << "Get available system components.";
435 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800436 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200437 const boost::system::error_code ec,
438 const boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500439 std::string, std::variant<std::string, uint32_t, uint16_t>>&
440 properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200441 if (ec)
442 {
443 BMCWEB_LOG_DEBUG << "DBUS response error";
444 messages::internalError(aResp->res);
445
446 return;
447 }
448 aResp->res.jsonValue["Id"] = dimmId;
449 aResp->res.jsonValue["Name"] = "DIMM Slot";
450
451 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600452 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200453 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500454 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800455 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600456 if (memorySize == nullptr)
457 {
458 // Important property not in desired type
459 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200460
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600461 return;
462 }
463 if (*memorySize == 0)
464 {
465 // Slot is not populated, set status end return
466 aResp->res.jsonValue["Status"]["State"] = "Absent";
467 aResp->res.jsonValue["Status"]["Health"] = "OK";
468 // HTTP Code will be set up automatically, just return
469 return;
470 }
471 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200472 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200473 aResp->res.jsonValue["Status"]["State"] = "Enabled";
474 aResp->res.jsonValue["Status"]["Health"] = "OK";
475
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500476 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200477 {
478 if (property.first == "MemoryDataWidth")
479 {
480 aResp->res.jsonValue["DataWidthBits"] = property.second;
481 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530482 else if (property.first == "PartNumber")
483 {
484 aResp->res.jsonValue["PartNumber"] = property.second;
485 }
486 else if (property.first == "SerialNumber")
487 {
488 aResp->res.jsonValue["SerialNumber"] = property.second;
489 }
490 else if (property.first == "Manufacturer")
491 {
492 aResp->res.jsonValue["Manufacturer"] = property.second;
493 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200494 else if (property.first == "MemoryType")
495 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500496 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800497 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200498 if (value != nullptr)
499 {
500 aResp->res.jsonValue["MemoryDeviceType"] = *value;
501 if (boost::starts_with(*value, "DDR"))
502 {
503 aResp->res.jsonValue["MemoryType"] = "DRAM";
504 }
505 }
506 }
507 }
508 },
509 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
510}
511
James Feist45094ad2020-04-29 14:02:30 -0700512void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
513 const std::string& service, const std::string& path)
514{
515 crow::connections::systemBus->async_method_call(
516 [aResp{std::move(aResp)}](
517 const boost::system::error_code ec,
518 const boost::container::flat_map<
519 std::string, std::variant<std::string, uint64_t, uint32_t,
520 bool>>& properties) {
521 if (ec)
522 {
523 BMCWEB_LOG_DEBUG << "DBUS response error";
524 messages::internalError(aResp->res);
525
526 return;
527 }
528
529 nlohmann::json& partition =
530 aResp->res.jsonValue["Regions"].emplace_back(
531 nlohmann::json::object());
532 for (const auto& [key, val] : properties)
533 {
534 if (key == "MemoryClassification")
535 {
536 partition[key] = val;
537 }
538 else if (key == "OffsetInKiB")
539 {
540 const uint64_t* value = std::get_if<uint64_t>(&val);
541 if (value == nullptr)
542 {
543 messages::internalError(aResp->res);
544 BMCWEB_LOG_DEBUG
545 << "Invalid property type for OffsetInKiB";
546 continue;
547 }
548
549 partition["OffsetMiB"] = (*value >> 10);
550 }
551 else if (key == "PartitionId")
552 {
553 partition["RegionId"] = val;
554 }
555
556 else if (key == "PassphraseState")
557 {
558 partition["PassphraseEnabled"] = val;
559 }
560 else if (key == "SizeInKiB")
561 {
562 const uint64_t* value = std::get_if<uint64_t>(&val);
563 if (value == nullptr)
564 {
565 messages::internalError(aResp->res);
566 BMCWEB_LOG_DEBUG
567 << "Invalid property type for SizeInKiB";
568 continue;
569 }
570 partition["SizeMiB"] = (*value >> 10);
571 }
572 }
573 },
574
575 service, path, "org.freedesktop.DBus.Properties", "GetAll",
576 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
577}
578
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500579void getDimmData(std::shared_ptr<AsyncResp> aResp, const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200580{
581 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
582 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800583 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200584 const boost::system::error_code ec,
585 const boost::container::flat_map<
586 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500587 std::string, std::vector<std::string>>>&
588 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200589 if (ec)
590 {
591 BMCWEB_LOG_DEBUG << "DBUS response error";
592 messages::internalError(aResp->res);
593
594 return;
595 }
James Feist45094ad2020-04-29 14:02:30 -0700596 bool found = false;
597 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200598 {
James Feist45094ad2020-04-29 14:02:30 -0700599 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200600 {
James Feist45094ad2020-04-29 14:02:30 -0700601 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200602 {
James Feist45094ad2020-04-29 14:02:30 -0700603 if (!found &&
604 (std::find(
605 interfaces.begin(), interfaces.end(),
606 "xyz.openbmc_project.Inventory.Item.Dimm") !=
607 interfaces.end()))
608 {
609 getDimmDataByService(aResp, dimmId, service, path);
610 found = true;
611 }
612
613 // partitions are separate as there can be multiple per
614 // device, i.e.
615 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
616 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
617 if (std::find(interfaces.begin(), interfaces.end(),
618 "xyz.openbmc_project.Inventory.Item."
619 "PersistentMemory.Partition") !=
620 interfaces.end())
621 {
622 getDimmPartitionData(aResp, service, path);
623 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200624 }
625 }
626 }
627 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700628 if (!found)
629 {
630 messages::resourceNotFound(aResp->res, "Memory", dimmId);
631 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200632 return;
633 },
634 "xyz.openbmc_project.ObjectMapper",
635 "/xyz/openbmc_project/object_mapper",
636 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700637 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700638 std::array<const char*, 2>{
639 "xyz.openbmc_project.Inventory.Item.Dimm",
640 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700641}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200642
643class ProcessorCollection : public Node
644{
645 public:
646 /*
647 * Default Constructor
648 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500649 ProcessorCollection(CrowApp& app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800650 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200651 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200652 entityPrivileges = {
653 {boost::beast::http::verb::get, {{"Login"}}},
654 {boost::beast::http::verb::head, {{"Login"}}},
655 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
656 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
657 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
658 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
659 }
660
661 private:
662 /**
663 * Functions triggers appropriate requests on DBus
664 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500665 void doGet(crow::Response& res, const crow::Request& req,
666 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200667 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800668 res.jsonValue["@odata.type"] =
669 "#ProcessorCollection.ProcessorCollection";
670 res.jsonValue["Name"] = "Processor Collection";
Ed Tanous0f74e642018-11-12 15:17:05 -0800671
Ed Tanous029573d2019-02-01 10:57:49 -0800672 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200673 auto asyncResp = std::make_shared<AsyncResp>(res);
674
Ed Tanous029573d2019-02-01 10:57:49 -0800675 getResourceList(asyncResp, "Processors",
Alpana Kumari32bee762019-04-25 04:47:57 -0500676 {"xyz.openbmc_project.Inventory.Item.Cpu",
677 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200678 }
679};
680
681class Processor : public Node
682{
683 public:
684 /*
685 * Default Constructor
686 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500687 Processor(CrowApp& app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800688 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200689 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200690 entityPrivileges = {
691 {boost::beast::http::verb::get, {{"Login"}}},
692 {boost::beast::http::verb::head, {{"Login"}}},
693 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
694 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
695 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
696 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
697 }
698
699 private:
700 /**
701 * Functions triggers appropriate requests on DBus
702 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500703 void doGet(crow::Response& res, const crow::Request& req,
704 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200705 {
706 // Check if there is required param, truly entering this shall be
707 // impossible
708 if (params.size() != 1)
709 {
710 messages::internalError(res);
711
712 res.end();
713 return;
714 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500715 const std::string& processorId = params[0];
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600716 res.jsonValue["@odata.type"] = "#Processor.v1_7_0.Processor";
Ed Tanous029573d2019-02-01 10:57:49 -0800717 res.jsonValue["@odata.id"] =
Alpana Kumari32bee762019-04-25 04:47:57 -0500718 "/redfish/v1/Systems/system/Processors/" + processorId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200719
Ed Tanous029573d2019-02-01 10:57:49 -0800720 auto asyncResp = std::make_shared<AsyncResp>(res);
721
Alpana Kumari32bee762019-04-25 04:47:57 -0500722 getCpuData(asyncResp, processorId,
723 {"xyz.openbmc_project.Inventory.Item.Cpu",
Zhikui Ren5e54a362020-07-13 15:31:38 -0700724 "xyz.openbmc_project.Inventory.Decorator.Asset",
Alpana Kumari32bee762019-04-25 04:47:57 -0500725 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Ed Tanous029573d2019-02-01 10:57:49 -0800726 }
727};
728
729class MemoryCollection : public Node
730{
731 public:
732 /*
733 * Default Constructor
734 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500735 MemoryCollection(CrowApp& app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800736 Node(app, "/redfish/v1/Systems/system/Memory/")
737 {
738 entityPrivileges = {
739 {boost::beast::http::verb::get, {{"Login"}}},
740 {boost::beast::http::verb::head, {{"Login"}}},
741 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
742 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
743 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
744 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
745 }
746
747 private:
748 /**
749 * Functions triggers appropriate requests on DBus
750 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500751 void doGet(crow::Response& res, const crow::Request& req,
752 const std::vector<std::string>& params) override
Ed Tanous029573d2019-02-01 10:57:49 -0800753 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800754 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
755 res.jsonValue["Name"] = "Memory Module Collection";
Ed Tanous029573d2019-02-01 10:57:49 -0800756 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200757 auto asyncResp = std::make_shared<AsyncResp>(res);
758
Ed Tanous029573d2019-02-01 10:57:49 -0800759 getResourceList(asyncResp, "Memory",
Alpana Kumari32bee762019-04-25 04:47:57 -0500760 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200761 }
762};
763
764class Memory : public Node
765{
766 public:
767 /*
768 * Default Constructor
769 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500770 Memory(CrowApp& app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800771 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200772 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200773 entityPrivileges = {
774 {boost::beast::http::verb::get, {{"Login"}}},
775 {boost::beast::http::verb::head, {{"Login"}}},
776 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
777 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
778 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
779 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
780 }
781
782 private:
783 /**
784 * Functions triggers appropriate requests on DBus
785 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500786 void doGet(crow::Response& res, const crow::Request& req,
787 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200788 {
789 // Check if there is required param, truly entering this shall be
790 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -0800791 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200792 {
793 messages::internalError(res);
794 res.end();
795 return;
796 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500797 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200798
Rapkiewicz, Pawelbb3d9942018-11-22 10:59:11 +0100799 res.jsonValue["@odata.type"] = "#Memory.v1_6_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200800 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -0800801 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200802 auto asyncResp = std::make_shared<AsyncResp>(res);
803
Ed Tanous029573d2019-02-01 10:57:49 -0800804 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200805 }
806};
807
808} // namespace redfish